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

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

#1 commit prototype

File size: 5.8 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 (!synchronizer())
148 THROW_EXCEPTION("invalid synchronizer");
149
150 synchronizer()->lock();
151}
152
153cf::task::scopedLock::~scopedLock()
154{
155 try
156 {
157 synchronizer()->unlock();
158 }
159 catch (...)
160 {
161 }
162}
163
164cf::task::ISynchronizer * cf::task::scopedLock::synchronizer()
165{
166 return mSynchronizer;
167}
168
169cf::task::thread::thread(const ThreadFunction callback)
170 throw (cf::exception)
171 : mThreadID(NULL)
172{
173 try
174 {
175 mCtx.mIsRunning = false;
176 mCtx.mCallback = callback;
177
178#ifndef _ON_WINDOWS
179 mThreadID = cf::memory::alloc(sizeof(thread_t));
180#endif
181 }
182 catch (cf::exception &e)
183 {
184 FORWARD_EXCEPTION(e);
185 }
186}
187
188cf::task::thread::~thread()
189{
190#ifdef _ON_WINDOWS
191 if (!mThreadID)
192 return;
193
194 CloseHandle(mThreadID);
195#else
196 cf::memory::free(mThreadID);
197#endif
198}
199
200cf::void_t cf::task::thread::start(cf::void_t * arg)
201 throw (cf::exception)
202{
203 try
204 {
205 if (mCtx.mIsRunning)
206 return;
207
208 if (!mMutex.trylock())
209 return;
210
211 mCtx.mArgument = arg;
212
213#ifdef _ON_WINDOWS
214 mThreadID = CreateThread(NULL, 0, Runner, &mCtx, 0, NULL);
215 if (mThreadID == NULL)
216 THROW_EXCEPTION("cannot create thread");
217#else
218 cf::int32_t result = 0;
219
220 pthread_attr_t * attr = NULL;
221# if defined(_SOLARIS)
222 pthread_attr_t solarisAttr;
223 struct sched_param sched;
224
225 attr = &solarisAttr;
226
227 result = pthread_attr_init(attr);
228 if (result)
229 THROW_EXCEPTION("cannot init. thread-attr");
230
231 result = pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
232 if (result)
233 THROW_EXCEPTION("cannot set thread-inherit-schedule-attr");
234
235 result = pthread_attr_setschedpolicy(attr, SCHED_RR);
236 if (result)
237 THROW_EXCEPTION("cannot set thread-schedule-policy-attr");
238
239 sched.sched_priority = 1;
240 result = pthread_attr_setschedparam(attr, &sched);
241 if (result)
242 THROW_EXCEPTION("cannot set thread-schedule-param-attr");
243# endif // # if defined(_SOLARIS)
244
245 result = pthread_create((thread_t *)mThreadID, attr, Runner, &mCtx);
246 if (result)
247 THROW_EXCEPTION("cannot create thread");
248#endif
249
250 mCtx.mIsRunning = true;
251
252 mMutex.unlock();
253 }
254 catch (cf::exception &e)
255 {
256 mMutex.unlock();
257 throw e;
258 }
259}
260
261cf::void_t cf::task::thread::join()
262{
263#ifdef _ON_WINDOWS
264 WaitForSingleObject(mThreadID, INFINITE);
265#else
266 cf::char_t status[16] = {0x00,};
267 pthread_join(*((thread_t *)mThreadID), (cf::void_t **)status);
268#endif
269}
270
271cf::bool_t cf::task::thread::isRunning() const
272{
273 return mCtx.mIsRunning;
274}
275
276cf::uint32_t cf::task::thread::id()
277{
278#ifdef _ON_WINDOWS
279 DWORD tid = GetCurrentThreadId();
280#else
281 pthread_t tid = pthread_self();
282#endif
283
284 return static_cast<cf::uint32_t>(tid);
285}
286
287cf::void_t cf::task::thread::sleep(cf::int32_t milliseconds)
288{
289#ifdef _ON_WINDOWS
290 Sleep(static_cast<DWORD>(milliseconds));
291#else
292 usleep(milliseconds * 1000);
293#endif
294}
295
296cf::uint32_t cf::task::process::id()
297{
298#ifdef _ON_WINDOWS
299 DWORD pid = GetCurrentProcessId();
300#else
301 pid_t pid = getpid();
302#endif
303
304 return static_cast<cf::uint32_t>(pid);
305}
Note: See TracBrowser for help on using the repository browser.