gslot.h
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
20 
21 #ifndef G_SLOT_H
22 #define G_SLOT_H
23 
24 #include "gdef.h"
25 #include "gexception.h"
26 #include "gnoncopyable.h"
27 
29 namespace G
30 {
31 
38 class SlotBase
39 {
40 public:
41  SlotBase() ;
43 
44  virtual ~SlotBase() ;
46 
47  void up() ;
49 
50  void down() ;
53 
54 private:
55  SlotBase( const SlotBase & ) ; // not implemented
56  void operator=( const SlotBase & ) ; // not implemented
57 
58 private:
59  unsigned long m_ref_count ;
60 } ;
61 
66 class SignalImp
67 {
68 public:
69  G_EXCEPTION( AlreadyConnected , "signal already connected to a slot" ) ;
70  static void check( const SlotBase * p ) ;
71 private:
72  SignalImp() ; // not implemented
73 } ;
74 
79 template <typename T>
80 void swap_( T & t1 , T & t2 )
81 {
82  T temp( t1 ) ;
83  t1 = t2 ;
84  t2 = temp ;
85 }
86 
88 
94 template <typename T>
95 class SlotImp0 : public SlotBase
96 {
97 private:
98  T & m_object ;
99  void (T::*m_fn)() ;
100 public:
101  SlotImp0( T & object , void (T::*fn)() ) : m_object(object) , m_fn(fn) {}
102  void callback() { (m_object.*m_fn)() ; }
103 } ;
104 
108 template <typename T>
109 class SlotOp0
110 {
111 public:
112  static void callback( SlotBase * imp )
113  { static_cast<SlotImp0<T>*>(imp)->callback() ; }
114 } ;
115 
119 class Slot0
120 {
121 private:
122  SlotBase * m_imp ;
123  void (*m_op)( SlotBase * ) ;
124 public:
125  Slot0() : m_imp(0) , m_op(0) {}
126  Slot0( SlotBase * imp , void (*op)(SlotBase*) ) : m_imp(imp) , m_op(op) {}
127  ~Slot0() { if(m_imp) m_imp->down() ; }
128  void callback() { if( m_imp ) (*m_op)( m_imp ) ; }
129  Slot0( const Slot0 & other ) : m_imp(other.m_imp) , m_op(other.m_op) { if(m_imp) m_imp->up() ; }
130  void swap( Slot0 & rhs ) { swap_(m_imp,rhs.m_imp) ; swap_(m_op,rhs.m_op) ; }
131  void operator=( const Slot0 & rhs ) { Slot0 tmp(rhs) ; swap(tmp) ; }
132  const SlotBase * base() const { return m_imp ; }
133 } ;
134 
138 class Signal0 : public noncopyable
139 {
140 private:
141  bool m_emitted ;
142  bool m_once ;
143  Slot0 m_slot ;
144 public:
145  explicit Signal0( bool once = false ) : m_emitted(false) , m_once(once) {}
146  void emit() { if(!m_once||!m_emitted) { m_emitted = true ; m_slot.callback() ; } }
147  void connect( Slot0 slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
148  void disconnect() { m_slot = Slot0() ; }
149  void reset() { m_emitted = false ; }
150 } ;
151 
155 template <typename T>
156 Slot0 slot( T & object , void (T::*fn)() )
157 {
158  return Slot0( new SlotImp0<T>(object,fn) , SlotOp0<T>::callback ) ;
159 }
160 
162 
166 template <typename T, typename P>
167 class SlotImp1 : public SlotBase
168 {
169 private:
170  T & m_object ;
171  void (T::*m_fn)( P ) ;
172 public:
173  SlotImp1( T & object , void (T::*fn)(P) ) : m_object(object) , m_fn(fn) {}
174  void callback( P p ) { (m_object.*m_fn)(p) ; }
175 } ;
176 
180 template <typename T, typename P>
181 class SlotOp1
182 {
183 public:
184  static void callback( SlotBase * imp , P p )
185  { static_cast<SlotImp1<T,P>*>(imp)->callback( p ) ; }
186 } ;
187 
191 template <typename P>
192 class Slot1
193 {
194 private:
195  SlotBase * m_imp ;
196  void (*m_op)( SlotBase * , P ) ;
197 public:
198  Slot1() : m_imp(0) , m_op(0) {}
199  Slot1( SlotBase * imp , void (*op)(SlotBase*,P) ) : m_imp(imp) , m_op(op) {}
200  ~Slot1() { if( m_imp ) m_imp->down() ; }
201  void callback( P p ) { if( m_imp ) (*m_op)( m_imp , p ) ; }
202  Slot1( const Slot1<P> & other ) : m_imp(other.m_imp) , m_op(other.m_op) { if(m_imp) m_imp->up() ; }
203  void swap( Slot1<P> & rhs ) { swap_(m_imp,rhs.m_imp) ; swap_(m_op,rhs.m_op) ; }
204  void operator=( const Slot1<P> & rhs ) { Slot1 tmp(rhs) ; swap(tmp) ; }
205  const SlotBase * base() const { return m_imp ; }
206 } ;
207 
211 template <typename P>
212 class Signal1 : public noncopyable
213 {
214 private:
215  bool m_emitted ;
216  bool m_once ;
217  Slot1<P> m_slot ;
218 public:
219  explicit Signal1( bool once = false ) : m_emitted(false) , m_once(once) {}
220  void emit( P p ) { if(!m_once||!m_emitted) { m_emitted = true ; m_slot.callback( p ) ; } }
221  void connect( Slot1<P> slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
222  void disconnect() { m_slot = Slot1<P>() ; }
223  void reset() { m_emitted = false ; }
224 } ;
225 
229 template <typename T,typename P>
230 Slot1<P> slot( T & object , void (T::*fn)(P) )
231 {
232  return Slot1<P>( new SlotImp1<T,P>(object,fn) , SlotOp1<T,P>::callback ) ;
233 }
234 
236 
240 template <typename T, typename P1, typename P2>
241 class SlotImp2 : public SlotBase
242 {
243 private:
244  T & m_object ;
245  void (T::*m_fn)( P1 , P2 ) ;
246 public:
247  SlotImp2( T & object , void (T::*fn)(P1,P2) ) : m_object(object) , m_fn(fn) {}
248  void callback( P1 p1 , P2 p2 ) { (m_object.*m_fn)(p1,p2) ; }
249 } ;
250 
254 template <typename T, typename P1 , typename P2>
255 class SlotOp2
256 {
257 public:
258  static void callback( SlotBase * imp , P1 p1 , P2 p2 )
259  { static_cast<SlotImp2<T,P1,P2>*>(imp)->callback( p1 , p2 ) ; }
260 } ;
261 
265 template <typename P1, typename P2>
266 class Slot2
267 {
268 private:
269  SlotBase * m_imp ;
270  void (*m_op)( SlotBase * , P1 , P2 ) ;
271 public:
272  Slot2() : m_imp(0) , m_op(0) {}
273  Slot2( SlotBase * imp , void (*op)(SlotBase*,P1,P2) ) : m_imp(imp) , m_op(op) {}
274  ~Slot2() { if( m_imp ) m_imp->down() ; }
275  void callback( P1 p1 , P2 p2 ) { if( m_imp ) (*m_op)( m_imp , p1 , p2 ) ; }
276  Slot2( const Slot2<P1,P2> & other ) : m_imp(other.m_imp) , m_op(other.m_op) { if(m_imp) m_imp->up() ; }
277  void swap( Slot2<P1,P2> & rhs ) { swap_(m_imp,rhs.m_imp) ; swap_(m_op,rhs.m_op) ; }
278  void operator=( const Slot2<P1,P2> & rhs ) { Slot2 tmp(rhs) ; swap(tmp) ; }
279  const SlotBase * base() const { return m_imp ; }
280 } ;
281 
285 template <typename P1, typename P2>
286 class Signal2 : public noncopyable
287 {
288 private:
289  bool m_emitted ;
290  bool m_once ;
291  Slot2<P1,P2> m_slot ;
292 public:
293  explicit Signal2( bool once = false ) : m_emitted(false) , m_once(once) {}
294  void emit( P1 p1 , P2 p2 ) { if(!m_once||!m_emitted) { m_emitted = true ; m_slot.callback( p1 , p2 ) ; } }
295  void connect( Slot2<P1,P2> slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
296  void disconnect() { m_slot = Slot2<P1,P2>() ; }
297  void reset() { m_emitted = false ; }
298 } ;
299 
303 template <typename T, typename P1, typename P2>
304 Slot2<P1,P2> slot( T & object , void (T::*fn)(P1,P2) )
305 {
306  return Slot2<P1,P2>( new SlotImp2<T,P1,P2>(object,fn) , SlotOp2<T,P1,P2>::callback ) ;
307 }
308 
310 
314 template <typename T, typename P1, typename P2, typename P3>
315 class SlotImp3 : public SlotBase
316 {
317 private:
318  T & m_object ;
319  void (T::*m_fn)( P1 , P2 , P3 ) ;
320 public:
321  SlotImp3( T & object , void (T::*fn)(P1,P2,P3) ) : m_object(object) , m_fn(fn) {}
322  void callback( P1 p1 , P2 p2 , P3 p3 ) { (m_object.*m_fn)(p1,p2,p3) ; }
323 } ;
324 
328 template <typename T, typename P1 , typename P2, typename P3>
329 class SlotOp3
330 {
331 public:
332  static void callback( SlotBase * imp , P1 p1 , P2 p2 , P3 p3 )
333  { static_cast<SlotImp3<T,P1,P2,P3>*>(imp)->callback( p1 , p2 , p3 ) ; }
334 } ;
335 
339 template <typename P1, typename P2, typename P3>
340 class Slot3
341 {
342 private:
343  SlotBase * m_imp ;
344  void (*m_op)( SlotBase * , P1 , P2 , P3 ) ;
345 public:
346  Slot3() : m_imp(0) , m_op(0) {}
347  Slot3( SlotBase * imp , void (*op)(SlotBase*,P1,P2,P3) ) : m_imp(imp) , m_op(op) {}
348  ~Slot3() { if( m_imp ) m_imp->down() ; }
349  void callback( P1 p1 , P2 p2 , P3 p3 ) { if( m_imp ) (*m_op)( m_imp , p1 , p2 , p3 ) ; }
350  Slot3( const Slot3<P1,P2,P3> & other ) : m_imp(other.m_imp) , m_op(other.m_op) { if(m_imp) m_imp->up() ; }
351  void swap( Slot3<P1,P2,P3> & rhs ) { swap_(m_imp,rhs.m_imp) ; swap_(m_op,rhs.m_op) ; }
352  void operator=( const Slot3<P1,P2,P3> & rhs ) { Slot3 tmp(rhs) ; swap(tmp) ; }
353  const SlotBase * base() const { return m_imp ; }
354 } ;
355 
359 template <typename P1, typename P2, typename P3>
360 class Signal3 : public noncopyable
361 {
362 private:
363  bool m_emitted ;
364  bool m_once ;
365  Slot3<P1,P2,P3> m_slot ;
366 public:
367  explicit Signal3( bool once = false ) : m_emitted(false) , m_once(once) {}
368  void emit( P1 p1 , P2 p2 , P3 p3 ) { if(!m_once||!m_emitted) { m_emitted = true ; m_slot.callback( p1 , p2 , p3 ) ; }}
369  void connect( Slot3<P1,P2,P3> slot ) { SignalImp::check(m_slot.base()) ; m_slot = slot ; }
370  void disconnect() { m_slot = Slot3<P1,P2,P3>() ; }
371  void reset() { m_emitted = false ; }
372 } ;
373 
377 template <typename T, typename P1, typename P2, typename P3>
378 Slot3<P1,P2,P3> slot( T & object , void (T::*fn)(P1,P2,P3) )
379 {
381 }
382 
383 }
384 
385 #endif
386 
Slot1(const Slot1< P > &other)
Definition: gslot.h:202
void connect(Slot0 slot)
Definition: gslot.h:147
const SlotBase * base() const
Definition: gslot.h:205
SlotImp2(T &object, void(T::*fn)(P1, P2))
Definition: gslot.h:247
A noncopyable base class (a la boost).
Definition: gnoncopyable.h:35
void connect(Slot1< P > slot)
Definition: gslot.h:221
~Slot1()
Definition: gslot.h:200
Part of the slot/signal system.
Definition: gslot.h:286
Part of the slot/signal system.
Definition: gslot.h:266
Part of the slot/signal system.
Definition: gslot.h:255
SlotImp3(T &object, void(T::*fn)(P1, P2, P3))
Definition: gslot.h:321
Slot1(SlotBase *imp, void(*op)(SlotBase *, P))
Definition: gslot.h:199
const SlotBase * base() const
Definition: gslot.h:132
const SlotBase * base() const
Definition: gslot.h:353
Part of the slot/signal system.
Definition: gslot.h:315
void swap(Slot1< P > &rhs)
Definition: gslot.h:203
void disconnect()
Definition: gslot.h:148
Slot2()
Definition: gslot.h:272
Part of the slot/signal system.
Definition: gslot.h:38
void connect(Slot3< P1, P2, P3 > slot)
Definition: gslot.h:369
void swap(Slot3< P1, P2, P3 > &rhs)
Definition: gslot.h:351
Signal2(bool once=false)
Definition: gslot.h:293
void disconnect()
Definition: gslot.h:296
Slot0 slot(T &object, void(T::*fn)())
Part of the slot/signal system.
Definition: gslot.h:156
SlotImp0(T &object, void(T::*fn)())
Definition: gslot.h:101
Part of the slot/signal system.
Definition: gslot.h:212
void reset()
Definition: gslot.h:149
Part of the slot/signal system.
Definition: gslot.h:192
Slot1()
Definition: gslot.h:198
Part of the slot/signal system.
Definition: gslot.h:329
void emit(P1 p1, P2 p2)
Definition: gslot.h:294
static void callback(SlotBase *imp, P p)
Definition: gslot.h:184
Slot0(const Slot0 &other)
Definition: gslot.h:129
void emit(P p)
Definition: gslot.h:220
Part of the slot/signal system.
Definition: gslot.h:95
void operator=(const Slot3< P1, P2, P3 > &rhs)
Definition: gslot.h:352
void callback(P1 p1, P2 p2)
Definition: gslot.h:248
Signal1(bool once=false)
Definition: gslot.h:219
static void check(const SlotBase *p)
Definition: gslot.cpp:46
void callback()
Definition: gslot.h:128
void swap(Slot0 &rhs)
Definition: gslot.h:130
void callback(P p)
Definition: gslot.h:174
~Slot0()
Definition: gslot.h:127
static void callback(SlotBase *imp, P1 p1, P2 p2)
Definition: gslot.h:258
~Slot3()
Definition: gslot.h:348
Part of the slot/signal system.
Definition: gslot.h:340
SlotBase()
Default constuctor.
Definition: gslot.cpp:28
~Slot2()
Definition: gslot.h:274
Low-level classes.
void reset()
Definition: gslot.h:297
Slot3(SlotBase *imp, void(*op)(SlotBase *, P1, P2, P3))
Definition: gslot.h:347
void operator=(const Slot0 &rhs)
Definition: gslot.h:131
Slot2(SlotBase *imp, void(*op)(SlotBase *, P1, P2))
Definition: gslot.h:273
const SlotBase * base() const
Definition: gslot.h:279
static void callback(SlotBase *imp)
Definition: gslot.h:112
void swap_(T &t1, T &t2)
Part of the slot/signal system.
Definition: gslot.h:80
void callback(P p)
Definition: gslot.h:201
void callback()
Definition: gslot.h:102
Slot0(SlotBase *imp, void(*op)(SlotBase *))
Definition: gslot.h:126
void callback(P1 p1, P2 p2, P3 p3)
Definition: gslot.h:349
Part of the slot/signal system.
Definition: gslot.h:138
void callback(P1 p1, P2 p2, P3 p3)
Definition: gslot.h:322
Part of the slot/signal system.
Definition: gslot.h:119
Part of the slot/signal system.
Definition: gslot.h:109
void emit()
Definition: gslot.h:146
Slot3()
Definition: gslot.h:346
Slot2(const Slot2< P1, P2 > &other)
Definition: gslot.h:276
void operator=(const Slot2< P1, P2 > &rhs)
Definition: gslot.h:278
Part of the slot/signal system.
Definition: gslot.h:360
void reset()
Definition: gslot.h:371
void emit(P1 p1, P2 p2, P3 p3)
Definition: gslot.h:368
#define G_EXCEPTION(class_name, description)
define as a function rather than a type if optimising for size
Definition: gexception.h:93
void disconnect()
Definition: gslot.h:370
virtual ~SlotBase()
Destructor.
Definition: gslot.cpp:24
void reset()
Definition: gslot.h:223
void down()
Decrements the reference count and does "delete this" on zero.
Definition: gslot.cpp:37
void operator=(const Slot1< P > &rhs)
Definition: gslot.h:204
void swap(Slot2< P1, P2 > &rhs)
Definition: gslot.h:277
Part of the slot/signal system.
Definition: gslot.h:241
static void callback(SlotBase *imp, P1 p1, P2 p2, P3 p3)
Definition: gslot.h:332
Slot0()
Definition: gslot.h:125
void up()
Increments the reference count.
Definition: gslot.cpp:32
Slot3(const Slot3< P1, P2, P3 > &other)
Definition: gslot.h:350
Part of the slot/signal system.
Definition: gslot.h:181
void connect(Slot2< P1, P2 > slot)
Definition: gslot.h:295
Signal3(bool once=false)
Definition: gslot.h:367
Part of the slot/signal system.
Definition: gslot.h:66
void disconnect()
Definition: gslot.h:222
SlotImp1(T &object, void(T::*fn)(P))
Definition: gslot.h:173
void callback(P1 p1, P2 p2)
Definition: gslot.h:275
Signal0(bool once=false)
Definition: gslot.h:145
Part of the slot/signal system.
Definition: gslot.h:167