From 12172ff178b62b7c4d710ca1a54819a2b1d47a97 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 11 Dec 2009 18:08:30 +0000 Subject: thread-safe but lifetime-unsafe closures for passing closures around instead of sigc::slot, which is thread-unsafe but lifetime-safe (lifetime safe means that the slot is guaranteed to be safe to use no matter what the lifetime of the object to which it refers is) git-svn-id: svn://localhost/ardour2/branches/3.0@6349 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/pbd/pbd/closure.h | 120 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 libs/pbd/pbd/closure.h diff --git a/libs/pbd/pbd/closure.h b/libs/pbd/pbd/closure.h new file mode 100644 index 0000000000..f6c722a072 --- /dev/null +++ b/libs/pbd/pbd/closure.h @@ -0,0 +1,120 @@ +#ifndef __pbd_closure_h__ +#define __pbd_closure_h__ + +#include +#include +using std::cerr; + +namespace PBD { + +struct ClosureBaseImpl { + ClosureBaseImpl() { g_atomic_int_set (&_ref, 0); } + + ClosureBaseImpl* ref() { g_atomic_int_inc (&_ref); return this; } + void unref() { if (g_atomic_int_dec_and_test (&_ref)) delete this; } + + virtual void operator() () = 0; + +protected: + virtual ~ClosureBaseImpl() { cerr << "DBI @ " << this << " destroyed\n"; } + +private: + gint _ref; +}; + +struct Closure { + Closure () : impl (0) {} + Closure (ClosureBaseImpl* i) : impl (i->ref()) {} + Closure (const Closure& other) : impl (other.impl ? other.impl->ref() : 0) {} + + Closure& operator= (const Closure& other) { + if (&other == this) { + return *this; + } + if (impl) { + impl->unref(); + } + if (other.impl) { + impl = other.impl->ref(); + } else { + impl = 0; + } + return *this; + } + + virtual ~Closure () { if (impl) { impl->unref(); } } + + /* will crash if impl is unset */ + void operator() () { (*impl)(); } + +private: + ClosureBaseImpl* impl; +}; + +template +struct ClosureImpl0 : public ClosureBaseImpl { + ClosureImpl0 (T& obj, void (T::*m)()) + : object (obj), method (m) {} + void operator() () { (object.*method)(); } + private: + T& object; + void (T::*method)(); +}; + +template +struct ClosureImpl1 : public ClosureBaseImpl +{ + ClosureImpl1 (T& obj, void (T::*m)(A1), A1 arg) + : object (obj), method (m), arg1 (arg) {} + void operator() () { (object.*method) (arg1); } + + private: + T& object; + void (T::*method)(A1); + A1 arg1; +}; + +template +struct ClosureImpl2 : public ClosureBaseImpl +{ + ClosureImpl2 (T& obj, void (T::*m)( A1, A2), A1 arga, A2 argb) + : object (obj), method (m), arg1 (arga), arg2 (argb) {} + void operator() () { (object.*method) (arg1, arg2); } + + private: + T& object; + void (T::*method)(A1, A2); + A1 arg1; + A2 arg2; +}; + +template +struct ClosureImpl3 : public ClosureBaseImpl +{ + ClosureImpl3 (T& obj, void (T::*m)( A1, A2, A3), A1 arga, A2 argb, A3 argc) + : object (obj), method (m), arg1 (arga), arg2 (argb), arg3 (argc) {} + void operator() () { (object.*method) (arg1, arg2, arg3); } + + private: + T& object; + void (T::*method)(A1, A2, A3); + A1 arg1; + A2 arg2; + A3 arg3; +}; + +template +Closure closure (T& t, void (T::*m)()) {return Closure (new ClosureImpl0 (t,m)); } + +template +Closure closure (T& t, void (T::*m)(A), A a) { return Closure (new ClosureImpl1(t,m,a)); } + +template +Closure closure (T& t, void (T::*m)(A1,A2), A1 a1, A2 a2) { return Closure (new ClosureImpl2(t,m, a1, a2)); } + +template +Closure closure (T& t, void (T::*m)(A1, A2, A3), A1 a1, A2 a2, A3 a3) { return Closure (new ClosureImpl3(t,m , a1, a2, a3)); } + +} + +#endif /* __pbd_closure_h__ */ -- cgit v1.2.3