2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include "ecore-callback-manager.h"
24 #include <dali/integration-api/debug.h>
39 * Structure contains the callback function and control options
44 * the type of callback
48 STANDARD_CALLBACK, ///< either an idle call back, or a default call back
49 EVENT_HANDLER ///< event handler
55 CallbackData( CallbackBase* callback, CallbackType type )
56 : mCallback(callback),
59 mPriority(CallbackManager::DEFAULT_PRIORITY),
63 mEventControl(CallbackManager::CALLBACK_PASS_ON),
64 mRemoveFromContainerFunction(NULL)
74 delete mRemoveFromContainerFunction;
78 CallbackBase* mCallback; ///< call back
79 CallbackType mType; ///< type of call back
81 // Data for idle / default call backs
82 Ecore_Idler* mIdler; ///< ecore idler
83 CallbackManager::Priority mPriority; ///< Priority (idle or normal)
84 bool mExecute; ///< whether to run the callback
86 // Data for event handlers
87 Ecore_Event_Handler* mEventHandler; ///< ecore handler
88 int mEvent; ///< ecore event id
89 CallbackManager::EventControl mEventControl; ///< event control
91 CallbackBase* mRemoveFromContainerFunction; ///< Called to remove the callbackdata from the callback container
98 * Called from the main thread while idle.
100 Eina_Bool IdleCallback(void *data)
102 CallbackData *callbackData = static_cast<CallbackData *>(data);
104 // remove callback data from the container first in case our callback tries to modify the container
105 CallbackBase::Execute( *callbackData->mRemoveFromContainerFunction, callbackData );
108 CallbackBase::Execute( *callbackData->mCallback );
110 // remove the idle call back
111 ecore_idler_del(callbackData->mIdler);
115 return ECORE_CALLBACK_CANCEL;
119 * Ecore callback event handler, called from the main thread
120 * @param data user data
121 * @param type event type, e.g. ECORE_EVENT_SIGNAL_EXIT
122 * @param event pointer to ecore event
124 Eina_Bool EventHandler(void *data, int type, void *event)
126 CallbackData* callbackData = static_cast<CallbackData*>(data);
128 // make sure the type is for the right event
129 DALI_ASSERT_ALWAYS( type == callbackData->mEvent && "Callback data does not match event" );
131 // remove callback data from the container first in case our callback tries to modify the container
132 CallbackBase::Execute( *callbackData->mRemoveFromContainerFunction, callbackData );
135 CallbackBase::Execute( *callbackData->mCallback );
139 if (callbackData->mEventControl == CallbackManager::CALLBACK_PASS_ON)
141 returnVal = ECORE_CALLBACK_PASS_ON;
145 returnVal = ECORE_CALLBACK_DONE;
154 * called from MainLoopCallback to process standard callbacks
156 void AddStandardCallback(CallbackData *callbackData)
158 if (callbackData->mPriority == CallbackManager::IDLE_PRIORITY)
160 // run the call back on idle
161 callbackData->mIdler = ecore_idler_add(IdleCallback, callbackData);
162 DALI_ASSERT_ALWAYS( callbackData->mIdler != NULL && "Idle method not created" );
166 // run the call back now, then delete it from the container
167 if ( callbackData->mExecute )
169 CallbackBase::Execute( *callbackData->mCallback );
171 CallbackBase::Execute( *callbackData->mRemoveFromContainerFunction, callbackData );
177 * called from MainLoopCallback to add event callbacks
179 void AddEventCallback(CallbackData *callbackData)
181 callbackData->mEventHandler = ecore_event_handler_add(callbackData->mEvent, &EventHandler, callbackData);
185 * main loop call back to process call back data.
187 void MainLoopCallback(void *data)
189 CallbackData *callbackData = static_cast< CallbackData* >(data);
191 if (callbackData->mType == CallbackData::STANDARD_CALLBACK)
193 AddStandardCallback(callbackData);
195 else if (callbackData->mType == CallbackData::EVENT_HANDLER)
197 AddEventCallback(callbackData);
202 * Main loop call back to remove all call back data
204 void* MainRemoveAllCallback(void* data)
206 EcoreCallbackManager *callbackManager = static_cast<EcoreCallbackManager *>(data);
208 callbackManager->RemoveAllCallbacksFromMainThread();
213 } // unnamed namespace
215 EcoreCallbackManager::EcoreCallbackManager()
220 void EcoreCallbackManager::RemoveStandardCallback(CallbackData *callbackData)
222 if (callbackData->mPriority == CallbackManager::IDLE_PRIORITY)
224 // delete the idle call back
225 ecore_idler_del(callbackData->mIdler);
230 // ecore doesn't give us a handle for functions we want executing on the
231 // main thread, E.g. we can't do
232 // handle = ecore_main_loop_thread_safe_call_async( myfunc )
233 // ecore_main_loop_thread_remove_async_call(handle); // doesn't exist
235 // We just have to set a flag to say do not execute.
236 // Hence we can't delete the call back at this point.
237 callbackData->mExecute = false;
241 void EcoreCallbackManager::RemoveEventCallback(CallbackData *callbackData)
243 ecore_event_handler_del(callbackData->mEventHandler);
248 void EcoreCallbackManager::Start()
250 DALI_ASSERT_DEBUG( mRunning == false );
255 void EcoreCallbackManager::Stop()
257 // make sure we're not called twice
258 DALI_ASSERT_DEBUG( mRunning == true );
260 // lock out any other call back functions
261 boost::unique_lock< boost::mutex > lock( mMutex );
265 // the synchronous calls return data from the callback, which we ignore.
266 ecore_main_loop_thread_safe_call_sync(MainRemoveAllCallback, this);
269 bool EcoreCallbackManager::AddCallback(CallbackBase* callback, Priority priority)
275 CallbackData *callbackData = new CallbackData(callback, CallbackData::STANDARD_CALLBACK);
277 callbackData->mPriority = priority;
279 callbackData->mRemoveFromContainerFunction = MakeCallback( this, &EcoreCallbackManager::RemoveCallbackFromContainer );
281 { // acquire lock to access container
282 boost::unique_lock< boost::mutex > lock( mMutex );
284 // add the call back to the container
285 mCallbackContainer.push_front(callbackData);
288 // Get callbackData processed on the main loop..
290 ecore_main_loop_thread_safe_call_async(MainLoopCallback, callbackData);
298 bool EcoreCallbackManager::AddEventCallback(CallbackBase* callback, int type, EventControl control)
304 CallbackData *callbackData = new CallbackData(callback,CallbackData::EVENT_HANDLER);
305 callbackData->mEventControl = control;
306 callbackData->mEvent = type;
308 callbackData->mRemoveFromContainerFunction = MakeCallback( this, &EcoreCallbackManager::RemoveCallbackFromContainer );
310 { // acquire lock to access container
311 boost::unique_lock< boost::mutex > lock( mMutex );
313 // add the call back to the container
314 mCallbackContainer.push_front(callbackData);
317 // Get callbackData processed on the main loop..
318 ecore_main_loop_thread_safe_call_async(MainLoopCallback, callbackData);
326 void EcoreCallbackManager::RemoveCallbackFromContainer(CallbackData *callbackData)
328 // always called from main loop
329 boost::unique_lock< boost::mutex > lock( mMutex );
331 mCallbackContainer.remove(callbackData);
334 void EcoreCallbackManager::RemoveAllCallbacksFromMainThread()
336 // always called from main thread
337 // the mutex will already be locked at this point
339 for( CallbackList::iterator iter = mCallbackContainer.begin(); iter != mCallbackContainer.end(); ++iter)
341 CallbackData* data = (*iter);
343 if (data->mType == CallbackData::STANDARD_CALLBACK)
345 RemoveStandardCallback(data);
347 else if (data->mType == CallbackData::EVENT_HANDLER)
349 RemoveEventCallback(data);
352 mCallbackContainer.clear();
355 // Creates a concrete interface for CallbackManager
356 CallbackManager* CallbackManager::New()
358 return new EcoreCallbackManager;
361 } // namespace Adaptor
363 } // namespace Internal