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

Last change on this file since 24 was 24, checked in by cheese, 8 years ago

#1 bin::operator +() 버그 수정 및 task::thread 소멸 시 포인터 초기화 하도록 수정

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 mMutex = NULL;
80}
81
82cf::void_t cf::task::mutex::lock()
83 throw (cf::exception)
84{
85 mutex_t * inst = (mutex_t *)mMutex;
86
87#ifdef _ON_WINDOWS
88 EnterCriticalSection(inst);
89#else
90 cf::int32_t result = pthread_mutex_lock(inst);
91 if (result)
92 THROW_EXCEPTION("cannot lock {" << result << "}");
93#endif
94
95 mIsLocked = true;
96}
97
98cf::void_t cf::task::mutex::unlock()
99 throw (cf::exception)
100{
101 mutex_t * inst = reinterpret_cast<mutex_t *>(mMutex);
102
103#ifdef _ON_WINDOWS
104 LeaveCriticalSection(inst);
105#else
106 cf::int32_t result = pthread_mutex_unlock(inst);
107 if (result)
108 THROW_EXCEPTION("cannot unlock {" << result << "}");
109#endif
110
111 mIsLocked = false;
112}
113
114cf::bool_t cf::task::mutex::trylock()
115 throw (cf::exception)
116{
117 cf::bool_t getLocking = false;
118 mutex_t * inst = reinterpret_cast<mutex_t *>(mMutex);
119
120#ifdef _ON_WINDOWS
121 getLocking = TryEnterCriticalSection(inst) ? true : false;
122#else
123 cf::int32_t result = pthread_mutex_trylock(inst);
124 switch (result)
125 {
126 case 0: getLocking = true; break;
127 case EBUSY: getLocking = false; break;
128 default:
129 THROW_EXCEPTION("cannot trylock {" << result << "}");
130 }
131#endif
132
133 if (getLocking)
134 mIsLocked = true;
135
136 return getLocking;
137}
138
139cf::bool_t cf::task::mutex::isLocked() const
140{
141 return mIsLocked;
142}
143
144cf::task::scopedLock::scopedLock(ISynchronizer * inst)
145 throw (cf::exception)
146 : mSynchronizer(inst)
147{
148 if (!mSynchronizer)
149 THROW_EXCEPTION("invalid synchronizer");
150
151 mSynchronizer->lock();
152}
153
154cf::task::scopedLock::~scopedLock()
155{
156 try
157 {
158 unlock();
159 }
160 catch (...)
161 {
162 }
163}
164
165cf::bool_t cf::task::scopedLock::isLocked() const
166{
167 return mSynchronizer->isLocked();
168}
169
170cf::void_t cf::task::scopedLock::unlock()
171 throw (cf::exception)
172{
173 mSynchronizer->unlock();
174}
175
176cf::task::thread::thread(const ThreadFunction callback)
177 throw (cf::exception)
178 : mThreadID(NULL)
179{
180 try
181 {
182 mCtx.mIsRunning = false;
183 mCtx.mCallback = callback;
184
185#ifndef _ON_WINDOWS
186 mThreadID = cf::memory::alloc(sizeof(thread_t));
187#endif
188 }
189 catch (cf::exception &e)
190 {
191 FORWARD_EXCEPTION(e);
192 }
193}
194
195cf::task::thread::~thread()
196{
197#ifdef _ON_WINDOWS
198 if (!mThreadID)
199 return;
200
201 CloseHandle(mThreadID);
202#else
203 cf::memory::free(mThreadID);
204#endif
205}
206
207cf::void_t cf::task::thread::start(cf::void_t * arg)
208 throw (cf::exception)
209{
210 try
211 {
212 if (mCtx.mIsRunning)
213 return;
214
215 if (!mMutex.trylock())
216 return;
217
218 mCtx.mArgument = arg;
219
220#ifdef _ON_WINDOWS
221 mThreadID = CreateThread(NULL, 0, Runner, &mCtx, 0, NULL);
222 if (mThreadID == NULL)
223 THROW_EXCEPTION("cannot create thread");
224#else
225 cf::int32_t result = 0;
226
227 pthread_attr_t * attr = NULL;
228# if defined(_SOLARIS)
229 pthread_attr_t solarisAttr;
230 struct sched_param sched;
231
232 attr = &solarisAttr;
233
234 result = pthread_attr_init(attr);
235 if (result)
236 THROW_EXCEPTION("cannot init. thread-attr");
237
238 result = pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
239 if (result)
240 THROW_EXCEPTION("cannot set thread-inherit-schedule-attr");
241
242 result = pthread_attr_setschedpolicy(attr, SCHED_RR);
243 if (result)
244 THROW_EXCEPTION("cannot set thread-schedule-policy-attr");
245
246 sched.sched_priority = 1;
247 result = pthread_attr_setschedparam(attr, &sched);
248 if (result)
249 THROW_EXCEPTION("cannot set thread-schedule-param-attr");
250# endif // # if defined(_SOLARIS)
251
252 result = pthread_create((thread_t *)mThreadID, attr, Runner, &mCtx);
253 if (result)
254 THROW_EXCEPTION("cannot create thread");
255#endif
256
257 mCtx.mIsRunning = true;
258
259 mMutex.unlock();
260 }
261 catch (cf::exception &e)
262 {
263 mMutex.unlock();
264 throw e;
265 }
266}
267
268cf::void_t cf::task::thread::join()
269{
270#ifdef _ON_WINDOWS
271 WaitForSingleObject(mThreadID, INFINITE);
272#else
273 cf::char_t status[16] = {0x00,};
274 pthread_join(*((thread_t *)mThreadID), (cf::void_t **)status);
275#endif
276}
277
278cf::bool_t cf::task::thread::isRunning() const
279{
280 return mCtx.mIsRunning;
281}
282
283cf::uint32_t cf::task::thread::id()
284{
285#ifdef _ON_WINDOWS
286 DWORD tid = GetCurrentThreadId();
287#else
288 pthread_t tid = pthread_self();
289#endif
290
291 return static_cast<cf::uint32_t>(tid);
292}
293
294cf::void_t cf::task::thread::sleep(cf::int32_t milliseconds)
295{
296#ifdef _ON_WINDOWS
297 Sleep(static_cast<DWORD>(milliseconds));
298#else
299 usleep(milliseconds * 1000);
300#endif
301}
302
303cf::uint32_t cf::task::process::id()
304{
305#ifdef _ON_WINDOWS
306 DWORD pid = GetCurrentProcessId();
307#else
308 pid_t pid = getpid();
309#endif
310
311 return static_cast<cf::uint32_t>(pid);
312}
Note: See TracBrowser for help on using the repository browser.