Posted by
Bojan Nikolic on
Mar 20, 2012; 10:35am
URL: http://quantlib.414.s1.nabble.com/Observer-pattern-and-destruction-during-update-tp9023.html
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