Update for MaxTimeOut
[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         result r = __pTimer->Start(timeout);
137
138         SysTryReturn(NID_BASE_RT, r == E_SUCCESS, r, r,"[%s]Timer does not start.", GetErrorMessage(r));
139
140         __waitStatus = WAIT_ON;
141         if (__threadType == THREAD_TYPE_MAIN)
142         {
143                 ecore_main_loop_begin();
144                 SysLog(NID_BASE_RT, "The waiting loop(ecore) is stopped.");
145         }
146         else
147         {
148                 while(!__timeout && __notifyWait)
149                 {       
150                         g_main_context_iteration(__pGmainContext, TRUE);
151                         Thread::Sleep(__sleepTime);
152                 }
153                 SysLog(NID_BASE_RT, "The waiting loop(glib) is stopped.");
154         }
155         __pTimer->Cancel();
156         __waitStatus = WAIT_OFF;
157
158         SysTryReturn(NID_BASE_RT, __timeout != true, E_TIMEOUT, E_TIMEOUT, "[E_TIMEOUT]The time is expired.");
159         
160         return E_SUCCESS;
161 }
162
163 result 
164 _WaitingLoopImpl::Wait(IWaitingLoopCondition& condition)
165 {
166         SysTryReturnResult(NID_BASE_RT, __waitStatus == WAIT_OFF, E_INVALID_STATE, "[E_INVALID_STATUS]The waiting loop is waiting on a thread.");
167
168         __timeout = false;
169         __waitType = WAIT_CONDITION;
170         __pWaitingLoopCondition = &condition;
171
172         if (__threadType == THREAD_TYPE_MAIN)
173         {
174                 result r = __pTimer->StartAsRepeatable(__waitingRepeatableTime);
175                 SysTryReturn(NID_BASE_RT, r == E_SUCCESS, r, r, "[%s]Timer does not start.", GetErrorMessage(r));
176         
177                 __waitStatus = WAIT_ON;
178                 ecore_main_loop_begin();
179                 SysLog(NID_BASE_RT, "The waiting loop(ecore) is stopped.");
180
181                 __pTimer->Cancel();
182         }
183         else
184         {
185                 __waitStatus = WAIT_ON;
186                 while(!__pWaitingLoopCondition->IsMet() && __notifyWait)
187                 {
188                         g_main_context_iteration(__pGmainContext, FALSE);
189                         Thread::Sleep(__sleepTime);
190                 }
191                 SysLog(NID_BASE_RT, "The waiting loop(glib) is stopped.");
192         }
193         __waitStatus = WAIT_OFF;
194
195         return E_SUCCESS;
196 }
197
198 result 
199 _WaitingLoopImpl::Wait(int timeout, IWaitingLoopCondition& condition)
200 {
201         SysTryReturnResult(NID_BASE_RT, __waitStatus == WAIT_OFF, E_INVALID_STATE, "[E_INVALID_STATUS]The waiting loop is waiting on a thread.");
202
203         __timeout = false;
204         __timerCalledCount = 0;
205         __waitType = WAIT_TIMEOUT_CONDITION;
206         __pWaitingLoopCondition = &condition;
207
208         if (timeout < __waitingRepeatableTime)
209         {
210                 result r = __pTimer->StartAsRepeatable(__waitingRepeatableTime);
211                 SysTryReturn(NID_BASE_RT, r == E_SUCCESS, r, r, "[%s]Timer does not start.", GetErrorMessage(r));
212         }
213         else
214         {
215                 result r = __pTimer->StartAsRepeatable(timeout/10);
216                 SysTryReturn(NID_BASE_RT, r == E_SUCCESS, r, r, "[%s]Timer does not start.", GetErrorMessage(r));       
217         }
218         __waitStatus = WAIT_ON;
219         if (__threadType == THREAD_TYPE_MAIN)
220         {
221                 ecore_main_loop_begin();
222                 SysLog(NID_BASE_RT, "The waiting loop(ecore) is stopped.");
223         }
224         else
225         {
226                 while(!__pWaitingLoopCondition->IsMet() && __timeout && __notifyWait)
227                 {
228                         g_main_context_iteration(__pGmainContext, TRUE);
229                         Thread::Sleep(__sleepTime);
230                 }
231                 SysLog(NID_BASE_RT, "The waiting loop(glib) is stopped.");
232         }
233
234         __pTimer->Cancel();
235         __waitStatus = WAIT_OFF;
236
237         SysTryReturn(NID_BASE_RT, __timeout != true, E_TIMEOUT, E_TIMEOUT, "[E_TIMEOUT]The time is expired.");
238
239         return E_SUCCESS;
240 }
241
242 void 
243 _WaitingLoopImpl::Notify(void)
244 {
245         SysTryReturnVoidResult(NID_BASE_RT, __waitStatus == WAIT_ON, E_INVALID_STATE, "[E_INVALID_STATUS]The waiting loop is not waiting on a thread.");
246         __notifyWait = false;
247
248         SysLog(NID_BASE_RT, "The waiting loop would be stopped from Notifying.");
249
250         if (__threadType == THREAD_TYPE_MAIN)
251         {
252                 ecore_main_loop_quit();
253         }
254 }
255
256 void 
257 _WaitingLoopImpl::SetMaxTimeoutForWaiting(int timeout)
258 {
259         if (timeout < __maxTime)
260         {
261                 __maxTimeout = __maxTime;
262         }
263         else
264         {
265                 __maxTimeout = timeout;
266         }
267 }
268
269 void 
270 _WaitingLoopImpl::OnTimerExpired(Timer& timer)
271 {
272         if (__threadType == THREAD_TYPE_MAIN)
273         {
274                 if (__waitType == WAIT_TIMEOUT)
275                 {
276                         ecore_main_loop_quit();
277                         SysLog(NID_BASE_RT, "The waiting loop is stopped from time out.");
278                         __timeout = true;
279                 }
280                 else if ((__waitType == WAIT_CONDITION) && __pWaitingLoopCondition->IsMet())
281                 {
282                         ecore_main_loop_quit(); 
283                         SysLog(NID_BASE_RT, "The waiting loop  is stopped from firing condition.");
284                 }
285                 else if (__waitType == WAIT_TIMEOUT_CONDITION)
286                 {
287                         __timerCalledCount++;
288                         if (__timerCalledCount == __waitingCount)
289                         {
290                                 ecore_main_loop_quit(); 
291                                 SysLog(NID_BASE_RT, "The waiting loop is stopped from time out.");
292                                 __timeout = true;
293                         }
294                         else
295                         {
296                                 if (__pWaitingLoopCondition->IsMet())
297                                 {
298                                         ecore_main_loop_quit(); 
299                                         SysLog(NID_BASE_RT, "The waiting loop is stopped from firing condition.");      
300                                 }       
301                         }               
302                 }
303         }
304         else
305         {
306                 if (__waitType == WAIT_TIMEOUT)
307                 {
308                         __timeout = true;
309                         SysLog(NID_BASE_RT, "The waiting loop is stopped from time out.");
310                 }
311                 else if (__waitType == WAIT_TIMEOUT_CONDITION)
312                 {
313                         __timerCalledCount++;
314                         if (__timerCalledCount == __waitingCount)
315                         {
316                                 __timeout = true;
317                                 SysLog(NID_BASE_RT, "The waiting loop is stopped from time out.");
318                         }
319                 }
320         }
321 }
322
323 bool
324 _WaitingLoopImpl::IsSameThread(void)
325 {
326         _ThreadImpl* pThreadImpl = _ThreadImpl::GetCurrentThreadImpl();
327         SysTryReturn(NID_BASE_RT, pThreadImpl != null, false, E_OBJ_NOT_FOUND,"This is not a OSP thread.");
328         
329         ThreadType threadType = pThreadImpl->GetThreadType();
330
331         if (__threadType == threadType)
332         {
333                 SysLog(NID_BASE_RT, "The waiting loop is working on the current thread.");
334                 return true;
335         }
336         else
337         {
338                 SysLog(NID_BASE_RT, "The waiting loop is working on another thread.");
339                 return false;
340         }       
341 }
342
343 } } } // Tizen::Base::Runtime
344