Track ActiveTexture calls
[platform/core/uifw/dali-adaptor.git] / adaptors / common / ecore-callback-manager.cpp
1 /*
2  * Copyright (c) 2014 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include "ecore-callback-manager.h"
20
21 // EXTERNAL INCLUDES
22 #include <Ecore.h>
23
24 #include <dali/integration-api/debug.h>
25
26 // INTERNAL INCLUDES
27
28
29 namespace Dali
30 {
31
32 namespace Internal
33 {
34
35 namespace Adaptor
36 {
37
38 /**
39  * Structure contains the callback function and control options
40  */
41 struct CallbackData
42 {
43   /**
44    * the type of callback
45    */
46   enum CallbackType
47   {
48     STANDARD_CALLBACK,  ///< either an idle call back, or a default call back
49     EVENT_HANDLER       ///< event handler
50   };
51
52   /**
53    * Constructor
54    */
55   CallbackData(CallbackManager::Callback callback, CallbackType type):
56      mCallback(callback),
57      mType(type),
58      mIdler(NULL),
59      mPriority(CallbackManager::DEFAULT_PRIORITY),
60      mExecute(true),
61      mEventHandler(NULL),
62      mEvent(0),
63      mEventControl(CallbackManager::CALLBACK_PASS_ON)
64   {
65   }
66
67   // Data
68   CallbackManager::Callback       mCallback;      ///< call back
69   CallbackType                    mType;          ///< type of call back
70
71     // Data for idle / default call backs
72   Ecore_Idler*                    mIdler;         ///< ecore idler
73   CallbackManager::Priority       mPriority;      ///< Priority (idle or normal)
74   bool                            mExecute;       ///< whether to run the callback
75
76   // Data for event handlers
77   Ecore_Event_Handler*            mEventHandler;  ///< ecore handler
78   int                             mEvent;         ///< ecore event id
79   CallbackManager::EventControl   mEventControl;  ///< event control
80
81   // function typedef to remove the callbackdata from the callback container
82   typedef boost::function<void(CallbackData *)>  RemoveFromContainerFunction;
83
84   RemoveFromContainerFunction     mRemoveFromContainerFunction;
85 };
86
87 namespace
88 {
89
90 /**
91  * Called from the main thread while idle.
92  */
93 Eina_Bool IdleCallback(void *data)
94 {
95   CallbackData *callbackData = static_cast<CallbackData *>(data);
96
97   // remove callback data from the container first in case our callback tries to modify the container
98   callbackData->mRemoveFromContainerFunction(callbackData);
99
100   // run the function
101   callbackData->mCallback();
102
103   // remove the idle call back
104   ecore_idler_del(callbackData->mIdler);
105
106   delete callbackData;
107
108   return ECORE_CALLBACK_CANCEL;
109 }
110
111 /**
112  * Ecore callback event handler, called from the main thread
113  * @param data  user data
114  * @param type event type, e.g. ECORE_EVENT_SIGNAL_EXIT
115  * @param event pointer to ecore event
116  */
117 Eina_Bool EventHandler(void *data, int type, void *event)
118 {
119   CallbackData* callbackData = static_cast<CallbackData*>(data);
120
121   // make sure the type is for the right event
122   DALI_ASSERT_ALWAYS( type == callbackData->mEvent && "Callback data does not match event" );
123
124   // remove callback data from the container first in case our callback tries to modify the container
125   callbackData->mRemoveFromContainerFunction(callbackData);
126
127   // run the call back
128   callbackData->mCallback();
129
130   Eina_Bool returnVal;
131
132   if (callbackData->mEventControl == CallbackManager::CALLBACK_PASS_ON)
133   {
134     returnVal = ECORE_CALLBACK_PASS_ON;
135   }
136   else
137   {
138     returnVal = ECORE_CALLBACK_DONE;
139   }
140
141   delete callbackData;
142
143   return returnVal;
144 }
145
146 /**
147  * called from MainLoopCallback to process standard callbacks
148  */
149 void AddStandardCallback(CallbackData *callbackData)
150 {
151   if (callbackData->mPriority == CallbackManager::IDLE_PRIORITY)
152   {
153     // run the call back on idle
154     callbackData->mIdler = ecore_idler_add(IdleCallback, callbackData);
155     DALI_ASSERT_ALWAYS( callbackData->mIdler != NULL && "Idle method not created" );
156   }
157   else
158   {
159     // run the call back now, then delete it from the container
160     if ( callbackData->mExecute )
161     {
162       callbackData->mCallback();
163     }
164     callbackData->mRemoveFromContainerFunction(callbackData);
165     delete callbackData;
166   }
167 }
168
169 /**
170  * called from MainLoopCallback to add event callbacks
171  */
172 void AddEventCallback(CallbackData *callbackData)
173 {
174   callbackData->mEventHandler = ecore_event_handler_add(callbackData->mEvent, &EventHandler, callbackData);
175 }
176
177 /**
178  * main loop call back to process call back data.
179  */
180 void MainLoopCallback(void *data)
181 {
182   CallbackData *callbackData = static_cast< CallbackData* >(data);
183
184   if (callbackData->mType ==  CallbackData::STANDARD_CALLBACK)
185   {
186     AddStandardCallback(callbackData);
187   }
188   else if (callbackData->mType ==  CallbackData::EVENT_HANDLER)
189   {
190     AddEventCallback(callbackData);
191   }
192 }
193
194 /**
195  * Main loop call back to remove all call back data
196  */
197 void* MainRemoveAllCallback(void* data)
198 {
199   EcoreCallbackManager *callbackManager = static_cast<EcoreCallbackManager *>(data);
200
201   callbackManager->RemoveAllCallbacksFromMainThread();
202
203   return NULL;
204 }
205
206 } // unnamed namespace
207
208 EcoreCallbackManager::EcoreCallbackManager()
209 :mRunning(false)
210 {
211 }
212
213 void EcoreCallbackManager::RemoveStandardCallback(CallbackData *callbackData)
214 {
215   if (callbackData->mPriority == CallbackManager::IDLE_PRIORITY)
216   {
217     // delete the idle call back
218     ecore_idler_del(callbackData->mIdler);
219     delete callbackData;
220   }
221   else
222   {
223     // ecore doesn't give us a handle for functions we want executing on the
224     // main thread, E.g. we can't do
225     // handle = ecore_main_loop_thread_safe_call_async( myfunc )
226     // ecore_main_loop_thread_remove_async_call(handle);  // doesn't exist
227     //
228     // We just have to set a flag to say do not execute.
229     // Hence we can't delete the call back at this point.
230     callbackData->mExecute = false;
231   }
232 }
233
234 void EcoreCallbackManager::RemoveEventCallback(CallbackData *callbackData)
235 {
236   ecore_event_handler_del(callbackData->mEventHandler);
237
238   delete callbackData;
239 }
240
241 void EcoreCallbackManager::Start()
242 {
243   DALI_ASSERT_DEBUG( mRunning == false );
244
245   mRunning = true;
246 }
247
248 void EcoreCallbackManager::Stop()
249 {
250   // make sure we're not called twice
251   DALI_ASSERT_DEBUG( mRunning == true );
252
253   // lock out any other call back functions
254   boost::unique_lock< boost::mutex > lock( mMutex );
255
256   mRunning = false;
257
258   // the synchronous calls return data from the callback, which we ignore.
259   ecore_main_loop_thread_safe_call_sync(MainRemoveAllCallback, this);
260 }
261
262 bool EcoreCallbackManager::AddCallback(Callback callback, Priority priority)
263 {
264   bool added(false);
265
266   if ( mRunning )
267   {
268     CallbackData *callbackData = new CallbackData(callback, CallbackData::STANDARD_CALLBACK);
269
270     callbackData->mPriority = priority;
271
272     callbackData->mRemoveFromContainerFunction =  boost::bind(&EcoreCallbackManager::RemoveCallbackFromContainer, this,_1);
273
274     { // acquire lock to access container
275       boost::unique_lock< boost::mutex > lock( mMutex );
276
277       // add the call back to the container
278       mCallbackContainer.push_front(callbackData);
279     }
280
281     // Get callbackData processed on the main loop..
282
283     ecore_main_loop_thread_safe_call_async(MainLoopCallback, callbackData);
284
285     added = true;
286   }
287
288   return added;
289 }
290
291 bool EcoreCallbackManager::AddEventCallback(Callback callback, int type, EventControl control)
292 {
293   bool added(false);
294
295   if( mRunning )
296   {
297     CallbackData *callbackData = new CallbackData(callback,CallbackData::EVENT_HANDLER);
298     callbackData->mEventControl = control;
299     callbackData->mEvent = type;
300
301     callbackData->mRemoveFromContainerFunction =  boost::bind(&EcoreCallbackManager::RemoveCallbackFromContainer, this,_1);
302
303     { // acquire lock to access container
304       boost::unique_lock< boost::mutex > lock( mMutex );
305
306       // add the call back to the container
307       mCallbackContainer.push_front(callbackData);
308     }
309
310     // Get callbackData processed on the main loop..
311     ecore_main_loop_thread_safe_call_async(MainLoopCallback, callbackData);
312
313     added = true;
314   }
315
316   return added;
317 }
318
319 void EcoreCallbackManager::RemoveCallbackFromContainer(CallbackData *callbackData)
320 {
321   // always called from main loop
322   boost::unique_lock< boost::mutex > lock( mMutex );
323
324   mCallbackContainer.remove(callbackData);
325 }
326
327 void EcoreCallbackManager::RemoveAllCallbacksFromMainThread()
328 {
329    // always called from main thread
330    // the mutex will already be locked at this point
331
332    for( CallbackList::iterator  iter =  mCallbackContainer.begin(); iter != mCallbackContainer.end(); ++iter)
333    {
334      CallbackData* data = (*iter);
335
336      if (data->mType ==  CallbackData::STANDARD_CALLBACK)
337      {
338        RemoveStandardCallback(data);
339      }
340      else if (data->mType ==  CallbackData::EVENT_HANDLER)
341      {
342        RemoveEventCallback(data);
343      }
344    }
345    mCallbackContainer.clear();
346 }
347
348 // Creates a concrete interface for CallbackManager
349 CallbackManager* CallbackManager::New()
350 {
351   return new EcoreCallbackManager;
352 }
353
354 } // namespace Adaptor
355
356 } // namespace Internal
357
358 } // namespace Dali