00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef _psignal_h_
00021 #define _psignal_h_
00022
00023 #include <pclasses/config.h>
00024 #include <pclasses/pslot.h>
00025 #include <pclasses/plocktraits.h>
00026 #include <list>
00027
00028 namespace P {
00029
00031
00038 template <class _SlotT, class _Mutex>
00039 class SignalBase {
00040 public:
00041 typedef _SlotT SlotType;
00042 typedef std::list<SlotType*> SlotList;
00043 typedef LockTraits<_Mutex> LockTraits;
00044
00045 typedef typename LockTraits::MutexType MutexType;
00046 typedef typename LockTraits::ReadLock ReadLock;
00047 typedef typename LockTraits::WriteLock WriteLock;
00048
00049 inline SignalBase()
00050 { }
00051
00052 inline ~SignalBase()
00053 {
00054
00055 typename SlotList::iterator i = _slots.begin();
00056 while(i != _slots.end())
00057 {
00058 delete *i;
00059 i = _slots.erase(i);
00060 }
00061 }
00062
00064 inline void bind(SlotType& slot)
00065 {
00066 WriteLock wl(_mutex);
00067 _slots.push_back(slot.clone());
00068 }
00069
00071 template <class UnbindSlotType>
00072 inline void unbind(UnbindSlotType& slot)
00073 {
00074 WriteLock wl(_mutex);
00075 typename SlotList::iterator i = _slots.begin();
00076 while(i != _slots.end())
00077 {
00078 UnbindSlotType* s = static_cast<UnbindSlotType*>(*i);
00079 if(s && *s == slot)
00080 {
00081 delete *i;
00082 _slots.erase(i);
00083 return;
00084 }
00085 ++i;
00086 }
00087 }
00088
00089 protected:
00090
00092 SlotList slotList()
00093 {
00094 ReadLock rl(_mutex);
00095 return _slots;
00096 }
00097
00098 private:
00099 SignalBase(const SignalBase&);
00100 SignalBase& operator=(const SignalBase&);
00101
00102 MutexType _mutex;
00103 SlotList _slots;
00104 };
00105
00106
00108
00112 template <class _RetT, class _Mutex = VoidMutex>
00113 class Signal0: public SignalBase<Slot0<_RetT>, _Mutex> {
00114 public:
00115 typedef _RetT RetType;
00116
00117 typedef SignalBase<
00118 Slot0<_RetT>,
00119 _Mutex
00120 > SignalBase;
00121
00123 RetType emit()
00124 {
00125 typedef typename SignalBase::SlotList SlotList;
00126 RetType ret = RetType();
00127 SlotList slots = slotList();
00128 for(typename SlotList::const_iterator i = slots.begin(); i != slots.end(); ++i) {
00129 ret = (*i)->proxy();
00130 if(ret)
00131 break;
00132 }
00133 return ret;
00134 }
00135 };
00136
00137
00138 #ifdef CXX_PARTIAL_SPECIALIZATION
00139
00141
00145 template <class _Mutex>
00146 class Signal0<void, _Mutex>: public SignalBase<Slot0<void>, _Mutex> {
00147 public:
00148 typedef SignalBase<
00149 Slot0<void>,
00150 _Mutex
00151 > SignalBase;
00152
00154 void emit()
00155 {
00156 typedef typename SignalBase::SlotList SlotList;
00157 SlotList slots = slotList();
00158 for(typename SlotList::const_iterator i = slots.begin(); i != slots.end(); ++i)
00159 (*i)->proxy();
00160 }
00161 };
00162
00163 #endif
00164
00165
00167
00171 template <class _RetT, class _ParamType1, class _Mutex = VoidMutex>
00172 class Signal1: public SignalBase<Slot1<_RetT, _ParamType1>, _Mutex> {
00173 public:
00174 typedef _RetT RetType;
00175
00176 typedef SignalBase<
00177 Slot1<_RetT, _ParamType1>,
00178 _Mutex
00179 > SignalBase;
00180
00182 RetType emit(_ParamType1 p1)
00183 {
00184 typedef typename SignalBase::SlotList SlotList;
00185 RetType ret = RetType();
00186 SlotList slots = slotList();
00187 for(typename SlotList::const_iterator i = slots.begin(); i != slots.end(); ++i)
00188 {
00189 ret = (*i)->proxy(p1);
00190 if(ret)
00191 break;
00192 }
00193 return ret;
00194 }
00195 };
00196
00197
00198 #ifdef CXX_PARTIAL_SPECIALIZATION
00199
00201
00205 template <class _ParamType1, class _Mutex>
00206 class Signal1<void, _ParamType1, _Mutex>:
00207 public SignalBase<Slot1<void, _ParamType1>, _Mutex>
00208 {
00209 public:
00210 typedef SignalBase<
00211 Slot1<void, _ParamType1>,
00212 _Mutex
00213 > SignalBase;
00214
00216 void emit(_ParamType1 p1)
00217 {
00218 typedef typename SignalBase::SlotList SlotList;
00219 SlotList slots = slotList();
00220 for(typename SlotList::const_iterator i = slots.begin(); i != slots.end(); ++i)
00221 (*i)->proxy(p1);
00222 }
00223 };
00224
00225 #endif
00226
00227
00229
00233 template <class _RetT, class _ParamType1, class _ParamType2, class _Mutex = VoidMutex>
00234 class Signal2:
00235 public SignalBase<Slot2<_RetT, _ParamType1, _ParamType2>, _Mutex>
00236 {
00237 public:
00238 typedef _RetT RetType;
00239
00240 typedef SignalBase<
00241 Slot2<_RetT, _ParamType1, _ParamType2>,
00242 _Mutex
00243 > SignalBase;
00244
00246 RetType emit(_ParamType1 p1, _ParamType2 p2)
00247 {
00248 typedef typename SignalBase::SlotList SlotList;
00249 RetType ret = RetType();
00250 SlotList slots = slotList();
00251 for(typename SlotList::const_iterator i = slots.begin(); i != slots.end(); ++i)
00252 {
00253 ret = (*i)->proxy(p1,p2);
00254 if(ret)
00255 break;
00256 }
00257 return ret;
00258 }
00259 };
00260
00261
00262 #ifdef CXX_PARTIAL_SPECIALIZATION
00263
00265
00269 template <class _ParamType1, class _ParamType2, class _Mutex>
00270 class Signal2<void, _ParamType1, _ParamType2, _Mutex>:
00271 public SignalBase<Slot2<void, _ParamType1, _ParamType2>, _Mutex>
00272 {
00273 public:
00274 typedef SignalBase<
00275 Slot2<void, _ParamType1, _ParamType2>,
00276 _Mutex
00277 > SignalBase;
00278
00280 void emit(_ParamType1 p1, _ParamType2 p2)
00281 {
00282 typedef typename SignalBase::SlotList SlotList;
00283 SlotList slots = slotList();
00284 for(typename SlotList::const_iterator i = slots.begin(); i != slots.end(); ++i)
00285 (*i)->proxy(p1,p2);
00286 }
00287 };
00288
00289 #endif
00290
00291
00293
00297 template <
00298 class _RetT, class _ParamType1, class _ParamType2,
00299 class _ParamType3, class _Mutex = VoidMutex
00300 >
00301 class Signal3:
00302 public SignalBase<Slot3<_RetT, _ParamType1, _ParamType2, _ParamType3>, _Mutex>
00303 {
00304 public:
00305 typedef _RetT RetType;
00306
00307 typedef SignalBase<
00308 Slot3<_RetT, _ParamType1, _ParamType2, _ParamType3>,
00309 _Mutex
00310 > SignalBase;
00311
00313 RetType emit(_ParamType1 p1, _ParamType2 p2, _ParamType3 p3)
00314 {
00315 typedef typename SignalBase::SlotList SlotList;
00316 RetType ret = RetType();
00317 SlotList slots = slotList();
00318 for(typename SlotList::const_iterator i = slots.begin(); i != slots.end(); ++i)
00319 {
00320 ret = (*i)->proxy(p1,p2,p3);
00321 if(ret)
00322 break;
00323 }
00324 return ret;
00325 }
00326 };
00327
00328
00329 #ifdef CXX_PARTIAL_SPECIALIZATION
00330
00332
00336 template <
00337 class _ParamType1, class _ParamType2,
00338 class _ParamType3, class _Mutex
00339 >
00340 class Signal3<void, _ParamType1, _ParamType2, _ParamType3, _Mutex>:
00341 public SignalBase<Slot3<void, _ParamType1, _ParamType2, _ParamType3>, _Mutex>
00342 {
00343 public:
00344 typedef SignalBase<
00345 Slot3<void, _ParamType1, _ParamType2, _ParamType3>,
00346 _Mutex
00347 > SignalBase;
00348
00350 void emit(_ParamType1 p1, _ParamType2 p2, _ParamType3 p3)
00351 {
00352 typedef typename SignalBase::SlotList SlotList;
00353 SlotList slots = slotList();
00354 for(typename SlotList::const_iterator i = slots.begin(); i != slots.end(); ++i)
00355 (*i)->proxy(p1,p2);
00356 }
00357 };
00358
00359 #endif
00360
00361
00363
00367 template <class _SignalT, class _SlotT>
00368 void bind(_SignalT& sig, _SlotT slot)
00369 { sig.bind(slot); }
00370
00372
00376 template <class _SignalT, class _SlotT>
00377 void unbind(_SignalT& sig, _SlotT slot)
00378 { sig.unbind(slot); }
00379
00380 }
00381
00382 #endif