6ab4c7b5bddcf5f56bb610896fc84350005faeb4
[platform/framework/native/appfw.git] / src / base / runtime / FBaseRt_WaitingLoopImpl.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file        FBaseRt_WaitingLoopImpl.cpp
20  * @brief       This is the implementation for the %_WaitingLoopImpl class.
21  *
22  */
23
24 #include <Ecore.h>
25 #include <unique_ptr.h>
26 #include <FBaseRtWaitingLoop.h>
27 #include <FBaseSysLog.h>
28 #include "FBaseRt_ThreadImpl.h"
29 #include "FBaseRt_EventDispatcher.h"
30 #include "FBaseRt_WaitingLoopImpl.h"
31
32 using namespace Tizen::Base;
33
34 namespace Tizen { namespace Base { namespace Runtime
35 {
36
37
38 static int __sleepTime = 10;
39 static int __waitingCount = 10;
40 static int __waitingRepeatableTime = 100;
41 static int __maxTime = 50;
42
43 _WaitingLoopImpl::_WaitingLoopImpl(void)
44         : __pTimer(null)
45         , __timeout(false)
46         , __notifyWait(true)
47         , __threadType(THREAD_TYPE_MAIN)
48         , __pGmainContext(null)
49         , __waitType(WAIT_DEFAULT)
50         , __waitStatus(WAIT_OFF)
51         , __pWaitingLoopCondition(null)
52         , __timerCalledCount(0)
53         , __maxTimeout(10000)
54 {
55
56 }
57
58 _WaitingLoopImpl::~_WaitingLoopImpl(void)
59 {
60         if (__pTimer != null)
61         {
62                 __pTimer->Cancel();
63                 delete __pTimer;
64         }
65 }
66
67 result
68 _WaitingLoopImpl::Construct(void)
69 {
70         _ThreadImpl* pThreadImpl = _ThreadImpl::GetCurrentThreadImpl();
71         SysTryReturnResult(NID_BASE_RT, pThreadImpl != null, E_OBJ_NOT_FOUND,"This is not a OSP thread.");
72         
73         ThreadType threadType = pThreadImpl->GetThreadType();
74         
75         if(threadType == THREAD_TYPE_MAIN)
76         {
77                 SysLog(NID_BASE_RT, "This is a the main thread which supports the waiting loop using ecore.");
78         }
79         else if(threadType == THREAD_TYPE_EVENT_DRIVEN)
80         {
81                 SysLog(NID_BASE_RT, "This is a a event driven thread which supports the waiting loop using glib.");
82                 
83                 _EventDispatcher* pEventDispatcher = _EventDispatcher::GetCurrentEventDispatcher();
84                 if (pEventDispatcher != null)
85                 {
86                         __pGmainContext = pEventDispatcher->GetGMainContext();  
87                         SysLog(NID_BASE_RT, "This thread already has the gmaincontext.");       
88                 }
89                 else
90                 {
91                         SysLog(NID_BASE_RT, "This thread does not create the gmaincontext.");                   
92                 }
93         }       
94         else
95         {
96                 SysLog(NID_BASE_RT, "This ia a worker thread which does not support the waiting loop.");
97                 return E_INVALID_OPERATION;
98         }
99         __threadType = threadType;
100
101         std::unique_ptr< Timer > pTimer(new (std::nothrow) Timer());
102         SysTryReturnResult(NID_BASE_RT, pThreadImpl != null, E_OUT_OF_MEMORY,"Fail to create a timer instance.");
103         
104         result r = pTimer->Construct(*this); 
105         SysTryReturn(NID_BASE_RT, r == E_SUCCESS, null, r,"[%s]Fail to create a timer instance.", GetErrorMessage(r));
106
107         __pTimer = pTimer.release();
108         return r;
109 }
110
111 WaitingLoop* 
112 _WaitingLoopImpl::GetInstanceN(void)
113 {
114         std::unique_ptr< _WaitingLoopImpl > pWaitingLoopImpl(new (std::nothrow) _WaitingLoopImpl());
115         SysTryReturn(NID_APP, pWaitingLoopImpl != null, null, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY]Fail to create a _WaitingLoopImpl instance.");
116         
117         result r = pWaitingLoopImpl->Construct();       
118         SysTryReturn(NID_BASE_RT, r == E_SUCCESS, null, r,"[%s]Fail to create a _WaitingLoopImpl instance.", GetErrorMessage(r));
119
120         WaitingLoop* pWaitingLoop = new WaitingLoop();
121         SysTryReturn(NID_BASE_RT, pWaitingLoop != null, null, E_OUT_OF_MEMORY,"[E_OUT_OF_MEMORY]Fail to create a WaitingLoop instance.");
122
123         pWaitingLoop->__pWaitingLoopImpl = pWaitingLoopImpl.release();
124         
125         return pWaitingLoop;
126 }
127
128 result 
129 _WaitingLoopImpl::Wait(int timeout)
130 {
131         SysTryReturnResult(NID_BASE_RT, __waitStatus == WAIT_OFF, E_INVALID_STATE, "The waiting loop is waiting on a thread.");
132         
133         __timeout = false;
134         __waitType = WAIT_TIMEOUT;
135
136         if (__maxTimeout < timeout)
137         {
138                 timeout = __maxTimeout;
139         }
140
141         result r = __pTimer->Start(timeout);
142
143         SysTryReturn(NID_BASE_RT, r == E_SUCCESS, r, r,"[%s]Timer does not start.", GetErrorMessage(r));
144
145         __waitStatus = WAIT_ON;
146         if (__threadType == THREAD_TYPE_MAIN)
147         {
148                 ecore_main_loop_begin();
149                 SysLog(NID_BASE_RT, "The waiting loop(ecore) is stopped.");
150         }
151         else
152         {
153                 while(!__timeout && __notifyWait)
154                 {       
155                         g_main_context_iteration(__pGmainContext, TRUE);
156                         Thread::Sleep(__sleepTime);
157                 }
158                 SysLog(NID_BASE_RT, "The waiting loop(glib) is stopped.");
159         }
160         __pTimer->Cancel();
161         __waitStatus = WAIT_OFF;
162
163         SysTryReturn(NID_BASE_RT, __timeout != true, E_TIMEOUT, E_TIMEOUT, "[E_TIMEOUT]The time is expired.");
164         
165         return E_SUCCESS;
166 }
167
168 result 
169 _WaitingLoopImpl::Wait(IWaitingLoopCondition& condition)
170 {
171         SysTryReturnResult(NID_BASE_RT, __waitStatus == WAIT_OFF, E_INVALID_STATE, "[E_INVALID_STATUS]The waiting loop is waiting on a thread.");
172
173         __timeout = false;
174         __waitType = WAIT_CONDITION;
175         __pWaitingLoopCondition = &condition;
176
177         if (__threadType == THREAD_TYPE_MAIN)
178         {
179                 result r = __pTimer->StartAsRepeatable(__waitingRepeatableTime);
180                 SysTryReturn(NID_BASE_RT, r == E_SUCCESS, r, r, "[%s]Timer does not start.", GetErrorMessage(r));
181         
182                 __waitStatus = WAIT_ON;
183                 ecore_main_loop_begin();
184                 SysLog(NID_BASE_RT, "The waiting loop(ecore) is stopped.");
185
186                 __pTimer->Cancel();
187         }
188         else
189         {
190                 __waitStatus = WAIT_ON;
191                 while(!__pWaitingLoopCondition->IsMet() && __notifyWait)
192                 {
193                         g_main_context_iteration(__pGmainContext, FALSE);
194                         Thread::Sleep(__sleepTime);
195                 }
196                 SysLog(NID_BASE_RT, "The waiting loop(glib) is stopped.");
197         }
198         __waitStatus = WAIT_OFF;
199
200         return E_SUCCESS;
201 }
202
203 result 
204 _WaitingLoopImpl::Wait(int timeout, IWaitingLoopCondition& condition)
205 {
206         SysTryReturnResult(NID_BASE_RT, __waitStatus == WAIT_OFF, E_INVALID_STATE, "[E_INVALID_STATUS]The waiting loop is waiting on a thread.");
207
208         __timeout = false;
209         __timerCalledCount = 0;
210         __waitType = WAIT_TIMEOUT_CONDITION;
211         __pWaitingLoopCondition = &condition;
212
213         if(timeout > __maxTimeout)
214         {
215                 timeout = __maxTimeout;
216         }
217
218         if (timeout < __waitingRepeatableTime)
219         {
220                 result r = __pTimer->StartAsRepeatable(__waitingRepeatableTime);
221                 SysTryReturn(NID_BASE_RT, r == E_SUCCESS, r, r, "[%s]Timer does not start.", GetErrorMessage(r));
222         }
223         else
224         {
225                 result r = __pTimer->StartAsRepeatable(timeout/10);
226                 SysTryReturn(NID_BASE_RT, r == E_SUCCESS, r, r, "[%s]Timer does not start.", GetErrorMessage(r));       
227         }
228         __waitStatus = WAIT_ON;
229         if (__threadType == THREAD_TYPE_MAIN)
230         {
231                 ecore_main_loop_begin();
232                 SysLog(NID_BASE_RT, "The waiting loop(ecore) is stopped.");
233         }
234         else
235         {
236                 while(!__pWaitingLoopCondition->IsMet() && __timeout && __notifyWait)
237                 {
238                         g_main_context_iteration(__pGmainContext, TRUE);
239                         Thread::Sleep(__sleepTime);
240                 }
241                 SysLog(NID_BASE_RT, "The waiting loop(glib) is stopped.");
242         }
243
244         __pTimer->Cancel();
245         __waitStatus = WAIT_OFF;
246
247         SysTryReturn(NID_BASE_RT, __timeout != true, E_TIMEOUT, E_TIMEOUT, "[E_TIMEOUT]The time is expired.");
248
249         return E_SUCCESS;
250 }
251
252 void 
253 _WaitingLoopImpl::Notify(void)
254 {
255         SysTryReturnVoidResult(NID_BASE_RT, __waitStatus == WAIT_ON, E_INVALID_STATE, "[E_INVALID_STATUS]The waiting loop is not waiting on a thread.");
256         __notifyWait = false;
257
258         SysLog(NID_BASE_RT, "The waiting loop would be stopped from Notifying.");
259
260         if (__threadType == THREAD_TYPE_MAIN)
261         {
262                 ecore_main_loop_quit();
263         }
264 }
265
266 void 
267 _WaitingLoopImpl::SetMaxTimeoutForWaiting(int timeout)
268 {
269         if (timeout < __maxTime)
270         {
271                 __maxTimeout = __maxTime;
272         }
273         else
274         {
275                 __maxTimeout = timeout;
276         }
277 }
278
279 void 
280 _WaitingLoopImpl::OnTimerExpired(Timer& timer)
281 {
282         if (__threadType == THREAD_TYPE_MAIN)
283         {
284                 if (__waitType == WAIT_TIMEOUT)
285                 {
286                         ecore_main_loop_quit();
287                         SysLog(NID_BASE_RT, "The waiting loop is stopped from time out.");
288                         __timeout = true;
289                 }
290                 else if ((__waitType == WAIT_CONDITION) && __pWaitingLoopCondition->IsMet())
291                 {
292                         ecore_main_loop_quit(); 
293                         SysLog(NID_BASE_RT, "The waiting loop  is stopped from firing condition.");
294                 }
295                 else if (__waitType == WAIT_TIMEOUT_CONDITION)
296                 {
297                         __timerCalledCount++;
298                         if (__timerCalledCount == __waitingCount)
299                         {
300                                 ecore_main_loop_quit(); 
301                                 SysLog(NID_BASE_RT, "The waiting loop is stopped from time out.");
302                                 __timeout = true;
303                         }
304                         else
305                         {
306                                 if (__pWaitingLoopCondition->IsMet())
307                                 {
308                                         ecore_main_loop_quit(); 
309                                         SysLog(NID_BASE_RT, "The waiting loop is stopped from firing condition.");      
310                                 }       
311                         }               
312                 }
313         }
314         else
315         {
316                 if (__waitType == WAIT_TIMEOUT)
317                 {
318                         __timeout = true;
319                         SysLog(NID_BASE_RT, "The waiting loop is stopped from time out.");
320                 }
321                 else if (__waitType == WAIT_TIMEOUT_CONDITION)
322                 {
323                         __timerCalledCount++;
324                         if (__timerCalledCount == __waitingCount)
325                         {
326                                 __timeout = true;
327                                 SysLog(NID_BASE_RT, "The waiting loop is stopped from time out.");
328                         }
329                 }
330         }
331 }
332
333 bool
334 _WaitingLoopImpl::IsSameThread(void)
335 {
336         _ThreadImpl* pThreadImpl = _ThreadImpl::GetCurrentThreadImpl();
337         SysTryReturn(NID_BASE_RT, pThreadImpl != null, false, E_OBJ_NOT_FOUND,"This is not a OSP thread.");
338         
339         ThreadType threadType = pThreadImpl->GetThreadType();
340
341         if (__threadType == threadType)
342         {
343                 SysLog(NID_BASE_RT, "The waiting loop is working on the current thread.");
344                 return true;
345         }
346         else
347         {
348                 SysLog(NID_BASE_RT, "The waiting loop is working on another thread.");
349                 return false;
350         }       
351 }
352
353 } } } // Tizen::Base::Runtime
354