/* inter-thread signal module Copyright (C) 2007 Vadim Lebedev This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include using namespace boost; using namespace std; // Thread id int gTID = 1000; struct XComm { typedef int TargetID; struct mess_base { virtual void callback() = 0; }; template struct mess : public mess_base { const Slot slot; mess(const Slot& s) : slot(s) { } virtual void callback() { slot(); } }; template static void send(TargetID tid, const T& slot) { if (tid == get_tid()) { cout << __FUNCTION__ << ": direct call to: " << tid << endl; slot(); return; } else { cout << __FUNCTION__ << ": message sent from: " << get_tid() << " to: " << tid << endl; mess *m = new mess(slot); m->callback(); delete m; } } static TargetID get_tid() { return gTID; } }; // multihread functor template struct mtfunction : public boost::function { typedef function base_type; typedef typename base_type::result_type result_type; typename Comm::TargetID tid; mtfunction() : base_type(), tid(Comm::get_tid()) { } template mtfunction(T f) : base_type(f), tid(Comm::get_tid()) { } mtfunction(const mtfunction& other) : base_type((const base_type &)other), tid(other.tid) { } mtfunction& operator=(const mtfunction& other) { base_type::operator=(other); tid = other.tid; return *this; } static void caller0(base_type *fun) { (*fun)(); } template static void caller1(base_type *fun, T1 a1) { (*fun)(a1); } template static void caller2(base_type *fun, T1 a1, T2 a2) { (*fun)(a1,a2); } template static void caller3(base_type *fun, T1 a1, T2 a2, T3 a3) { (*fun)(a1,a2,a3); } template static void caller4(base_type *fun, T1 a1, T2 a2, T3 a3, T4 a4) { (*fun)(a1,a2,a3,a4); } template static void caller5(base_type *fun, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { (*fun)(a1,a2,a3,a4,a5); } template static void caller6(base_type *fun, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) { (*fun)(a1,a2,a3,a4,a5,a6); } result_type operator()() const { Comm::send(tid, boost::bind(&caller0, (base_type *)this)); } template result_type operator()(T1 a1) const { Comm::send(tid, boost::bind(&caller1, (base_type *)this, a1)); } template result_type operator()(T1 a1, T2 a2) const { Comm::send(tid, boost::bind(&caller2, (base_type *)this, a1, a2)); } template result_type operator()(T1 a1, T2 a2, T3 a3) const { Comm::send(tid, boost::bind(&caller3, (base_type *)this, a1, a2, a3)); } template result_type operator()(T1 a1, T2 a2, T3 a3, T4 a4) const { Comm::send(tid, boost::bind(&caller4, (base_type *)this, a1, a2, a3, a4)); } template result_type operator()(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) const { Comm::send(tid, boost::bind(&caller5, (base_type *)this, a1, a2, a3, a4, a5)); } template result_type operator()(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6) const { Comm::send(tid, boost::bind(&caller6, (base_type *)this, a1, a2, a3, a4, a5, a6)); } }; // multithreaded signals template< typename Signature, // function type R (T1, T2, ..., TN) typename Combiner = last_value::result_type>, typename Group = int, typename GroupCompare = std::less > class mtsignal : public signal > { typedef signal > base_type; public: explicit mtsignal(const Combiner& combiner = Combiner(), const GroupCompare& group_compare = GroupCompare()) : base_type(combiner, group_compare) { } }; mtsignal sig1; mtsignal sig2; int s1_handler(int a) { cout << "s1_handler:: " << a << endl; return 0; } int s2_rhandler(const string& a) { cout << "s2_rhandler:: " << a << endl; return 0; } int s2_handler(string a) { cout << "s2_handler:: " << a << endl; return 0; } main(int argc, char *argv[]) { sig1.connect(&s1_handler); cout << "sig1 connected" << endl; sig1(33); gTID++; // simulate thread switch sig1(55); cout << "sig1 done" << endl; sig2.connect(&s2_rhandler); gTID++; sig2.connect(&s2_handler); sig2("abcd"); }