#include #include #include #include #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // STL #include #include #include using namespace boost::phoenix; // using namespace boost::phoenix::arg_names; template class Queue; namespace _bi=boost::_bi; template struct nargs; template struct nargs<_bi::bind_t >{enum {value=0};}; template struct nargs<_bi::bind_t > >{enum {value=1};}; template struct nargs<_bi::bind_t > >{enum {value=2};}; template struct slot_wrap_impl { public: slot_wrap_impl(Queue &n_q) : m_q(n_q) {}; template struct result { typedef void type; }; template typename result::type operator()(SlotSignature n_method) const { using boost::phoenix::if_; using boost::phoenix::switch_; using boost::phoenix::case_; using boost::phoenix::default_; using boost::phoenix::bind; /* switch (nargs::value) { case 0: // m_q.post(n_method); boost::phoenix::bind(&Queue::post, &m_q, n_method)(); break; case 1: // m_q.post(n_method); boost::phoenix::bind(&Queue::post, &m_q, n_method, _1)(); break; case 2: // m_q.post(n_method); boost::phoenix::bind(&Queue::post, &m_q, n_method, _1, _2)(); break; } */ std::cout << "binding post...\n"; // boost::phoenix::bind(&Queue::post, &m_q, n_method)(); // boost::phoenix::bind(&boost::asio::io_service::post, &m_q.m_iosrv, n_method); m_q.post(n_method); std::cout << "post bound" << std::endl; /* if (CallingBack) { m_q.callback(); }; */ }; private: Queue &m_q; }; template class Queue : public boost::noncopyable { public: friend struct slot_wrap_impl; explicit Queue(const boost::uint8_t n_workerthreads) : m_work(new boost::asio::io_service::work(m_iosrv)), m_num_threads(n_workerthreads) { for (boost::uint8_t i = 0; i < m_num_threads; i++) { boost::shared_ptr thread(new boost::thread( boost::bind(&boost::asio::io_service::run, &m_iosrv))); m_workerthreads.push_back(thread); } }; explicit Queue() : m_work(new boost::asio::io_service::work(m_iosrv)), m_num_threads(0) { }; explicit Queue(boost::function n_signal_callback) : m_work(new boost::asio::io_service::work(m_iosrv)), m_signal_callback(n_signal_callback), m_num_threads(0) { }; ~Queue(void) throw () { // this will tell the io_service that from now on "exit" is the name of the game delete m_work; int cnt = 0; // Wait for all threads in the pool to exit. BOOST_FOREACH(const boost::shared_ptr &t, m_workerthreads) { if (t) { t->join(); } }; // Enter Chuck Norris m_iosrv.stop(); }; std::size_t process(boost::system::error_code & n_errcode) { if (m_num_threads) return 0; return m_iosrv.poll(n_errcode); } void callback(void) { try { m_signal_callback(); } catch (const std::exception &sex) { } } // template void post(boost::function n_handler) { std::cout << "posting handler...\n"; m_iosrv.post(n_handler); std::cout << "handler posted" << std::endl; }; template void wrap(SlotFunction n_handler) { std::cout << "wrapping zero parameters" << std::endl; m_iosrv.wrap(n_handler); }; template boost::signals2::connection connect(boost::signals2::signal &n_signal, SlotFunction n_method) { using boost::phoenix::bind; using boost::phoenix::arg_names::arg1; std::cout << "connect called" << std::endl; /* boost::function f = if_( CallingBack ) [ bind(&Queue::post, *this, arg1) //m_signal_callback ] .else_ [ bind(&Queue::post, *this, arg1) ]; return n_signal.connect( if_( CallingBack ) [ bind(&Queue::post, *this, arg1()) //*m_signal_callback ] .else_ [ bind(&Queue::post, *this, arg1()) ] () (n_method) ); */ boost::phoenix::function > f(*this); std::cout << "functor instanciated" << std::endl; boost::signals2::connection ret = n_signal.connect(f(n_method)); std::cout << "signal connected" << std::endl; return ret; }; private: boost::asio::io_service m_iosrv; //!< the io service dispatcher object boost::asio::io_service::work *m_work; //!< lots to do.... boost::function m_signal_callback; //!< will be called after a signal triggered an action to be posted into the Q const boost::uint8_t m_num_threads; //!< this many threads have been started std::vector > m_workerthreads; //!< all in there run our commands }; class testclass { public: void slot_zero(void) { std::cout << "testclass slot 0" << std::endl; }; void slot_one(int n_arg) { std::cout << "testclass slot 1: " << n_arg << std::endl; }; void slot_two(const std::string &n_str, double n_arg) { std::cout << "testclass slot 2: " << n_str << " " << n_arg << std::endl; }; }; int main (int argc, char **argv) { Queue q; boost::signals2::signal sig; boost::signals2::signal sig1; boost::signals2::signal sig2; testclass tc; std::cout << "connecting all signals...\n"; q.connect(sig, boost::bind(&testclass::slot_zero, &tc)); // q.connect(sig1, boost::bind(&testclass::slot_one, &tc, _1)); // q.connect(sig2, boost::bind(&testclass::slot_two, &tc, _1, _2)); std::cout << "signals connected" << std::endl; // The signals will not actually be executed here std::cout << "triggering signals...\n"; sig(); sig1(42); std::cout << "signal triggered" << std::endl; sig2("Hallo Welt", 23.17); std::cout << "processing queue...\n"; boost::system::error_code errc; // here we execute the accumulated signals q.process(errc); std::cout << "q processed" << std::endl; };