source: libcf++/trunk/src/task.cpp@ 11

Last change on this file since 11 was 11, checked in by cheese, 9 years ago

#1 add new interfaces for bin and task

File size: 5.9 KB
Line 
1/**
2 * @file task.cpp
3 * @author myusgun@gmail.com
4 * @brief task
5 */
6#include "cf/task.h"
7#include "cf/memory.h"
8
9#ifdef _ON_WINDOWS
10# include <windows.h>
11# include <process.h>
12typedef HANDLE thread_t;
13typedef CRITICAL_SECTION mutex_t;
14# define THREAD_RETURN cf::ulong_t /**< return-type of thread worker */
15# define THREAD_CALL __stdcall
16#else
17# include <string.h>
18# include <unistd.h>
19# include <pthread.h>
20# include <errno.h>
21typedef pthread_t thread_t;
22typedef pthread_mutex_t mutex_t;
23# define THREAD_RETURN void * /**< return-type of thread worker */
24# define THREAD_CALL
25#endif
26
27typedef THREAD_RETURN(THREAD_CALL * THREAD_WORKER)(cf::void_t *);
28
29/*--------------------------------------------------------------*/
30static inline THREAD_RETURN THREAD_CALL Runner(cf::void_t * arg)
31{
32 cf::task::thread::THREAD_CTX * ctx = reinterpret_cast<cf::task::thread::THREAD_CTX *>(arg);
33
34 ctx->mReturned = ctx->mCallback(ctx->mArgument);
35 ctx->mIsRunning = false;
36
37 return (THREAD_RETURN)(ctx->mReturned ? -1 : 0);
38}
39/*--------------------------------------------------------------*/
40
41cf::task::mutex::mutex()
42 throw (cf::exception)
43 : mIsLocked(false)
44{
45 mutex_t * inst = NULL;
46
47 try
48 {
49 inst = reinterpret_cast<mutex_t *>(cf::memory::alloc(sizeof(mutex_t)));
50
51#ifdef _ON_WINDOWS
52 InitializeCriticalSection(inst);
53#else
54 if (pthread_mutex_init(inst, NULL))
55 THROW_EXCEPTION("cannot create mutex("
56 << errno << ":" << strerror(errno) << ")");
57#endif
58
59 mMutex = inst;
60 }
61 catch (cf::exception &e)
62 {
63 cf::memory::free(mMutex);
64 FORWARD_EXCEPTION(e);
65 }
66}
67
68cf::task::mutex::~mutex()
69{
70 mutex_t * inst = reinterpret_cast<mutex_t *>(mMutex);
71
72#ifdef _ON_WINDOWS
73 DeleteCriticalSection(inst);
74#else
75 pthread_mutex_destroy(inst);
76#endif
77
78 cf::memory::free(mMutex);
79}
80
81cf::void_t cf::task::mutex::lock()
82 throw (cf::exception)
83{
84 mutex_t * inst = (mutex_t *)mMutex;
85
86#ifdef _ON_WINDOWS
87 EnterCriticalSection(inst);
88#else
89 cf::int32_t result = pthread_mutex_lock(inst);
90 if (result)
91 THROW_EXCEPTION("cannot lock {" << result << "}");
92#endif
93
94 mIsLocked = true;
95}
96
97cf::void_t cf::task::mutex::unlock()
98 throw (cf::exception)
99{
100 mutex_t * inst = reinterpret_cast<mutex_t *>(mMutex);
101
102#ifdef _ON_WINDOWS
103 LeaveCriticalSection(inst);
104#else
105 cf::int32_t result = pthread_mutex_unlock(inst);
106 if (result)
107 THROW_EXCEPTION("cannot unlock {" << result << "}");
108#endif
109
110 mIsLocked = false;
111}
112
113cf::bool_t cf::task::mutex::trylock()
114 throw (cf::exception)
115{
116 cf::bool_t getLocking = false;
117 mutex_t * inst = reinterpret_cast<mutex_t *>(mMutex);
118
119#ifdef _ON_WINDOWS
120 getLocking = TryEnterCriticalSection(inst) ? true : false;
121#else
122 cf::int32_t result = pthread_mutex_trylock(inst);
123 switch (result)
124 {
125 case 0: getLocking = true; break;
126 case EBUSY: getLocking = false; break;
127 default:
128 THROW_EXCEPTION("cannot trylock {" << result << "}");
129 }
130#endif
131
132 if (getLocking)
133 mIsLocked = true;
134
135 return getLocking;
136}
137
138cf::bool_t cf::task::mutex::locked() const
139{
140 return mIsLocked;
141}
142
143cf::task::scopedLock::scopedLock(ISynchronizer * inst)
144 throw (cf::exception)
145 : mSynchronizer(inst)
146{
147 if (!mSynchronizer)
148 THROW_EXCEPTION("invalid synchronizer");
149
150 mSynchronizer->lock();
151}
152
153cf::task::scopedLock::~scopedLock()
154{
155 try
156 {
157 unlock();
158 }
159 catch (...)
160 {
161 }
162}
163
164cf::bool_t cf::task::scopedLock::locked() const
165{
166 return mSynchronizer->locked();
167}
168
169cf::void_t cf::task::scopedLock::unlock()
170 throw (cf::exception)
171{
172 mSynchronizer->unlock();
173}
174
175cf::task::thread::thread(const ThreadFunction callback)
176 throw (cf::exception)
177 : mThreadID(NULL)
178{
179 try
180 {
181 mCtx.mIsRunning = false;
182 mCtx.mCallback = callback;
183
184#ifndef _ON_WINDOWS
185 mThreadID = cf::memory::alloc(sizeof(thread_t));
186#endif
187 }
188 catch (cf::exception &e)
189 {
190 FORWARD_EXCEPTION(e);
191 }
192}
193
194cf::task::thread::~thread()
195{
196#ifdef _ON_WINDOWS
197 if (!mThreadID)
198 return;
199
200 CloseHandle(mThreadID);
201#else
202 cf::memory::free(mThreadID);
203#endif
204}
205
206cf::void_t cf::task::thread::start(cf::void_t * arg)
207 throw (cf::exception)
208{
209 try
210 {
211 if (mCtx.mIsRunning)
212 return;
213
214 if (!mMutex.trylock())
215 return;
216
217 mCtx.mArgument = arg;
218
219#ifdef _ON_WINDOWS
220 mThreadID = CreateThread(NULL, 0, Runner, &mCtx, 0, NULL);
221 if (mThreadID == NULL)
222 THROW_EXCEPTION("cannot create thread");
223#else
224 cf::int32_t result = 0;
225
226 pthread_attr_t * attr = NULL;
227# if defined(_SOLARIS)
228 pthread_attr_t solarisAttr;
229 struct sched_param sched;
230
231 attr = &solarisAttr;
232
233 result = pthread_attr_init(attr);
234 if (result)
235 THROW_EXCEPTION("cannot init. thread-attr");
236
237 result = pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
238 if (result)
239 THROW_EXCEPTION("cannot set thread-inherit-schedule-attr");
240
241 result = pthread_attr_setschedpolicy(attr, SCHED_RR);
242 if (result)
243 THROW_EXCEPTION("cannot set thread-schedule-policy-attr");
244
245 sched.sched_priority = 1;
246 result = pthread_attr_setschedparam(attr, &sched);
247 if (result)
248 THROW_EXCEPTION("cannot set thread-schedule-param-attr");
249# endif // # if defined(_SOLARIS)
250
251 result = pthread_create((thread_t *)mThreadID, attr, Runner, &mCtx);
252 if (result)
253 THROW_EXCEPTION("cannot create thread");
254#endif
255
256 mCtx.mIsRunning = true;
257
258 mMutex.unlock();
259 }
260 catch (cf::exception &e)
261 {
262 mMutex.unlock();
263 throw e;
264 }
265}
266
267cf::void_t cf::task::thread::join()
268{
269#ifdef _ON_WINDOWS
270 WaitForSingleObject(mThreadID, INFINITE);
271#else
272 cf::char_t status[16] = {0x00,};
273 pthread_join(*((thread_t *)mThreadID), (cf::void_t **)status);
274#endif
275}
276
277cf::bool_t cf::task::thread::isRunning() const
278{
279 return mCtx.mIsRunning;
280}
281
282cf::uint32_t cf::task::thread::id()
283{
284#ifdef _ON_WINDOWS
285 DWORD tid = GetCurrentThreadId();
286#else
287 pthread_t tid = pthread_self();
288#endif
289
290 return static_cast<cf::uint32_t>(tid);
291}
292
293cf::void_t cf::task::thread::sleep(cf::int32_t milliseconds)
294{
295#ifdef _ON_WINDOWS
296 Sleep(static_cast<DWORD>(milliseconds));
297#else
298 usleep(milliseconds * 1000);
299#endif
300}
301
302cf::uint32_t cf::task::process::id()
303{
304#ifdef _ON_WINDOWS
305 DWORD pid = GetCurrentProcessId();
306#else
307 pid_t pid = getpid();
308#endif
309
310 return static_cast<cf::uint32_t>(pid);
311}
Note: See TracBrowser for help on using the repository browser.