#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; template struct slot_wrap_impl { public: slot_wrap_impl(Queue &n_q) : m_q(n_q) {}; template struct result { typedef SlotSignature 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_; // if_ ( CallingBack ) [ // m_q.callback() // ]; // switch_(NumArgs) [ // case_<0>(m_q.post(n_method)), // case_<1>(m_q.post(boost::bind(n_method, _1))), // default_(m_q.post(n_method)) // ]; m_q.post(n_method); if (CallingBack) { m_q.callback(); }; }; private: Queue &m_q; }; template class Queue : public boost::noncopyable { public: 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); } template void post(Handler n_handler) { m_iosrv.post(n_handler); }; void callback(void) { try { m_signal_callback(); } catch (const std::exception &sex) { } } template boost::signals2::connection connect(boost::signals2::signal &n_signal, SlotFunction n_method) { // boost::phoenix::function< slot_wrap_impl > f(*this); // f(n_method); // return n_signal.connect(f(n_method)); // return n_signal.connect( boost::phoenix::if_ (CallingBack) [m_iosrv.wrap( n_method )] .else_ [ m_iosrv.post(n_method) , m_signal_callback() ]); //return n_signal.connect( if_( CallingBack ) [ post(n_method) , m_signal_callback() ] .else_ [ m_iosrv.wrap( n_method ) ] ); // return n_signal.connect( if_( CallingBack ) [ post(n_method), m_signal_callback() ] .else_ [ post(n_method), m_iosrv.wrap( n_method ) ] ); // return n_signal.connect( if_( CallingBack ) [ post(n_method), m_signal_callback() ] .else_ [ m_iosrv.wrap( n_method ) ] ); }; /* template boost::signals2::connection connect(boost::signals2::signal& n_signal, SlotFunction n_method) { // return n_signal.connect(boost::bind(&Queue::slotWrapper, this, n_method, _1)); boost::phoenix::function< slot_wrap_impl > f(*this); return n_signal.connect(f(boost::bind(n_method, _1))); // return n_signal.connect(f(boost::phoenix::bind(n_method, _1))); }; */ /* template boost::signals2::connection connect(boost::signals2::signal& n_signal, SlotSignature n_method) { // return n_signal.connect(boost::bind(&Queue::slotWrapper, this, n_method, _1, _2)); }; */ private: /* template< typename SlotSignature > void slotWrapper(SlotSignature n_method) { post(n_method); if (m_signal_callback) { m_signal_callback(); } } template< typename SlotSignature, typename T1 > void slotWrapper(SlotSignature n_method, T1 t1) { boost::function f(n_method); post(boost::bind(f, t1)); if (m_signal_callback) { m_signal_callback(); } } template< typename SlotSignature, typename T1, typename T2 > void slotWrapper(SlotSignature n_method, T1 t1, T2 t2) { boost::function f(n_method); post(boost::bind(f, t1, t2)); if (m_signal_callback) { m_signal_callback(); } } */ 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 }; struct testslot { void operator()() const { std::cout << "testslot" << std::endl; } }; struct testslot_one { void operator()(int n_arg) const { std::cout << "testslot 1: " << n_arg << std::endl; } }; struct testslot_two { void operator()(const std::string &n_str, double n_num) const { std::cout << "testslot 2: " << n_str << " " << n_num << std::endl; } }; int main (int argc, char **argv) { Queue q; boost::signals2::signal sig; boost::signals2::signal sig1; boost::signals2::signal sig2; struct testslot t; struct testslot_one t1; struct testslot_two t2; q.connect(sig, t); // q.connect(sig1, t1); // q.connect(sig2, t2); // The signals will not actually be executed here sig(); sig1(42); sig2("Hallo Welt", 23.17); boost::system::error_code errc; // here we execute the accumulated signals q.process(errc); };