// // unnamed_in_out.hpp // // Copyright (c) 2005-2009 Yigong Liu (yigongliu at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef UNNAMED_IN_OUT_HPP #define UNNAMED_IN_OUT_HPP #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace channel { /** * port class: "unnamed" named_out with pull_dispatcher * same role as port in CCR and channel in C++CSP or JCSP */ template< typename executor_type = abstract_executor, //force in-line execution typename idtype = null_id, typename platform_type = boost_platform, typename synchpolicy = mt_synch , typename name_space = null_name_space , typename pulldispatcher = pull_dispatcher > class port: public named_out { public: typedef typename pulldispatcher::choice_async choice_async; typedef typename pulldispatcher::join_async join_async; typedef typename pulldispatcher::choice_sync choice_sync; typedef typename pulldispatcher::join_sync join_sync; typedef named_out named_out_type; typedef named_in named_in_type; port(executor_type *e=NULL) : named_out_type(e) {} }; /** * signal and slot: for synch event dispatching * signal : "unnamed" named_out with push_dispatchers * when signal(named_out) is destroyed, all its remaining slots(named_ins) are unbound; * their num_bindings() should return 0 * when slots(named_in) are destroyed, they are unbound from named_in automatically */ template < typename executor_type = abstract_executor, //force in-line execution typename idtype = null_id, typename platform_type = boost_platform, typename synchpolicy = mt_synch, typename name_space = null_name_space, typename push_dispatcher = broadcast_dispatcher > class signal : public named_out { public: typedef named_in slot; typedef named_out named_out_type; typedef name name_type; typedef typename name_type::binding_set_type binding_set_type; executor_type *exec_; signal(executor_type *e=NULL) : named_out_type(e), exec_(e) {} ~signal() { //signal should be the last to kill after all slots cleanup. do some cleanup ? binding_set_type & bindings0 = ((name_type*) this)->bindings_; //here something wrong with list::iterator!? so copy to a vector std::vector bindings(bindings0.begin(), bindings0.end()); typename std::vector::iterator iter; for(iter = bindings.begin(); iter != bindings.end(); iter++) { delete ((slot *) (*iter)); } } template slot * bind(recver_type rc) { slot * ss = new slot(boost::bind(rc, _2), exec_); ((name_type *)this)->bind((name_type *)ss); ((name_type *)ss)->bind((name_type *)this); return ss; } //when slots are destroyed, they unbind from signals automatically //here is for the case when we just want unbind, not destroy void unbind(slot *ss) { ((name_type *)this)->unbind((name_type *)ss); ((name_type *)ss)->unbind((name_type *)this); } }; } } #endif