Merge "Fixed test case to match new stencil hit rules" into tizen
[platform/core/uifw/dali-core.git] / dali / public-api / signals / base-signal.h
1 #ifndef __DALI_BASE_SIGNAL_H__
2 #define __DALI_BASE_SIGNAL_H__
3
4 /*
5  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // INTERNAL INCLUDES
22 #include <dali/public-api/common/dali-common.h>
23 #include <dali/public-api/common/dali-vector.h>
24 #include <dali/public-api/signals/callback.h>
25 #include <dali/public-api/signals/connection-tracker-interface.h>
26 #include <dali/public-api/signals/signal-slot-connections.h>
27
28 namespace Dali DALI_IMPORT_API
29 {
30
31 /**
32  * @brief Implementation class for Dali::SignalV2%s.
33  *
34  * A slot can be connected to many signals
35  * A signal can be connected to many slots
36  *
37  * To provide automatic disconnection when either a signal or the object owning the slot dies,
38  * observers are used.
39  *
40  * A signal is an object with state. It holds a list of SignalConnection%s.
41  *
42  * E.g.
43  *  Signal OnTouch. mSignalConnections contains
44  * <table>
45  * <tr><td> %Callback 0 </td><td> Signal Observer 0  </td></tr>
46  * <tr><td> %Callback 1 </td><td> Signal Observer 1  </td></tr>
47  * <tr><td> %Callback 2 </td><td> Signal Observer 2  </td></tr>
48  * </table>
49  *
50  * OnTouch.Emit() will run callbacks 0, 1 and 2.
51  *
52  * When the signal is destroyed. SignalDisconnected() is called on each Signal Observer.
53  *
54  * Slots are just static or member functions, so have no state. E.g. they can't keep
55  * track of how many signals they are connected to.
56  * If the object owning a slot dies, it must automatically disconnected from all signals.
57  * If it doesn't disconnect and the signal is emitted, there will be a crash.
58  *
59  * To keep track of connections between slots and signals, a Connection tracker is used.
60  * It holds a list of SlotConnections.
61  *
62  * <table>
63  * <tr><td> %Callback 0 </td><td> Slot Observer 0  </td></tr>
64  * <tr><td> %Callback 1 </td><td> Slot Observer 1  </td></tr>
65  * <tr><td> %Callback 2 </td><td> Slot Observer 2  </td></tr>
66  * </table>
67  *
68  * When the connection tracker is destroyed, SlotDisconnected() is called on every slot observer ( signal )
69  * Signals implement the Slot Observer interface, to be told when a slot has disconnected
70  * Connection tracker implements the Signal Observer interface, to be told when a signal has disconnected (died)
71  *
72  */
73 class BaseSignal : public SlotObserver
74 {
75 public:
76
77   /**
78    * @brief Constructor.
79    */
80   BaseSignal();
81
82   /**
83    * @brief Virtual destructor.
84    */
85   virtual ~BaseSignal();
86
87   /**
88    * @brief Query whether there are any connected slots.
89    *
90    * @return True if there are any slots connected to the signal.
91    */
92   bool Empty() const;
93
94   /**
95    * @brief Query the number of slots.
96    *
97    * @return The number of slots connected to this signal.
98    */
99   std::size_t GetConnectionCount() const;
100
101   // Templated Emit functions for the Signal implementations
102
103   /**
104    * @brief Used to guard against nested Emit() calls.
105    */
106   struct EmitGuard
107   {
108     /**
109      * @brief Create the guard.
110      *
111      * @param[in,out] flag This flag will be set to true during Emit() calls.
112      */
113     EmitGuard( bool& flag );
114
115     /**
116      * @brief Non-virtual destructor.
117      *
118      */
119     ~EmitGuard();
120
121     /**
122      * @brief  Determine if an error occured.
123      *
124      * @return True if an error occurred i.e. if Emit() was called during Emit()
125      */
126     bool ErrorOccurred();
127
128     bool* mFlag; ///< Pointer to the emit guard flag.
129   };
130
131   /**
132    * @brief Emit a signal with no parameters.
133    *
134    * @pre Cannot be called from inside the same Signal's Emit methods.
135    */
136   void Emit();
137
138   /**
139    * @brief Emit a signal with no parameters.
140    *
141    * @pre Cannot be called from inside the same Signal's Emit methods.
142    * @return The value returned by the last callback.
143    */
144   template< typename Ret >
145   Ret EmitReturn()
146   {
147     Ret returnVal = Ret();
148
149     // Guards against nested Emit() calls
150     EmitGuard guard( mEmittingFlag );
151     if( guard.ErrorOccurred() )
152     {
153       return returnVal;
154     }
155
156     // If more connections are added by callbacks, these are ignore until the next Emit()
157     // Note that count cannot be reduced while iterating
158     const std::size_t initialCount( mSignalConnections.Count() );
159
160     for( std::size_t i = 0; i < initialCount; ++i )
161     {
162       CallbackBase* callback( GetCallback(i) );
163
164       // Note that connections will be set to NULL when disconnected
165       // This is preferable to reducing the connection count while iterating
166       if( callback )
167       {
168         returnVal = CallbackBase::ExecuteReturn<Ret>( *callback );
169       }
170     }
171
172     // Cleanup NULL values from Connection container
173     CleanupConnections();
174
175     return returnVal;
176   }
177
178   /**
179    * @brief Emit a signal with 1 parameter.
180    *
181    * @pre Cannot be called from inside the same Signal's Emit methods.
182    * @param[in] arg0 The first parameter.
183    */
184   template< typename Arg0 >
185   void Emit( Arg0 arg0 )
186   {
187     // Guards against nested Emit() calls
188     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
189     if( guard.ErrorOccurred() )
190     {
191       return;
192     }
193
194     // If more connections are added by callbacks, these are ignore until the next Emit()
195     // Note that count cannot be reduced while iterating
196     const std::size_t initialCount( mSignalConnections.Count() );
197
198     for( std::size_t i = 0; i < initialCount; ++i )
199     {
200       CallbackBase* callback( GetCallback(i) );
201
202       // Note that connections will be set to NULL when disconnected
203       // This is preferable to reducing the connection count while iterating
204       if( callback )
205       {
206         CallbackBase::Execute<Arg0 >( *callback, arg0 );
207       }
208     }
209
210     // Cleanup NULL values from Connection container
211     CleanupConnections();
212   }
213
214   /**
215    * @brief Emit a signal with 1 parameter.
216    *
217    * @pre Cannot be called from inside the same Signal's Emit methods.
218    * @param[in] arg0 The first parameter.
219    * @return The value returned by the last callback.
220    */
221   template< typename Ret, typename Arg0 >
222   Ret EmitReturn( Arg0 arg0 )
223   {
224     Ret returnVal = Ret();
225
226     // Guards against nested Emit() calls
227     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
228     if( guard.ErrorOccurred() )
229     {
230       return returnVal;
231     }
232
233     // If more connections are added by callbacks, these are ignore until the next Emit()
234     // Note that count cannot be reduced while iterating
235     const std::size_t initialCount( mSignalConnections.Count() );
236
237     for( std::size_t i = 0; i < initialCount; ++i )
238     {
239       CallbackBase* callback( GetCallback(i) );
240
241       // Note that connections will be set to NULL when disconnected
242       // This is preferable to reducing the connection count while iterating
243       if( callback )
244       {
245         returnVal = CallbackBase::ExecuteReturn<Ret,Arg0>( *callback, arg0 );
246       }
247     }
248
249     // Cleanup NULL values from Connection container
250     CleanupConnections();
251
252     return returnVal;
253   }
254
255   /**
256    * @brief Emit a signal with 2 parameters.
257    *
258    * @pre Cannot be called from inside the same Signal's Emit methods.
259    * @param[in] arg0 The first parameter.
260    * @param[in] arg1 The second parameter.
261    */
262   template< typename Arg0, typename Arg1 >
263   void Emit( Arg0 arg0, Arg1 arg1 )
264   {
265     // Guards against nested Emit() calls
266     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
267     if( guard.ErrorOccurred() )
268     {
269       return;
270     }
271
272     // If more connections are added by callbacks, these are ignore until the next Emit()
273     // Note that count cannot be reduced while iterating
274     const std::size_t initialCount( mSignalConnections.Count() );
275
276     for( std::size_t i = 0; i < initialCount; ++i )
277     {
278       CallbackBase* callback( GetCallback(i) );
279
280       // Note that connections will be set to NULL when disconnected
281       // This is preferable to reducing the connection count while iterating
282       if( callback )
283       {
284         CallbackBase::Execute<Arg0,Arg1>( *callback, arg0, arg1 );
285       }
286     }
287
288     // Cleanup NULL values from Connection container
289     CleanupConnections();
290   }
291
292   /**
293    * @brief Emit a signal with 2 parameters.
294    *
295    * @pre Cannot be called from inside the same Signal's Emit methods.
296    * @param[in] arg0 The first parameter.
297    * @param[in] arg1 The second parameter.
298    * @return The value returned by the last callback.
299    */
300   template< typename Ret, typename Arg0, typename Arg1 >
301   Ret EmitReturn( Arg0 arg0, Arg1 arg1 )
302   {
303     Ret returnVal = Ret();
304
305     // Guards against nested Emit() calls
306     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
307     if( guard.ErrorOccurred() )
308     {
309       return returnVal;
310     }
311
312     // If more connections are added by callbacks, these are ignore until the next Emit()
313     // Note that count cannot be reduced while iterating
314     const std::size_t initialCount( mSignalConnections.Count() );
315
316     for( std::size_t i = 0; i < initialCount; ++i )
317     {
318       CallbackBase* callback( GetCallback(i) );
319
320       // Note that connections will be set to NULL when disconnected
321       // This is preferable to reducing the connection count while iterating
322       if( callback )
323       {
324         returnVal = CallbackBase::ExecuteReturn<Ret,Arg0,Arg1>( *callback, arg0, arg1 );
325       }
326     }
327
328     // Cleanup NULL values from Connection container
329     CleanupConnections();
330
331     return returnVal;
332   }
333
334   /**
335    * @brief Emit a signal with 3 parameters.
336    *
337    * @pre Cannot be called from inside the same Signal's Emit methods.
338    * @param[in] arg0 The first parameter.
339    * @param[in] arg1 The second parameter.
340    * @param[in] arg2 The third parameter.
341    */
342   template< typename Arg0, typename Arg1, typename Arg2 >
343   void Emit( Arg0 arg0, Arg1 arg1, Arg2 arg2 )
344   {
345     // Guards against nested Emit() calls
346     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
347     if( guard.ErrorOccurred() )
348     {
349       return;
350     }
351
352     // If more connections are added by callbacks, these are ignore until the next Emit()
353     // Note that count cannot be reduced while iterating
354     const std::size_t initialCount( mSignalConnections.Count() );
355
356     for( std::size_t i = 0; i < initialCount; ++i )
357     {
358       CallbackBase* callback( GetCallback(i) );
359
360       // Note that connections will be set to NULL when disconnected
361       // This is preferable to reducing the connection count while iterating
362       if( callback )
363       {
364         CallbackBase::Execute<Arg0,Arg1,Arg2>( *callback, arg0, arg1, arg2 );
365       }
366     }
367
368     // Cleanup NULL values from Connection container
369     CleanupConnections();
370   }
371
372   /**
373    * @brief Emit a signal with 3 parameters.
374    *
375    * @pre Cannot be called from inside the same Signal's Emit methods.
376    * @param[in] arg0 The first parameter.
377    * @param[in] arg1 The second parameter.
378    * @param[in] arg2 The third parameter.
379    * @return The value returned by the last callback.
380    */
381   template< typename Ret, typename Arg0, typename Arg1, typename Arg2 >
382   Ret EmitReturn( Arg0 arg0, Arg1 arg1, Arg2 arg2 )
383   {
384     Ret returnVal = Ret();
385
386     // Guards against nested Emit() calls
387     EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
388     if( guard.ErrorOccurred() )
389     {
390       return returnVal;
391     }
392
393     // If more connections are added by callbacks, these are ignore until the next Emit()
394     // Note that count cannot be reduced while iterating
395     const std::size_t initialCount( mSignalConnections.Count() );
396
397     for( std::size_t i = 0; i < initialCount; ++i )
398     {
399       CallbackBase* callback( GetCallback(i) );
400
401       // Note that connections will be set to NULL when disconnected
402       // This is preferable to reducing the connection count while iterating
403       if( callback )
404       {
405         returnVal = CallbackBase::ExecuteReturn<Ret,Arg0,Arg1,Arg2>( *callback, arg0, arg1, arg2 );
406       }
407     }
408
409     // Cleanup NULL values from Connection container
410     CleanupConnections();
411
412     return returnVal;
413   }
414
415   // Connect / Disconnect function for use by Signal implementations
416
417   /**
418    * @brief Called by Signal implementations, when the user calls Signal.Connect( ... )
419    *
420    * @param[in] callback A newly allocated callback object (takes ownership).
421    */
422   void OnConnect( CallbackBase* callback );
423
424   /**
425    * @brief Called by Signal implementations, when the user calls Signal.Disconnect( ... )
426    *
427    * @param[in] callback A newly allocated callback object (takes ownership).
428    */
429   void OnDisconnect( CallbackBase* callback );
430
431   /**
432    * @brief Called by Signal implementations, when the user calls Signal.Connect( ... )
433    *
434    * @param[in] tracker The connection tracker.
435    * @param[in] callback A newly allocated callback object (takes ownership).
436    */
437   void OnConnect( ConnectionTrackerInterface* tracker, CallbackBase* callback );
438
439   /**
440    * @brief Called by Signal implementations, when the user calls Signal.Disconnect( ... )
441    *
442    * @param[in] tracker The connection tracker.
443    * @param[in] callback A newly allocated callback object (takes ownership).
444    */
445   void OnDisconnect( ConnectionTrackerInterface* tracker, CallbackBase* callback );
446
447 private: // SlotObserver interface, to be told when a slot disconnects
448
449   /**
450    * @copydoc SlotObserver::SlotDisconnected
451    */
452   virtual void SlotDisconnected( CallbackBase* callback );
453
454 private:
455
456   /**
457    * @brief Returns a callback given an index in to the connection array.
458    *
459    * @param[in] connectionIndex The index of the callback.
460    * @return The callback, or NULL if the connection has been deleted.
461    */
462   CallbackBase* GetCallback( std::size_t connectionIndex ) const;
463
464   /**
465    * @brief Helper to find whether a callback is connected.
466    *
467    * @param[in] callback The call back object.
468    * @return A valid index if the callback is connected.
469    */
470   int FindCallback( CallbackBase* callback );
471
472   /**
473    * @brief Deletes a connection object from the list of connections.
474    *
475    * @param[in] connectionIndex The index of the callback.
476    */
477   void DeleteConnection( std::size_t connectionIndex );
478
479   /**
480    * @brief Helper to remove NULL items from mSignalConnections, which is only safe at the end of Emit()
481    * i.e. not from methods which can be called during a signal Emit(), such as Disconnect().
482    */
483   void CleanupConnections();
484
485   BaseSignal( const BaseSignal& );                   ///< undefined copy constructor, signals don't support copying.
486   BaseSignal& operator=( const BaseSignal& );        ///< undefined assignment operator
487
488 private:
489
490   Dali::Vector< SignalConnection* > mSignalConnections;   ///< Array of connections
491
492   bool mEmittingFlag; ///< Used to guard against nested Emit() calls
493 };
494
495 } // namespace Dali
496
497 #endif // __DALI_BASE_SIGNAL_H__