dispatcher.h
Go to the documentation of this file.
00001 #ifndef H_CAN_DISPATCHER
00002 #define H_CAN_DISPATCHER
00003 
00004 #include <socketcan_interface/interface.h>
00005 #include <list>
00006 #include <boost/thread/mutex.hpp>
00007 #include <boost/unordered_map.hpp>
00008 #include <boost/utility.hpp>
00009 #include <boost/foreach.hpp>
00010 #include <boost/weak_ptr.hpp>
00011 
00012 namespace can{
00013 
00014 template< typename Listener > class SimpleDispatcher{
00015 public:
00016     typedef typename Listener::Callable Callable;
00017     typedef typename Listener::Type Type;
00018 protected:
00019     class DispatcherBase : boost::noncopyable{
00020         class GuardedListener: public Listener{
00021             boost::weak_ptr<DispatcherBase> guard_;
00022         public:
00023             GuardedListener(boost::shared_ptr<DispatcherBase> g, const Callable &callable): Listener(callable), guard_(g){}
00024             virtual ~GuardedListener() {
00025                 boost::shared_ptr<DispatcherBase> d = guard_.lock();
00026                 if(d){
00027                     d->remove(this);
00028                 }
00029             }
00030         };
00031         
00032         boost::mutex &mutex_;
00033         std::list< Listener* > listeners_;
00034     public:
00035         DispatcherBase(boost::mutex &mutex) : mutex_(mutex) {}
00036         void dispatch_nolock(const Type &obj) const{
00037            for(typename std::list<Listener* >::const_iterator it=listeners_.begin(); it != listeners_.end(); ++it){
00038                (**it)(obj);
00039             }
00040         }
00041         void remove(Listener *d){
00042             boost::mutex::scoped_lock lock(mutex_);
00043             listeners_.remove(d);
00044         }
00045         size_t numListeners(){
00046             boost::mutex::scoped_lock lock(mutex_);
00047             return listeners_.size();
00048         }
00049 
00050         static typename Listener::Ptr createListener(boost::shared_ptr<DispatcherBase> dispatcher, const  Callable &callable){
00051             boost::shared_ptr<Listener > l(new GuardedListener(dispatcher,callable));
00052             dispatcher->listeners_.push_back(l.get());
00053             return l;
00054         }
00055     };
00056     boost::mutex mutex_;
00057     boost::shared_ptr<DispatcherBase> dispatcher_;
00058 public:
00059     SimpleDispatcher() : dispatcher_(new DispatcherBase(mutex_)) {}
00060     typename Listener::Ptr createListener(const Callable &callable){
00061         boost::mutex::scoped_lock lock(mutex_);
00062         return DispatcherBase::createListener(dispatcher_, callable);
00063     }
00064     void dispatch(const Type &obj){
00065         boost::mutex::scoped_lock lock(mutex_);
00066         dispatcher_->dispatch_nolock(obj);
00067     }
00068     size_t numListeners(){
00069         return dispatcher_->numListeners();
00070     }
00071     operator Callable() { return Callable(this,&SimpleDispatcher::dispatch); }
00072 };
00073 
00074 template<typename K, typename Listener, typename Hash = boost::hash<K> > class FilteredDispatcher: public SimpleDispatcher<Listener>{
00075     typedef SimpleDispatcher<Listener> BaseClass;
00076     boost::unordered_map<K, boost::shared_ptr<typename BaseClass::DispatcherBase >, Hash> filtered_;
00077 public:
00078     using BaseClass::createListener;
00079     typename Listener::Ptr createListener(const K &key, const typename BaseClass::Callable &callable){
00080         boost::mutex::scoped_lock lock(BaseClass::mutex_);
00081         boost::shared_ptr<typename BaseClass::DispatcherBase > &ptr = filtered_[key];
00082         if(!ptr) ptr.reset(new typename BaseClass::DispatcherBase(BaseClass::mutex_));
00083         return BaseClass::DispatcherBase::createListener(ptr, callable);
00084     }
00085     void dispatch(const typename BaseClass::Type &obj){
00086         boost::mutex::scoped_lock lock(BaseClass::mutex_);
00087         boost::shared_ptr<typename BaseClass::DispatcherBase > &ptr = filtered_[obj];
00088         if(ptr) ptr->dispatch_nolock(obj);
00089         BaseClass::dispatcher_->dispatch_nolock(obj);
00090     }
00091     operator typename BaseClass::Callable() { return typename BaseClass::Callable(this,&FilteredDispatcher::dispatch); }
00092 };
00093 
00094 } // namespace can
00095 #endif


socketcan_interface
Author(s): Mathias L├╝dtke
autogenerated on Sun Sep 3 2017 03:10:37