signal_slot.h

Go to the documentation of this file.
00001 /*
00002  * File Name: signal_slot.h
00003  */
00004 
00005 /*
00006  * This file is part of uds-plugin-common.
00007  *
00008  * uds-plugin-common is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * uds-plugin-common is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 #ifndef SIGNAL_SLOT_H_
00028 #define SIGNAL_SLOT_H_
00029 
00030 #include <vector>
00031 
00032 /// A simple signal/slot implementation.
00033 namespace utils
00034 {
00035 
00036 struct empty {} ;
00037 typedef empty* UNUSABLE;
00038 
00039 template < typename A1 = UNUSABLE,
00040            typename A2 = UNUSABLE,
00041            typename A3 = UNUSABLE,
00042            typename A4 = UNUSABLE,
00043            typename A5 = UNUSABLE>
00044 class SlotBase
00045 {
00046 public:
00047     SlotBase(){}
00048     virtual ~SlotBase(){}
00049     virtual void operator()() = 0;
00050     virtual void operator()(A1 arg1) = 0;
00051     virtual void operator()(A1 arg1, A2 arg2) = 0;
00052     virtual void operator()(A1 arg1, A2 arg2, A3 arg3) = 0;
00053     virtual void operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4) = 0;
00054     virtual void operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) = 0;
00055     virtual bool compare(SlotBase<A1, A2, A3, A4, A5> * p) = 0;
00056 };
00057 
00058 
00059 template < class T,  
00060            typename A1 = UNUSABLE,
00061            typename A2 = UNUSABLE,
00062            typename A3 = UNUSABLE,
00063            typename A4 = UNUSABLE,
00064            typename A5 = UNUSABLE>
00065 class Slot : public SlotBase<A1, A2, A3, A4, A5>
00066 {
00067 private:
00068     typedef void (T::*Function0)();
00069     typedef void (T::*Function1)(A1);
00070     typedef void (T::*Function2)(A1, A2);
00071     typedef void (T::*Function3)(A1, A2, A3);
00072     typedef void (T::*Function4)(A1, A2, A3, A4);
00073     typedef void (T::*Function5)(A1, A2, A3, A4, A5);
00074     typedef Slot<T, A1, A2, A3, A4, A5>* SlotPtr;
00075 
00076 public:
00077 
00078     Slot(T *p, Function0 f0) : instance(p) { functor.func0_ = f0; }
00079     Slot(T *p, Function1 f1) : instance(p) { functor.func1_ = f1; }
00080     Slot(T *p, Function2 f2) : instance(p) { functor.func2_ = f2; }
00081     Slot(T *p, Function3 f3) : instance(p) { functor.func3_ = f3; }
00082     Slot(T *p, Function4 f4) : instance(p) { functor.func4_ = f4; }
00083     Slot(T *p, Function5 f5) : instance(p) { functor.func5_ = f5; }
00084     ~Slot() {}
00085 
00086     void operator()()
00087     {
00088         (instance->*(functor.func0_))();
00089     }
00090 
00091     void operator()(A1 arg1)
00092     {
00093         (instance->*(functor.func1_))(arg1);
00094     }
00095 
00096     void operator()(A1 arg1, A2 arg2)
00097     {
00098         (instance->*(functor.func2_))(arg1, arg2);
00099     }
00100 
00101     void operator()(A1 arg1, A2 arg2, A3 arg3)
00102     {
00103         (instance->*(functor.func3_))(arg1, arg2, arg3);
00104     }
00105 
00106     void operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4)
00107     {
00108         (instance->*(functor.func4_))(arg1, arg2, arg3, arg4);
00109     }
00110 
00111     void operator()(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
00112     {
00113         (instance->*(functor.func5_))(arg1, arg2, arg3, arg4, arg5);
00114     }
00115 
00116     // Compare the function pointer
00117     bool compare(SlotBase<A1, A2, A3, A4, A5> * p) 
00118     { 
00119         // Have to down_cast. Should compare the instance?
00120         SlotPtr ptr = static_cast<SlotPtr>(p);
00121         return  ( functor.func0_ == ptr->functor.func0_ &&
00122                   instance == ptr->instance );
00123     }
00124 
00125 private:
00126     T  *instance;
00127     union Functor
00128     {
00129         Function0   func0_;
00130         Function1   func1_;
00131         Function2   func2_;
00132         Function3   func3_;
00133         Function4   func4_;
00134         Function5   func5_;
00135     }functor;
00136 };
00137 
00138 template < typename A1 = UNUSABLE,
00139            typename A2 = UNUSABLE,
00140            typename A3 = UNUSABLE,
00141            typename A4 = UNUSABLE,
00142            typename A5 = UNUSABLE>
00143 class Signal
00144 {
00145     typedef SlotBase<A1, A2, A3, A4, A5>* SlotBasePtr;
00146 
00147 public:
00148     Signal() 
00149     {}
00150 
00151     ~Signal(){clear();}
00152 
00153 public:
00154     /// @brief Add receiver to receive pre-defined signals.
00155     template <class T>
00156     void add_slot(T* obj, void (T::*func)(void))
00157     {
00158         SlotBasePtr p = new Slot<T>(obj, func);
00159         receivers.push_back(p);
00160     }
00161 
00162     template <class T>
00163     void add_slot(T* obj, void (T::*func)(A1))
00164     {
00165         SlotBasePtr p = new Slot<T, A1>(obj, func);
00166         receivers.push_back(p);
00167     }
00168 
00169     template <class T>
00170     void add_slot(T* obj, void (T::*func)(A1, A2))
00171     {
00172         SlotBasePtr p = new Slot<T, A1, A2>(obj, func);
00173         receivers.push_back(p);
00174     }
00175 
00176     template <class T>
00177     void add_slot(T* obj, void (T::*func)(A1, A2, A3))
00178     {
00179         SlotBasePtr p = new Slot<T, A1, A2, A3>(obj, func);
00180         receivers.push_back(p);
00181     }
00182 
00183     template <class T>
00184     void add_slot(T* obj, void (T::*func)(A1, A2, A3, A4))
00185     {
00186         SlotBasePtr p = new Slot<T, A1, A2, A3, A4>(obj, func);
00187         receivers.push_back(p);
00188     }
00189 
00190     template <class T>
00191     void add_slot(T* obj, void (T::*func)(A1, A2, A3, A4, A5))
00192     {
00193         SlotBasePtr p = new Slot<T, A1, A2, A3, A4, A5>(obj, func);
00194         receivers.push_back(p);
00195     }
00196     
00197     /// @brief Remove receiver from the receivers list.
00198     template <class T>
00199     bool remove_slot(T* p, void (T::*func)())
00200     {
00201         Slot<T, A1, A2, A3, A4, A5> func_obj(p, func);
00202         return remove_receiver(&func_obj);
00203     }
00204 
00205     template <class T>
00206     bool remove_slot(T* p, void (T::*func)(A1 arg1))
00207     {
00208         Slot<T, A1, A2, A3, A4, A5> func_obj(p, func);
00209         return remove_receiver(&func_obj);
00210     }
00211 
00212     template <class T>
00213     bool remove_slot(T* p, void (T::*func)(A1 arg1, A2 arg2))
00214     {
00215         Slot<T, A1, A2, A3, A4, A5> func_obj(p, func);
00216         return remove_receiver(&func_obj);
00217     }
00218 
00219     template <class T>
00220     bool remove_slot(T* p, void (T::*func)(A1 arg1, A2 arg2, A3 arg3))
00221     {
00222         Slot<T, A1, A2, A3, A4, A5> func_obj(p, func);
00223         return remove_receiver(&func_obj);
00224     }
00225 
00226     template <class T>
00227     bool remove_slot(T* p, void (T::*func)(A1 arg1, A2 arg2, A3 arg3, A4 arg4))
00228     {
00229         Slot<T, A1, A2, A3, A4, A5> func_obj(p, func);
00230         return remove_receiver(&func_obj);
00231     }
00232 
00233     template <class T>
00234     bool remove_slot(T* p, void (T::*func)(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5))
00235     {
00236         Slot<T, A1, A2, A3, A4, A5> func_obj(p, func);
00237         return remove_receiver(&func_obj);
00238     }
00239 
00240     /// @brief Notify all receivers. 
00241     void broadcast()
00242     {
00243         ReceiversIter begin = receivers.begin();
00244         ReceiversIter end   = receivers.end();
00245         for(ReceiversIter it= begin; it != end; ++it)
00246         {
00247             (*(*it))();
00248         }
00249     }
00250 
00251     void broadcast(A1 arg1)
00252     {
00253         ReceiversIter begin = receivers.begin();
00254         ReceiversIter end   = receivers.end();
00255         for(ReceiversIter it= begin; it != end; ++it)
00256         {
00257             (*(*it))(arg1);
00258         }
00259     }
00260 
00261     /// safe_broadcast is added for object that will be released
00262     /// during broadcasting.
00263     void safe_broadcast(A1 arg1)
00264     {
00265         Signal<A1, A2, A3, A4, A5> object;
00266         object.receivers = receivers;
00267         object.broadcast(arg1);
00268         object.receivers.clear();
00269     }
00270 
00271     void broadcast(A1 arg1, A2 arg2)
00272     {
00273         ReceiversIter begin = receivers.begin();
00274         ReceiversIter end   = receivers.end();
00275         for(ReceiversIter it= begin; it != end; ++it)
00276         {
00277             (*(*it))(arg1, arg2);
00278         }
00279     }
00280 
00281     void broadcast(A1 arg1, A2 arg2, A3 arg3)
00282     {
00283         ReceiversIter begin = receivers.begin();
00284         ReceiversIter end   = receivers.end();
00285         for(ReceiversIter it= begin; it != end; ++it)
00286         {
00287             (*(*it))(arg1, arg2, arg3);
00288         }
00289     }
00290 
00291     void broadcast(A1 arg1, A2 arg2, A3 arg3, A4 arg4)
00292     {
00293         ReceiversIter begin = receivers.begin();
00294         ReceiversIter end   = receivers.end();
00295         for(ReceiversIter it= begin; it != end; ++it)
00296         {
00297             (*(*it))(arg1, arg2, arg3, arg4);
00298         }
00299     }
00300 
00301     void broadcast(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
00302     {
00303         ReceiversIter begin = receivers.begin();
00304         ReceiversIter end   = receivers.end();
00305         for(ReceiversIter it= begin; it != end; ++it)
00306         {
00307             (*(*it))(arg1, arg2, arg3, arg4, arg5);
00308         }
00309     }
00310 
00311 
00312     unsigned int count()
00313     {
00314         return static_cast<unsigned int>(receivers.size());
00315     }
00316 
00317 private:
00318     // Clear all of the receivers
00319     void clear()
00320     {
00321         ReceiversIter begin = receivers.begin();
00322         ReceiversIter end   = receivers.end();
00323         for(ReceiversIter it = begin; it != end; ++it)
00324         {
00325             delete (*it);
00326         }
00327         receivers.clear();
00328     }
00329 
00330     // Remove one receiver
00331     bool remove_receiver(SlotBasePtr p)
00332     {
00333         ReceiversIter begin = receivers.begin();
00334         ReceiversIter end   = receivers.end();
00335         for(ReceiversIter it = begin; it != end; ++it)
00336         {
00337             if ((*it)->compare(p))
00338             {
00339                 delete (*it);
00340                 receivers.erase(it);
00341                 return true;
00342             }
00343         }
00344         return false;
00345     }
00346 
00347 private:
00348     typedef std::vector<SlotBasePtr> Receivers;
00349     typedef typename std::vector<SlotBasePtr>::iterator ReceiversIter;
00350     Receivers receivers;
00351 };
00352 
00353 };  // namespace utils
00354 
00355 #endif
Generated by  doxygen 1.6.2-20100208