Dear All, I've been doing some experiments with cleaner destruction of objects in SWIG target languages with out-of-thread garbage collection. Unfortunately, I've not been able to come up with an automatic solution for the problem since encapsulated Observer/Observables relationships can cause problems just as well as top level Observers created in the target language. Therefore, one still has somehow go through the classes by hand identifying ones which cause problems and writing special destructors for them. Still, for completeness here are the patches describing what I've done. With these patches QuoteHandle destruction is I believe fully reliable. * Add an unregister function to the Handle class -- this is necessary so that the Observer relationship in the link can be removed before the destruction of the class begins: --- a/QuantLib/ql/handle.hpp +++ b/QuantLib/ql/handle.hpp @@ -49,6 +49,7 @@ bool empty() const { return !h_; } const boost::shared_ptr<T>& currentLink() const { return h_; } void update() { notifyObservers(); } + void unregister(void); private: boost::shared_ptr<T> h_; bool isObserver_; @@ -89,6 +90,8 @@ bool empty() const; //! allows registration as observable operator boost::shared_ptr<Observable>() const; + //! Unregister as observer + void unregister(void) {link_->unregister();} //! equality test template <class U> bool operator==(const Handle<U>& other) { return link_==other.link_; } @@ -134,6 +137,13 @@ } template <class T> + inline void Handle<T>::Link::unregister(void) { + if (h_ && isObserver_) + unregisterWith(h_); + isObserver_=false; + } + + template <class T> inline void Handle<T>::Link::linkTo(const boost::shared_ptr<T>& h, bool registerAsObserver) { if ((h != h_) || (isObserver_ != registerAsObserver)) { * Add a mutex on the observers_ data structure in the Observable class so that the integrity of this structure is maintained when one thread is modifying the structure while others are reading it (Thanks to Klaus Spanderen for pointing out this will be necessary) . Note that this will require QuantLib to be linked with boost threads library. --- a/QuantLib/ql/patterns/observable.hpp +++ b/QuantLib/ql/patterns/observable.hpp @@ -30,6 +30,7 @@ #include <ql/types.hpp> #include <boost/shared_ptr.hpp> +#include <boost/thread.hpp> #include <set> @@ -56,6 +57,7 @@ std::pair<iterator, bool> registerObserver(Observer*); Size unregisterObserver(Observer*); std::set<Observer*> observers_; + boost::mutex mx_observers_; }; //! Object that gets notified when a given observable changes @@ -108,14 +110,17 @@ inline std::pair<std::set<Observer*>::iterator, bool> Observable::registerObserver(Observer* o) { + boost::mutex::scoped_lock lock(mx_observers_); return observers_.insert(o); } inline Size Observable::unregisterObserver(Observer* o) { + boost::mutex::scoped_lock lock(mx_observers_); return observers_.erase(o); } inline void Observable::notifyObservers() { + boost::mutex::scoped_lock lock(mx_observers_); bool successful = true; std::string errMsg; for (iterator i=observers_.begin(); i!=observers_.end(); ++i) { * Illustration of how to add a specialised destructor (for Java in this case) which calls the unregister function to break Observer relationship before beginning the destruction of the class: --- a/QuantLib-SWIG/SWIG/marketelements.i +++ b/QuantLib-SWIG/SWIG/marketelements.i @@ -38,6 +38,22 @@ %template(Quote) boost::shared_ptr<Quote>; IsObservable(boost::shared_ptr<Quote>); +%typemap(javadestruct, + methodname="delete", + methodmodifiers="public synchronized") Handle<Quote> +{ + if (swigCPtr != 0) { + if (swigCMemOwn) { + unregister(); + swigCMemOwn = false; + $jnicall; + } + swigCPtr = 0; + } +} + + + %template(QuoteHandle) Handle<Quote>; IsObservable(Handle<Quote>); %template(RelinkableQuoteHandle) RelinkableHandle<Quote>; * Extend the SWIG interface to include the new unregister function: --- a/QuantLib-SWIG/SWIG/common.i +++ b/QuantLib-SWIG/SWIG/common.i @@ -99,6 +99,7 @@ #else bool empty(); #endif + void unregister(); }; template <class T> -- Bojan Nikolic || http://www.bnikolic.co.uk ------------------------------------------------------------------------------ This SF email is sponsosred by: Try Windows Azure free for 90 days Click Here http://p.sf.net/sfu/sfd2d-msazure _______________________________________________ QuantLib-dev mailing list [hidden email] https://lists.sourceforge.net/lists/listinfo/quantlib-dev |
Free forum by Nabble | Edit this page |