sync with tizen_2.0
[platform/framework/native/appfw.git] / src / base / runtime / FBaseRt_ThreadImpl.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_ThreadImpl.cpp
20  * @brief       This is the implementation file for the _ThreadImpl class.
21  *
22  */
23
24 #include <unistd.h>
25 #include <errno.h>
26
27 #include <FBaseRtThread.h>
28 #include <FBaseRtSemaphore.h>
29 #include <FBaseInteger.h>
30
31 #include "FBase_NativeError.h"
32 #include <FBaseSysLog.h>
33 #include "FBaseRt_ThreadImpl.h"
34 #include "FBaseRt_EventManager.h"
35 #include "FBaseRt_ThreadManager.h"
36
37 namespace Tizen { namespace Base { namespace Runtime
38 {
39
40 __thread Thread* pCurrentThread = null;
41
42 _ThreadImpl*
43 _ThreadImpl::GetCurrentThreadImpl(void)
44 {
45         if (pCurrentThread != null)
46         {
47                 return pCurrentThread->__pThreadImpl;
48         }
49
50         return null;
51 }
52
53 void
54 _ThreadImpl::Exit(int exitCode)
55 {
56         _ThreadImpl* pThreadImpl = GetCurrentThreadImpl();
57         if (pThreadImpl != null)
58         {
59                 pThreadImpl->__exitCode = exitCode;
60         }
61
62         pthread_exit(null);
63 }
64
65 result
66 _ThreadImpl::Sleep(long milliSeconds)
67 {
68         if (milliSeconds > 0)
69         {
70                 struct timespec tspec = { milliSeconds / 1000, (milliSeconds % 1000) * (1000 * 1000) };
71
72                 while (nanosleep(&tspec, &tspec) == -1)
73                 {
74                         if (errno == EINTR)
75                         {
76                                 continue;
77                         }
78                         else if (errno == EINVAL)
79                         {
80                                 return E_INVALID_ARG;}
81                         else
82                         {
83                                 return E_SYSTEM;
84                         }
85                 }
86
87                 return E_SUCCESS;
88         }
89         else if (milliSeconds == 0)
90         {
91                 return Yield();
92         }
93         else
94         {
95                 return E_INVALID_ARG;
96         }
97 }
98
99 result
100 _ThreadImpl::Yield(void)
101 {
102         int ret = pthread_yield();
103         SysTryReturnResult(NID_BASE_RT, ret == 0, E_SYSTEM, "Yield has failed due to a system error.");
104
105         return E_SUCCESS;
106 }
107
108 Thread*
109 _ThreadImpl::GetCurrentThread(void)
110 {
111         static Thread dummy;
112
113         if (pCurrentThread == null)
114         {
115                 return &dummy;
116         }
117
118         return pCurrentThread;
119 }
120
121 _ThreadImpl::_ThreadImpl(Thread& thread, const String& name, long stackSize, ThreadPriority priority, ThreadType threadType)
122         : _pThread(&thread)
123         , __name(name)
124         , __stackSize(stackSize)
125         , __priority(priority)
126         , __threadType(threadType)
127         , __nativeThread(0)
128         , __exitCode(0x0)
129         , __pEventManager(null)
130 {
131
132 }
133
134 _ThreadImpl::~_ThreadImpl(void)
135 {
136
137 }
138
139 result
140 _ThreadImpl::Join(void)
141 {
142         int ret = pthread_join(__nativeThread, null);
143         SysTryReturnResult(NID_BASE_RT, ret == 0, E_SYSTEM, "Thread join operation failed");
144
145         return E_SUCCESS;
146 }
147
148 result
149 _ThreadImpl::GetExitCode(int& exitCode) const
150 {
151         exitCode = __exitCode;
152
153         return E_SUCCESS;
154 }
155
156 const Tizen::Base::String&
157 _ThreadImpl::GetName(void) const
158 {
159         return __name;
160 }
161
162 result
163 _ThreadImpl::Start(void)
164 {
165         pthread_attr_t attr;
166         struct sched_param schedParam;
167
168         int ret = pthread_attr_init(&attr);
169         SysTryReturnResult(NID_BASE_RT, ret == 0, E_OUT_OF_MEMORY, "Not enough memory.");
170
171         int maxPriority = sched_get_priority_max(SCHED_FIFO);
172         int minPriority = sched_get_priority_min(SCHED_FIFO);
173
174         schedParam.sched_priority = (3 - (int) __priority) * ((maxPriority - minPriority + 1) / 3);
175
176         ret = pthread_create(&__nativeThread, &attr, _ThreadImpl::ThreadProc, this);
177         SysTryReturnResult(NID_BASE_RT, ret == 0, E_SYSTEM, "Create a thread has failed due to system error.");
178
179         pthread_attr_destroy(&attr);
180
181         return E_SUCCESS;
182 }
183
184 result
185 _ThreadImpl::Stop(void)
186 {
187         return E_SUCCESS;
188 }
189
190 Tizen::Base::Object*
191 _ThreadImpl::Run(void)
192 {
193         return null;
194 }
195
196 result
197 _ThreadImpl::Initialize(void)
198 {
199         pCurrentThread = _pThread;
200
201         return E_SUCCESS;
202 }
203
204 result
205 _ThreadImpl::Finalize(void)
206 {
207         pCurrentThread = null;
208
209         return E_SUCCESS;
210 }
211
212 result
213 _ThreadImpl::SendUserEvent(RequestId requestId, const Tizen::Base::Collection::IList* pArgs)
214 {
215         return E_INVALID_OPERATION;
216 }
217
218 const Thread*
219 _ThreadImpl::GetThread(void) const
220 {
221         return _pThread;
222 }
223
224 void
225 _ThreadImpl::SetThread(Thread* pThread)
226 {
227         _pThread = pThread;
228 }
229
230 void
231 _ThreadImpl::SetNativeThread(pthread_t nativeThread)
232 {
233         __nativeThread = nativeThread;
234 }
235
236 const ThreadPriority
237 _ThreadImpl::GetPriority(void) const
238 {
239         return __priority;
240 }
241
242 ThreadType
243 _ThreadImpl::GetThreadType(void) const
244 {
245         return __threadType;
246 }
247
248 void*
249 _ThreadImpl::ThreadProc(void* params)
250 {
251         _ThreadImpl* pSelf = (_ThreadImpl*) params;
252         if (pSelf == null)
253         {
254                 return null;
255         }
256
257         Thread* pThread = pSelf->_pThread;
258         if (pThread == null)
259         {
260                 return null;
261         }
262
263         result r = pSelf->Initialize();
264         if (IsFailed(r))
265         {
266                 return null;
267         }
268
269         if (pThread->OnStart())
270         {
271                 pSelf->Run();
272         }
273
274         pThread->OnStop();
275
276         pSelf->Finalize();
277
278         return null;
279 }
280
281 void
282 _ThreadImpl::SetEventManager(_EventManager* pEventManager)
283 {
284         __pEventManager = pEventManager;
285 }
286
287 _EventManager*
288 _ThreadImpl::GetEventManager(void)
289 {
290         return __pEventManager;
291 }
292
293
294 } } } // Tizen::Base::Runtime