diff options
-rw-r--r-- | libs/pbd/pbd/signal.h.py | 232 | ||||
-rw-r--r-- | libs/pbd/pbd/signals.h | 421 | ||||
-rw-r--r-- | libs/pbd/wscript | 2 | ||||
-rw-r--r-- | wscript | 2 |
4 files changed, 62 insertions, 595 deletions
diff --git a/libs/pbd/pbd/signal.h.py b/libs/pbd/pbd/signal.h.py deleted file mode 100644 index 9997811c52..0000000000 --- a/libs/pbd/pbd/signal.h.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/python - -import sys - -if len(sys.argv) < 2: - print 'Syntax: %s <path>' % sys.argv[0] - sys.exit(1) - -f = open(sys.argv[1], 'w') - -print >>f,""" -/** THIS FILE IS AUTOGENERATED by signals.h.py: CHANGES WILL BE LOST */ - -#include <list> -#include <boost/function.hpp> -#include <boost/bind.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/enable_shared_from_this.hpp> -#include <boost/optional.hpp> -#include "pbd/stacktrace.h" - -namespace PBD { - -class Connection; - -class SignalBase -{ -public: - virtual ~SignalBase () {} - virtual void disconnect (boost::shared_ptr<Connection>) = 0; - -protected: - boost::mutex _mutex; -}; - -class Connection : public boost::enable_shared_from_this<Connection> -{ -public: - Connection (SignalBase* b) : _signal (b) {} - - void disconnect () - { - boost::mutex::scoped_lock lm (_mutex); - if (_signal) { - _signal->disconnect (shared_from_this ()); - } - } - - void signal_going_away () - { - boost::mutex::scoped_lock lm (_mutex); - _signal = 0; - } - -private: - boost::mutex _mutex; - SignalBase* _signal; -}; - -template<typename R> -class OptionalLastValue -{ -public: - typedef boost::optional<R> result_type; - - template <typename Iter> - result_type operator() (Iter first, Iter last) const { - result_type r; - while (first != last) { - r = *first; - ++first; - } - - return r; - } -}; -""" - -def comma_separated(n, prefix = ""): - r = "" - for i in range(0, len(n)): - if i > 0: - r += ", " - r += "%s%s" % (prefix, n[i]) - return r - -def simple_signal(f, n, v): - - An = [] - for i in range(0, n): - An.append("A%d" % (i + 1)) - - if v: - print >>f,"template <%s>" % comma_separated(An, "typename ") - print >>f,"class SimpleSignal%d<%s> : public SignalBase" % (n, comma_separated(["void"] + An)) - else: - print >>f,"template <%s>" % comma_separated(["R"] + An + ["C = OptionalLastValue<R> "], "typename ") - print >>f,"class SimpleSignal%d : public SignalBase" % n - - print >>f,"{" - print >>f,"public:" - print >>f,"" - if v: - print >>f,"\ttypedef boost::function<void(%s)> slot_function_type;" % comma_separated(An) - print >>f,"\ttypedef void result_type;" - else: - print >>f,"\ttypedef boost::function<R(%s)> slot_function_type;" % comma_separated(An) - print >>f,"\ttypedef boost::optional<R> result_type;" - - print >>f,"private:" - print >>f,"" - - print >>f,""" - typedef std::map<boost::shared_ptr<Connection>, slot_function_type> Slots; - Slots _slots; -""" - - print >>f,"public:" - print >>f,"" - print >>f,"\t~SimpleSignal%d ()" % n - - print >>f,""" - { - boost::mutex::scoped_lock lm (_mutex); -#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6)) - for (typename Slots::iterator i = _slots.begin(); i != _slots.end(); ++i) { -#else - for (Slots::iterator i = _slots.begin(); i != _slots.end(); ++i) { -#endif - i->first->signal_going_away (); - } - } - - boost::shared_ptr<Connection> connect (slot_function_type f) - { - boost::shared_ptr<Connection> c (new Connection (this)); - boost::mutex::scoped_lock lm (_mutex); - _slots[c] = f; - return c; - } -""" - - Anan = [] - for a in An: - Anan.append('%s %s' % (a, a.lower())) - - an = [] - for a in An: - an.append(a.lower()) - - if v: - print >>f,"\tvoid emit (%s)" % comma_separated(Anan) - else: - print >>f,"\ttypename C::result_type emit (%s)" % comma_separated(Anan) - print >>f,"\t{" - print >>f,"\t\tSlots s;" - print >>f,"\t\t{" - print >>f,"\t\t\tboost::mutex::scoped_lock lm (_mutex);" - print >>f,"\t\t\ts = _slots;" - print >>f,"\t\t}" - if not v: - print >>f,"\t\tstd::list<R> r;" - if n == 0 and v: - print >>f,""" -#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ >= 6)) - for (typename Slots::iterator i = s.begin(); i != s.end(); ++i) { -#else - for (Slots::iterator i = s.begin(); i != s.end(); ++i) { -#endif -""" - else: - print >>f,"\t\tfor (typename Slots::iterator i = s.begin(); i != s.end(); ++i) {" - - print >>f,""" - bool still_there = false; - { - boost::mutex::scoped_lock lm (_mutex); - still_there = _slots.find (i->first) != _slots.end (); - } - - if (still_there) {""" - if v: - print >>f,"\t\t\t\t(i->second)(%s);" % comma_separated(an) - else: - print >>f,"\t\t\t\tr.push_back ((i->second)(%s));" % comma_separated(an) - print >>f,"\t\t\t}" - print >>f,"\t\t}" - if not v: - print >>f,"\t\tC c;" - print >>f,"\t\treturn c (r.begin(), r.end());" - print >>f,"\t}" - - print >>f,""" - bool empty () { - boost::mutex::scoped_lock lm (_mutex); - return _slots.empty (); - } -""" - - - if v: - tp = comma_separated(["void"] + An) - else: - tp = comma_separated(["R"] + An + ["C"]) - - print >>f,"\tstatic boost::shared_ptr<SimpleSignal%d<%s> > create ()" % (n, tp) - print >>f,"\t{" - print >>f,"\t\treturn boost::shared_ptr<SimpleSignal%d<%s> > (new SimpleSignal%d<%s>);" % (n, tp, n, tp) - print >>f,"\t}" - - print >>f,"" - print >>f,"private:" - print >>f,"" - print >>f,"\tfriend class Connection;" - print >>f,"" - print >>f,"\tSimpleSignal%d () {}" % n - - print >>f,""" - void disconnect (boost::shared_ptr<Connection> c) - { - boost::mutex::scoped_lock lm (_mutex); - _slots.erase (c); - } -}; -""" - - -for i in range(0, 6): - simple_signal(f, i, False) - simple_signal(f, i, True) - -print >>f,"}" diff --git a/libs/pbd/pbd/signals.h b/libs/pbd/pbd/signals.h index 7cdbcef414..e40b0bd2a4 100644 --- a/libs/pbd/pbd/signals.h +++ b/libs/pbd/pbd/signals.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2009 Paul Davis + Copyright (C) 2009-2012 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,13 +26,71 @@ #include <boost/noncopyable.hpp> #include <boost/bind.hpp> #include <boost/bind/protect.hpp> +#include <boost/function.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/optional.hpp> #include "pbd/event_loop.h" -#include "pbd/signal.h" namespace PBD { +class Connection; + +class SignalBase +{ +public: + virtual ~SignalBase () {} + virtual void disconnect (boost::shared_ptr<Connection>) = 0; + +protected: + boost::mutex _mutex; +}; + +class Connection : public boost::enable_shared_from_this<Connection> +{ +public: + Connection (SignalBase* b) : _signal (b) {} + + void disconnect () + { + boost::mutex::scoped_lock lm (_mutex); + if (_signal) { + _signal->disconnect (shared_from_this ()); + } + } + + void signal_going_away () + { + boost::mutex::scoped_lock lm (_mutex); + _signal = 0; + } + +private: + boost::mutex _mutex; + SignalBase* _signal; +}; + +template<typename R> +class OptionalLastValue +{ +public: + typedef boost::optional<R> result_type; + + template <typename Iter> + result_type operator() (Iter first, Iter last) const { + result_type r; + while (first != last) { + r = *first; + ++first; + } + + return r; + } +}; + typedef boost::shared_ptr<Connection> UnscopedConnection; + class ScopedConnection { public: @@ -94,364 +152,7 @@ class ScopedConnectionList : public boost::noncopyable ConnectionList _list; }; -template<typename R> -class Signal0 { -public: - typedef SimpleSignal0<R> SignalType; - - Signal0 () : _signal (SignalType::create ()) {} - - /** Arrange for @a slot to be executed whenever this signal is emitted. - Store the connection that represents this arrangement in @a c. - - NOTE: @a slot will be executed in the same thread that the signal is - emitted in. - */ - - void connect_same_thread (ScopedConnection& c, - const typename SignalType::slot_function_type& slot) { - c = _signal->connect (slot); - } - - /** Arrange for @a slot to be executed whenever this signal is emitted. - Add the connection that represents this arrangement to @a clist. - - NOTE: @a slot will be executed in the same thread that the signal is - emitted in. - */ - - void connect_same_thread (ScopedConnectionList& clist, - const typename SignalType::slot_function_type& slot) { - clist.add_connection (_signal->connect (slot)); - } - - /** Arrange for @a slot to be executed in the context of @a event_loop - whenever this signal is emitted. Add the connection that represents - this arrangement to @a clist. - - If the event loop/thread in which @a slot will be executed will - outlive the lifetime of any object referenced in @a slot, - then an InvalidationRecord should be passed, allowing - any request sent to the @a event_loop and not executed - before the object is destroyed to be marked invalid. - - "outliving the lifetime" doesn't have a specific, detailed meaning, - but is best illustrated by two contrasting examples: - - 1) the main GUI event loop/thread - this will outlive more or - less all objects in the application, and thus when arranging for - @a slot to be called in that context, an invalidation record is - highly advisable. - - 2) a secondary event loop/thread which will be destroyed along - with the objects that are typically referenced by @a slot. - Assuming that the event loop is stopped before the objects are - destroyed, there is no reason to pass in an invalidation record, - and MISSING_INVALIDATOR may be used. - */ - - void connect (ScopedConnectionList& clist, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - clist.add_connection (_signal->connect (boost::bind (&EventLoop::call_slot, event_loop, ir, slot))); - } - - /** See notes for the ScopedConnectionList variant of this function. This - * differs in that it stores the connection to the signal in a single - * ScopedConnection rather than a ScopedConnectionList. - */ - - void connect (ScopedConnection& c, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - c = _signal->connect (boost::bind (&EventLoop::call_slot, event_loop, ir, slot)); - } - - /** Emit this signal. This will cause all slots connected to it be executed - in the order that they were connected (cross-thread issues may alter - the precise execution time of cross-thread slots). - */ - - typename SignalType::result_type operator()() { - return _signal->emit (); - } - - /** Return true if there is nothing connected to this signal, false - * otherwise. - */ - - bool empty() const { return _signal->empty(); } - -private: - boost::shared_ptr<SignalType> _signal; -}; - -template<typename R, typename A, typename C = OptionalLastValue<R> > -class Signal1 { -public: - typedef SimpleSignal1<R, A, C> SignalType; - Signal1 () : _signal (SignalType::create()) {} - - void connect_same_thread (ScopedConnectionList& clist, - const typename SignalType::slot_function_type& slot) { - clist.add_connection (_signal->connect (slot)); - } - - void connect_same_thread (ScopedConnection& c, - const typename SignalType::slot_function_type& slot) { - c = _signal->connect (slot); - } - - static void compositor (typename boost::function<void(A)> f, EventLoop* event_loop, EventLoop::InvalidationRecord* ir, A arg) { - event_loop->call_slot (ir, boost::bind (f, arg)); - } - - void connect (ScopedConnectionList& clist, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - clist.add_connection (_signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1))); - } - - void connect (ScopedConnection& c, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - c = _signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1)); - - } - - typename SignalType::result_type operator()(A arg1) { - return _signal->emit (arg1); - } - - bool empty() const { return _signal->empty(); } - -private: - boost::shared_ptr<SignalType> _signal; -}; - -template<typename R, typename A1, typename A2> -class Signal2 { -public: - typedef SimpleSignal2<R, A1, A2> SignalType; - Signal2 () : _signal (SignalType::create()) {} - - void connect_same_thread (ScopedConnectionList& clist, - const typename SignalType::slot_function_type& slot) { - clist.add_connection (_signal->connect (slot)); - } - - void connect_same_thread (ScopedConnection& c, - const typename SignalType::slot_function_type& slot) { - c = _signal->connect (slot); - } - - static void compositor (typename boost::function<void(A1,A2)> f, PBD::EventLoop* event_loop, - EventLoop::InvalidationRecord* ir, - A1 arg1, A2 arg2) { - event_loop->call_slot (ir, boost::bind (f, arg1, arg2)); - } - - void connect (ScopedConnectionList& clist, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - clist.add_connection (_signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2))); - } - - void connect (ScopedConnection& c, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - c = _signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2)); - } - - typename SignalType::result_type operator()(A1 arg1, A2 arg2) { - return _signal->emit (arg1, arg2); - } - - bool empty() const { return _signal->empty(); } - -private: - boost::shared_ptr<SignalType> _signal; -}; - -template<typename R, typename A1, typename A2, typename A3> -class Signal3 { -public: - typedef SimpleSignal3<R, A1, A2, A3> SignalType; - Signal3 () : _signal (SignalType::create()) {} - - void connect_same_thread (ScopedConnectionList& clist, - const typename SignalType::slot_function_type& slot) { - clist.add_connection (_signal->connect (slot)); - } - - void connect_same_thread (ScopedConnection& c, - const typename SignalType::slot_function_type& slot) { - c = _signal->connect (slot); - } - - static void compositor (typename boost::function<void(A1,A2,A3)> f, PBD::EventLoop* event_loop, - EventLoop::InvalidationRecord* ir, - A1 arg1, A2 arg2, A3 arg3) { - event_loop->call_slot (ir, boost::bind (f, arg1, arg2, arg3)); - } - - void connect (ScopedConnectionList& clist, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - clist.add_connection (_signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3))); - } - - void connect (ScopedConnection& c, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - c = _signal->connect (_signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3))); - } - - typename SignalType::result_type operator()(A1 arg1, A2 arg2, A3 arg3) { - return _signal->emit (arg1, arg2, arg3); - } - - bool empty() const { return _signal->empty(); } - -private: - boost::shared_ptr<SignalType> _signal; -}; - -template<typename R, typename A1, typename A2, typename A3, typename A4> -class Signal4 { -public: - typedef SimpleSignal4<R, A1, A2, A3, A4> SignalType; - Signal4 () : _signal (SignalType::create()) {} - - void connect_same_thread (ScopedConnectionList& clist, - const typename SignalType::slot_function_type& slot) { - clist.add_connection (_signal->connect (slot)); - } - - void connect_same_thread (ScopedConnection& c, - const typename SignalType::slot_function_type& slot) { - c = _signal->connect (slot); - } - - static void compositor (typename boost::function<void(A1,A2,A3)> f, PBD::EventLoop* event_loop, - EventLoop::InvalidationRecord* ir, - A1 arg1, A2 arg2, A3 arg3, A4 arg4) { - event_loop->call_slot (ir, boost::bind (f, arg1, arg2, arg3, arg4)); - } - - void connect (ScopedConnectionList& clist, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - clist.add_connection (_signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3, _4))); - } - - void connect (ScopedConnection& c, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - c = _signal->connect (_signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3, _4))); - } - - typename SignalType::result_type operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4) { - return _signal->emit (arg1, arg2, arg3, arg4); - } - - bool empty() const { return _signal->empty(); } - -private: - boost::shared_ptr<SignalType> _signal; -}; - -template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5> -class Signal5 { -public: - typedef SimpleSignal5<R, A1, A2, A3, A4, A5> SignalType; - Signal5 () : _signal (SignalType::create()) {} - - void connect_same_thread (ScopedConnectionList& clist, - const typename SignalType::slot_function_type& slot) { - clist.add_connection (_signal->connect (slot)); - } - - void connect_same_thread (ScopedConnection& c, - const typename SignalType::slot_function_type& slot) { - c = _signal->connect (slot); - } - - static void compositor (typename boost::function<void(A1,A2,A3,A4,A5)> f, PBD::EventLoop* event_loop, - EventLoop::InvalidationRecord* ir, - A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) { - event_loop->call_slot (ir, boost::bind (f, arg1, arg2, arg3, arg4, arg5)); - } - - void connect (ScopedConnectionList& clist, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - clist.add_connection (_signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3, _4, _5))); - } - - void connect (ScopedConnection& c, - PBD::EventLoop::InvalidationRecord* ir, - const typename SignalType::slot_function_type& slot, - PBD::EventLoop* event_loop) { - if (ir) { - ir->event_loop = event_loop; - } - c = _signal->connect (_signal->connect (boost::bind (&compositor, slot, event_loop, ir, _1, _2, _3, _4, _5))); - } - - typename SignalType::result_type operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) { - return _signal->emit (arg1, arg2, arg3, arg4, arg5); - } - - bool empty() const { return _signal->empty(); } - -private: - boost::shared_ptr<SignalType> _signal; -}; +#include "pbd/signals_generated.h" } /* namespace */ diff --git a/libs/pbd/wscript b/libs/pbd/wscript index 641b333a53..f853277130 100644 --- a/libs/pbd/wscript +++ b/libs/pbd/wscript @@ -56,7 +56,7 @@ def configure(conf): def build(bld): # Make signal.h using signal.h.py - bld(rule = 'python ${SRC} ${TGT}', source = 'pbd/signal.h.py', target = 'pbd/signal.h') + bld(rule = 'python ${SRC} ${TGT}', source = 'pbd/signals.py', target = 'pbd/signals_generated.h') # Library obj = bld(features = 'cxx cxxshlib') @@ -536,8 +536,6 @@ def configure(conf): if Options.options.also_libdir != '': conf.env.append_value('LDFLAGS', '-L' + Options.options.also_libdir) - autowaf.check_header(conf, 'cxx', 'boost/signals2.hpp', mandatory = True) - if Options.options.boost_sp_debug: conf.env.append_value('CXXFLAGS', '-DBOOST_SP_ENABLE_DEBUG_HOOKS') |