8c7ff90ca5ed42317157b947d6f5aac886ab9d56
[platform/core/uifw/dali-core.git] / dali / internal / common / message.h
1 #ifndef __DALI_INTERNAL_MESSAGE_H__
2 #define __DALI_INTERNAL_MESSAGE_H__
3
4 /*
5  * Copyright (c) 2017 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 #include <typeinfo>
22
23 // INTERNAL INCLUDES
24 #include <dali/internal/common/buffer-index.h>
25 #include <dali/internal/common/type-abstraction.h>
26 #include <dali/internal/update/common/scene-graph-buffers.h>
27 #include <dali/integration-api/debug.h>
28
29 namespace Dali
30 {
31
32 namespace Internal
33 {
34
35 /**
36  * An abstract base class for messages queued across threads.
37  * Messages are only allowed to contain value objects, either copies of the parameters or pointers
38  * If message parameter type is & or const& the message will try to take a copy of the actual type
39  */
40 class MessageBase
41 {
42 public:
43
44   /**
45    * Construct the message base.
46    */
47   MessageBase( )
48   {
49   }
50
51   /**
52    * Virtual destructor
53    */
54   virtual ~MessageBase()
55   {
56   }
57
58   /**
59    * Called to process the message.
60    * @param [in] bufferIndex The current update/render buffer index (depending on which thread processes the message).
61    */
62   virtual void Process( BufferIndex bufferIndex ) = 0;
63
64 private:
65 };
66
67 /**
68  * Templated message which calls a member function of an object.
69  * This allows nodes etc. to be modified in a thread-safe manner, when the update occurs in a separate thread.
70  * The object lifetime must controlled i.e. not destroyed before the message is processed.
71  */
72 template< typename T >
73 class Message : public MessageBase
74 {
75 public:
76
77   typedef void(T::*MemberFunction)();
78
79   /**
80    * Create a message.
81    * @note The object is expected to be const in the thread which sends this message.
82    * However it can be modified when Process() is called in a different thread.
83    * @param[in] obj The object to be updated in a separate thread.
84    * @param[in] member The member function of the object.
85    */
86   Message( const T* obj, MemberFunction member )
87   : MessageBase(),
88     object( const_cast< T* >( obj ) ),
89     memberFunction( member )
90   {
91   }
92
93   /**
94    * Virtual destructor
95    */
96   virtual ~Message()
97   {
98   }
99
100   /**
101    * @copydoc MessageBase::Process
102    */
103   virtual void Process( BufferIndex /*bufferIndex*/ )
104   {
105     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
106
107     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
108
109     (object->*memberFunction)();
110   }
111
112 private:
113
114   T* object;
115   MemberFunction memberFunction;
116
117 };
118
119 /**
120  * Templated message which calls a member function of an object.
121  * This overload passes one value-type parameter.
122  * Template parameters need to match the MemberFunction!
123  * The message will contain copy of the value (in case of & or const&)
124  */
125 template< typename T, typename P >
126 class MessageValue1 : public MessageBase
127 {
128 public:
129
130   typedef void(T::*MemberFunction)( typename ParameterType< P >::PassingType );
131
132   /**
133    * Create a message.
134    * @note The object is expected to be const in the thread which sends this message.
135    * However it can be modified when Process() is called in a different thread.
136    * @param[in] obj The object.
137    * @param[in] member The member function of the object.
138    * @param[in] p1 The first value-type parameter to pass to the member function.
139    */
140   MessageValue1( const T* obj,
141                  MemberFunction member,
142                  typename ParameterType< P >::PassingType p1 )
143   : MessageBase(),
144     object( const_cast< T* >( obj ) ),
145     memberFunction( member ),
146     param1( p1 )
147   {
148   }
149
150   /**
151    * Virtual destructor
152    */
153   virtual ~MessageValue1()
154   {
155   }
156
157   /**
158    * @copydoc MessageBase::Process
159    */
160   virtual void Process( BufferIndex /*bufferIndex*/ )
161   {
162     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
163
164     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
165
166     (object->*memberFunction)( param1 );
167   }
168
169 private:
170
171   T* object;
172   MemberFunction memberFunction;
173   typename ParameterType< P >::HolderType param1;
174
175 };
176
177 /**
178  * Templated message which calls a member function of an object.
179  * This overload passes two value-type parameters.
180  * Template parameters need to match the MemberFunction!
181  * The message will contain copy of the value (in case of & or const&)
182  */
183
184 template< typename T, typename P1, typename P2 >
185 class MessageValue2 : public MessageBase
186 {
187 public:
188
189   typedef void(T::*MemberFunction)(
190       typename ParameterType< P1 >::PassingType,
191       typename ParameterType< P2 >::PassingType );
192
193   /**
194    * Create a message.
195    * @note The object is expected to be const in the thread which sends this message.
196    * However it can be modified when Process() is called in a different thread.
197    * @param[in] obj The object.
198    * @param[in] member The member function of the object.
199    * @param[in] p1 The first parameter to pass to the member function.
200    * @param[in] p2 The second parameter to pass to the member function.
201    */
202   MessageValue2( const T* obj,
203                  MemberFunction member,
204                  typename ParameterType< P1 >::PassingType p1,
205                  typename ParameterType< P2 >::PassingType p2 )
206   : MessageBase(),
207     object( const_cast< T* >( obj ) ),
208     memberFunction( member ),
209     param1( p1 ),
210     param2( p2 )
211   {
212   }
213
214   /**
215    * Virtual destructor
216    */
217   virtual ~MessageValue2()
218   {
219   }
220
221   /**
222    * @copydoc MessageBase::Process
223    */
224   virtual void Process( BufferIndex /*bufferIndex*/ )
225   {
226     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
227
228     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
229
230     (object->*memberFunction)( param1, param2 );
231   }
232
233 private:
234
235   T* object;
236   MemberFunction memberFunction;
237   typename ParameterType< P1 >::HolderType param1;
238   typename ParameterType< P2 >::HolderType param2;
239
240 };
241
242 /**
243  * Templated message which calls a member function of an object.
244  * This overload passes three value-type parameters.
245  * Template parameters need to match the MemberFunction!
246  * The message will contain copy of the value (in case of & or const&)
247  */
248 template< typename T, typename P1, typename P2, typename P3 >
249 class MessageValue3 : public MessageBase
250 {
251 public:
252
253   typedef void(T::*MemberFunction)(
254       typename ParameterType< P1 >::PassingType,
255       typename ParameterType< P2 >::PassingType,
256       typename ParameterType< P3 >::PassingType );
257
258   /**
259    * Create a message.
260    * @note The object is expected to be const in the thread which sends this message.
261    * However it can be modified when Process() is called in a different thread.
262    * @param[in] obj The object.
263    * @param[in] member The member function of the object.
264    * @param[in] p1 The first parameter to pass to the member function.
265    * @param[in] p2 The second parameter to pass to the member function.
266    * @param[in] p3 The third parameter to pass to the member function.
267    */
268   MessageValue3( const T* obj,
269                  MemberFunction member,
270                  typename ParameterType< P1 >::PassingType p1,
271                  typename ParameterType< P2 >::PassingType p2,
272                  typename ParameterType< P3 >::PassingType p3 )
273   : MessageBase(),
274     object( const_cast< T* >( obj ) ),
275     memberFunction( member ),
276     param1( p1 ),
277     param2( p2 ),
278     param3( p3 )
279   {
280   }
281
282   /**
283    * Virtual destructor
284    */
285   virtual ~MessageValue3()
286   {
287   }
288
289   /**
290    * @copydoc MessageBase::Process
291    */
292   virtual void Process( BufferIndex /*bufferIndex*/ )
293   {
294     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
295
296     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
297
298     (object->*memberFunction)( param1, param2, param3 );
299   }
300
301 private:
302
303   T* object;
304   MemberFunction memberFunction;
305   typename ParameterType< P1 >::HolderType param1;
306   typename ParameterType< P2 >::HolderType param2;
307   typename ParameterType< P3 >::HolderType param3;
308
309 };
310
311 /**
312  * Templated message which calls a member function of an object.
313  * This overload passes four value-type parameters.
314  * Template parameters need to match the MemberFunction!
315  * The message will contain copy of the value (in case of & or const&)
316  */
317 template< typename T, typename P1, typename P2, typename P3, typename P4 >
318 class MessageValue4 : public MessageBase
319 {
320 public:
321
322   typedef void(T::*MemberFunction)(
323       typename ParameterType< P1 >::PassingType,
324       typename ParameterType< P2 >::PassingType,
325       typename ParameterType< P3 >::PassingType,
326       typename ParameterType< P4 >::PassingType );
327
328   /**
329    * Create a message.
330    * @note The object is expected to be const in the thread which sends this message.
331    * However it can be modified when Process() is called in a different thread.
332    * @param[in] obj The object.
333    * @param[in] member The member function of the object.
334    * @param[in] p1 The first parameter to pass to the member function.
335    * @param[in] p2 The second parameter to pass to the member function.
336    * @param[in] p3 The third parameter to pass to the member function.
337    * @param[in] p4 The fourth parameter to pass to the member function.
338    */
339   MessageValue4( const T* obj,
340                  MemberFunction member,
341                  typename ParameterType< P1 >::PassingType p1,
342                  typename ParameterType< P2 >::PassingType p2,
343                  typename ParameterType< P3 >::PassingType p3,
344                  typename ParameterType< P4 >::PassingType p4 )
345   : MessageBase(),
346     object( const_cast< T* >( obj ) ),
347     memberFunction( member ),
348     param1( p1 ),
349     param2( p2 ),
350     param3( p3 ),
351     param4( p4 )
352   {
353   }
354
355   /**
356    * Virtual destructor
357    */
358   virtual ~MessageValue4()
359   {
360   }
361
362   /**
363    * @copydoc MessageBase::Process
364    */
365   virtual void Process( BufferIndex /*bufferIndex*/ )
366   {
367     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
368
369     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
370
371     (object->*memberFunction)( param1, param2, param3, param4 );
372   }
373
374 private:
375
376   T* object;
377   MemberFunction memberFunction;
378   typename ParameterType< P1 >::HolderType param1;
379   typename ParameterType< P2 >::HolderType param2;
380   typename ParameterType< P3 >::HolderType param3;
381   typename ParameterType< P4 >::HolderType param4;
382
383 };
384
385 /**
386  * Templated message which calls a member function of an object.
387  * This overload passes five value-type parameters.
388  * Template parameters need to match the MemberFunction!
389  * The message will contain copy of the value (in case of & or const&)
390  */
391 template< typename T, typename P1, typename P2, typename P3, typename P4, typename P5 >
392 class MessageValue5 : public MessageBase
393 {
394 public:
395
396   typedef void(T::*MemberFunction)(
397       typename ParameterType< P1 >::PassingType,
398       typename ParameterType< P2 >::PassingType,
399       typename ParameterType< P3 >::PassingType,
400       typename ParameterType< P4 >::PassingType,
401       typename ParameterType< P5 >::PassingType );
402
403   /**
404    * Create a message.
405    * @note The object is expected to be const in the thread which sends this message.
406    * However it can be modified when Process() is called in a different thread.
407    * @param[in] obj The object.
408    * @param[in] member The member function of the object.
409    * @param[in] p1 The first parameter to pass to the member function.
410    * @param[in] p2 The second parameter to pass to the member function.
411    * @param[in] p3 The third parameter to pass to the member function.
412    * @param[in] p4 The fourth parameter to pass to the member function.
413    * @param[in] p5 The fifth parameter to pass to the member function.
414    */
415   MessageValue5( const T* obj,
416                  MemberFunction member,
417                  typename ParameterType< P1 >::PassingType p1,
418                  typename ParameterType< P2 >::PassingType p2,
419                  typename ParameterType< P3 >::PassingType p3,
420                  typename ParameterType< P4 >::PassingType p4,
421                  typename ParameterType< P5 >::PassingType p5 )
422   : MessageBase(),
423     object( const_cast< T* >( obj ) ),
424     memberFunction( member ),
425     param1( p1 ),
426     param2( p2 ),
427     param3( p3 ),
428     param4( p4 ),
429     param5( p5 )
430   {
431   }
432
433   /**
434    * Virtual destructor
435    */
436   virtual ~MessageValue5()
437   {
438   }
439
440   /**
441    * @copydoc MessageBase::Process
442    */
443   virtual void Process( BufferIndex /*bufferIndex*/ )
444   {
445     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
446
447     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
448
449     (object->*memberFunction)( param1, param2, param3, param4, param5 );
450
451   }
452
453 private:
454
455   T* object;
456   MemberFunction memberFunction;
457   typename ParameterType< P1 >::HolderType param1;
458   typename ParameterType< P2 >::HolderType param2;
459   typename ParameterType< P3 >::HolderType param3;
460   typename ParameterType< P4 >::HolderType param4;
461   typename ParameterType< P5 >::HolderType param5;
462
463 };
464
465 /**
466  * Templated message which calls a member function of an object.
467  * This overload passes six value-type parameters.
468  * Template parameters need to match the MemberFunction!
469  * The message will contain copy of the value (in case of & or const&)
470  */
471 template< typename T, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6 >
472 class MessageValue6 : public MessageBase
473 {
474 public:
475
476   typedef void(T::*MemberFunction)(
477       typename ParameterType< P1 >::PassingType,
478       typename ParameterType< P2 >::PassingType,
479       typename ParameterType< P3 >::PassingType,
480       typename ParameterType< P4 >::PassingType,
481       typename ParameterType< P5 >::PassingType,
482       typename ParameterType< P6 >::PassingType );
483
484   /**
485    * Create a message.
486    * @note The object is expected to be const in the thread which sends this message.
487    * However it can be modified when Process() is called in a different thread.
488    * @param[in] obj The object.
489    * @param[in] member The member function of the object.
490    * @param[in] p1 The first parameter to pass to the member function.
491    * @param[in] p2 The second parameter to pass to the member function.
492    * @param[in] p3 The third parameter to pass to the member function.
493    * @param[in] p4 The fourth parameter to pass to the member function.
494    * @param[in] p5 The fifth parameter to pass to the member function.
495    * @param[in] p6 The sixth parameter to pass to the member function.
496    */
497   MessageValue6( const T* obj,
498                  MemberFunction member,
499                  typename ParameterType< P1 >::PassingType p1,
500                  typename ParameterType< P2 >::PassingType p2,
501                  typename ParameterType< P3 >::PassingType p3,
502                  typename ParameterType< P4 >::PassingType p4,
503                  typename ParameterType< P5 >::PassingType p5,
504                  typename ParameterType< P6 >::PassingType p6 )
505   : MessageBase(),
506     object( const_cast< T* >( obj ) ),
507     memberFunction( member ),
508     param1( p1 ),
509     param2( p2 ),
510     param3( p3 ),
511     param4( p4 ),
512     param5( p5 ),
513     param6( p6 )
514   {
515   }
516
517   /**
518    * Virtual destructor
519    */
520   virtual ~MessageValue6()
521   {
522   }
523
524   /**
525    * @copydoc MessageBase::Process
526    */
527   virtual void Process( BufferIndex /*bufferIndex*/ )
528   {
529     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
530
531     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
532
533     (object->*memberFunction)( param1, param2, param3, param4, param5, param6 );
534
535   }
536
537 private:
538
539   T* object;
540   MemberFunction memberFunction;
541   typename ParameterType< P1 >::HolderType param1;
542   typename ParameterType< P2 >::HolderType param2;
543   typename ParameterType< P3 >::HolderType param3;
544   typename ParameterType< P4 >::HolderType param4;
545   typename ParameterType< P5 >::HolderType param5;
546   typename ParameterType< P6 >::HolderType param6;
547
548 };
549
550 /**
551  * Templated message which calls a member function of an object.
552  * This overload passes just the buffer index to the method, no parameters.
553  */
554 template< typename T >
555 class MessageDoubleBuffered0 : public MessageBase
556 {
557 public:
558
559   typedef void(T::*MemberFunction)( BufferIndex );
560
561   /**
562    * Create a message.
563    * @note The object is expected to be const in the thread which sends this message.
564    * However it can be modified when Process() is called in a different thread.
565    * @param[in] obj The object.
566    * @param[in] member The member function of the object.
567    */
568   MessageDoubleBuffered0( const T* obj, MemberFunction member )
569   : MessageBase(),
570     object( const_cast< T* >( obj ) ),
571     memberFunction( member )
572   {
573   }
574
575   /**
576    * Virtual destructor
577    */
578   virtual ~MessageDoubleBuffered0()
579   {
580   }
581
582   /**
583    * @copydoc MessageBase::Process
584    */
585   virtual void Process( BufferIndex bufferIndex )
586   {
587     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
588
589     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
590
591     (object->*memberFunction)( bufferIndex );
592   }
593
594 private:
595
596   T* object;
597   MemberFunction memberFunction;
598
599 };
600
601
602 /**
603  * Templated message which calls a member function of an object.
604  * This overload passes a value-type to set a double-buffered property.
605  * Template parameters need to match the MemberFunction!
606  * The message will contain copy of the value (in case of & or const&)
607  */
608 template< typename T, typename P >
609 class MessageDoubleBuffered1 : public MessageBase
610 {
611 public:
612
613   typedef void(T::*MemberFunction)(
614       BufferIndex,
615       typename ParameterType< P >::PassingType );
616
617   /**
618    * Create a message.
619    * @note The object is expected to be const in the thread which sends this message.
620    * However it can be modified when Process() is called in a different thread.
621    * @param[in] obj The object.
622    * @param[in] member The member function of the object.
623    * @param[in] p The second parameter to pass.
624    */
625   MessageDoubleBuffered1( const T* obj,
626                           MemberFunction member,
627                           typename ParameterType< P >::PassingType p )
628   : MessageBase(),
629     object( const_cast< T* >( obj ) ),
630     memberFunction( member ),
631     param( p )
632   {
633   }
634
635   /**
636    * Virtual destructor
637    */
638   virtual ~MessageDoubleBuffered1()
639   {
640   }
641
642   /**
643    * @copydoc MessageBase::Process
644    */
645   virtual void Process( BufferIndex bufferIndex )
646   {
647     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
648
649     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
650
651     (object->*memberFunction)( bufferIndex,  param );
652   }
653
654 private:
655
656   T* object;
657   MemberFunction memberFunction;
658   typename ParameterType< P >::HolderType param;
659
660 };
661
662 /**
663  * Templated message which calls a member function of an object.
664  * This overload passes two value-types to set double-buffered properties.
665  * Template parameters need to match the MemberFunction!
666  * The message will contain copy of the value (in case of & or const&)
667  */
668 template< typename T, typename P2, typename P3 >
669 class MessageDoubleBuffered2 : public MessageBase
670 {
671 public:
672
673   typedef void(T::*MemberFunction)(
674       BufferIndex,
675       typename ParameterType< P2 >::PassingType,
676       typename ParameterType< P3 >::PassingType );
677
678   /**
679    * Create a message.
680    * @note The object is expected to be const in the thread which sends this message.
681    * However it can be modified when Process() is called in a different thread.
682    * @param[in] obj The object.
683    * @param[in] member The member function of the object.
684    * @param[in] p2 The second parameter to pass to the function.
685    * @param[in] p3 The third parameter to pass to the function.
686    */
687   MessageDoubleBuffered2( const T* obj,
688                           MemberFunction member,
689                           typename ParameterType< P2 >::PassingType p2,
690                           typename ParameterType< P3 >::PassingType p3 )
691   : MessageBase(),
692     object( const_cast< T* >( obj ) ),
693     memberFunction( member ),
694     param2( p2 ),
695     param3( p3 )
696   {
697   }
698
699   /**
700    * Virtual destructor
701    */
702   virtual ~MessageDoubleBuffered2()
703   {
704   }
705
706   /**
707    * @copydoc MessageBase::Process
708    */
709   virtual void Process( BufferIndex bufferIndex )
710   {
711     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
712
713     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
714
715     (object->*memberFunction)(
716         bufferIndex, param2, param3 );
717   }
718
719 private:
720
721   T* object;
722   MemberFunction memberFunction;
723   typename ParameterType< P2 >::HolderType param2;
724   typename ParameterType< P3 >::HolderType param3;
725
726 };
727
728
729 /**
730  * Templated message which calls a member function of an object.
731  * This overload passes three value-types to set double-buffered properties.
732  * Template parameters need to match the MemberFunction!
733  * The message will contain copy of the value (in case of & or const&)
734  */
735 template< typename T, typename P2, typename P3, typename P4 >
736 class MessageDoubleBuffered3 : public MessageBase
737 {
738 public:
739
740   typedef void(T::*MemberFunction)(
741       BufferIndex,
742       typename ParameterType< P2 >::PassingType,
743       typename ParameterType< P3 >::PassingType,
744       typename ParameterType< P4 >::PassingType );
745
746   /**
747    * Create a message.
748    * @note The object is expected to be const in the thread which sends this message.
749    * However it can be modified when Process() is called in a different thread.
750    * @param[in] obj The object.
751    * @param[in] member The member function of the object.
752    * @param[in] p2 The second parameter to pass.
753    * @param[in] p3 The third parameter to pass.
754    * @param[in] p4 The forth parameter to pass.
755    */
756   MessageDoubleBuffered3( const T* obj,
757                           MemberFunction member,
758                           typename ParameterType< P2 >::PassingType p2,
759                           typename ParameterType< P3 >::PassingType p3,
760                           typename ParameterType< P4 >::PassingType p4 )
761   : MessageBase(),
762     object( const_cast< T* >( obj ) ),
763     memberFunction( member ),
764     param2( p2 ),
765     param3( p3 ),
766     param4( p4 )
767   {
768   }
769
770   /**
771    * Virtual destructor
772    */
773   virtual ~MessageDoubleBuffered3()
774   {
775   }
776
777   /**
778    * @copydoc MessageBase::Process
779    */
780   virtual void Process( BufferIndex bufferIndex )
781   {
782     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
783
784     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
785
786     (object->*memberFunction)( bufferIndex, param2, param3, param4 );
787   }
788
789 private:
790
791   T* object;
792   MemberFunction memberFunction;
793   typename ParameterType< P2 >::HolderType param2;
794   typename ParameterType< P3 >::HolderType param3;
795   typename ParameterType< P4 >::HolderType param4;
796
797 };
798
799 /**
800  * Templated message which calls a member function of an object.
801  * This overload passes four value-types to set double-buffered properties.
802  * Template parameters need to match the MemberFunction!
803  * The message will contain copy of the value (in case of & or const&)
804  */
805 template< typename T, typename P2, typename P3, typename P4, typename P5 >
806 class MessageDoubleBuffered4 : public MessageBase
807 {
808 public:
809
810   typedef void(T::*MemberFunction)(
811       BufferIndex,
812       typename ParameterType< P2 >::PassingType,
813       typename ParameterType< P3 >::PassingType,
814       typename ParameterType< P4 >::PassingType,
815       typename ParameterType< P5 >::PassingType );
816
817   /**
818    * Create a message.
819    * @note The object is expected to be const in the thread which sends this message.
820    * However it can be modified when Process() is called in a different thread.
821    * @param[in] obj The object.
822    * @param[in] member The member function of the object.
823    * @param[in] p2 The second parameter to pass.
824    * @param[in] p3 The third parameter to pass.
825    * @param[in] p4 The forth parameter to pass.
826    * @param[in] p5 The fifth parameter to pass.
827    */
828   MessageDoubleBuffered4( const T* obj,
829                           MemberFunction member,
830                           typename ParameterType< P2 >::PassingType p2,
831                           typename ParameterType< P3 >::PassingType p3,
832                           typename ParameterType< P4 >::PassingType p4,
833                           typename ParameterType< P5 >::PassingType p5 )
834   : MessageBase(),
835     object( const_cast< T* >( obj ) ),
836     memberFunction( member ),
837     param2( p2 ),
838     param3( p3 ),
839     param4( p4 ),
840     param5( p5 )
841   {
842   }
843
844   /**
845    * Virtual destructor
846    */
847   virtual ~MessageDoubleBuffered4()
848   {
849   }
850
851   /**
852    * @copydoc MessageBase::Process
853    */
854   virtual void Process( BufferIndex bufferIndex )
855   {
856     DALI_ASSERT_DEBUG( object && "Message does not have an object" );
857
858     DALI_LOG_ERROR("Message::Process: object: %s, function pointer: %p\n", typeid(object).name(), memberFunction);
859
860     (object->*memberFunction)( bufferIndex, param2, param3, param4, param5 );
861   }
862
863 private:
864
865   T* object;
866   MemberFunction memberFunction;
867   typename ParameterType< P2 >::HolderType param2;
868   typename ParameterType< P3 >::HolderType param3;
869   typename ParameterType< P4 >::HolderType param4;
870   typename ParameterType< P5 >::HolderType param5;
871
872 };
873
874 } // namespace Internal
875
876 } // namespace Dali
877
878 #endif // __DALI_INTERNAL_MESSAGE_H__