5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 2006 - 2007 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
24 /**************************** SILC Thread API *******************************/
28 /* Thread structure for Symbian */
29 struct SilcSymbianThread {
31 SilcThreadStart start_func;
39 /* The actual thread function */
41 static TInt silc_thread_start(TAny *context)
44 SilcSymbianThread *tc = (SilcSymbianThread *)context;
45 SilcThreadStart start_func = tc->start_func;
46 void *user_context = tc->context;
47 SilcBool waitable = tc->waitable;
52 CTrapCleanup *cs = CTrapCleanup::New();
54 CActiveScheduler *s = new CActiveScheduler;
56 CActiveScheduler::Install(s);
58 /* Call the thread function */
59 TRAPD(ret_val, ret = start_func(user_context));
66 silc_thread_exit(ret);
72 /* Executed new thread */
74 SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
78 SilcSymbianThread *tc;
84 SILC_LOG_DEBUG(("Creating new thread"));
86 tc = (SilcSymbianThread *)silc_calloc(1, sizeof(*tc));
89 tc->start_func = start_func;
90 tc->context = context;
91 tc->waitable = waitable;
100 /* Create the thread */
101 silc_snprintf(tmp, sizeof(tmp), "thread-%p", tc);
102 silc_utf8_c2w((const unsigned char *)tmp, strlen(tmp), wname,
103 sizeof(wname) / sizeof(wname[0]));
104 TBuf<24> name((unsigned short *)wname);
106 ret = thread->Create(name, silc_thread_start, 8192, NULL, tc);
107 if (ret != KErrNone) {
108 SILC_LOG_ERROR(("Could not create new thread, error %d", ret));
114 /* Start the thread */
117 /* Close our instance to the thread */
120 return (SilcThread)thread;
122 /* Call thread callback immediately */
123 (*start_func)(context);
128 /* Exits current thread */
130 void silc_thread_exit(void *exit_value)
133 RThread().Kill((TInt)exit_value);
137 /* Returns current thread context */
139 SilcThread silc_thread_self(void)
142 RThread thread = RThread();
143 return (SilcThread)&thread;
149 /* Blocks calling thread to wait for `thread' to finish. */
151 SilcBool silc_thread_wait(SilcThread thread, void **exit_value)
155 RThread *t = (RThread *)thread;
157 User::WaitForAnyRequest();
164 /* Yield processor */
166 void silc_thread_yield(void)
170 #endif /* SILC_THREADS */
173 /***************************** SILC Mutex API *******************************/
175 /* SILC Mutex structure */
176 struct SilcMutexStruct {
179 #endif /* SILC_THREADS */
180 unsigned int locked : 1;
183 SilcBool silc_mutex_alloc(SilcMutex *mutex)
186 *mutex = (SilcMutex)silc_calloc(1, sizeof(**mutex));
189 (*mutex)->mutex = new RMutex();
190 if (!(*mutex)->mutex) {
194 if ((*mutex)->mutex->CreateLocal() != KErrNone) {
195 delete (*mutex)->mutex;
199 (*mutex)->locked = FALSE;
203 #endif /* SILC_THREADS */
206 void silc_mutex_free(SilcMutex mutex)
210 mutex->mutex->Close();
214 #endif /* SILC_THREADS */
217 void silc_mutex_lock(SilcMutex mutex)
221 mutex->mutex->Wait();
222 mutex->locked = TRUE;
224 #endif /* SILC_THREADS */
227 void silc_mutex_unlock(SilcMutex mutex)
231 mutex->locked = FALSE;
232 mutex->mutex->Signal();
234 #endif /* SILC_THREADS */
237 void silc_mutex_assert_locked(SilcMutex mutex)
241 SILC_ASSERT(mutex->locked);
242 #endif /* SILC_THREADS */
245 /***************************** SILC Rwlock API *****************************/
247 /* SILC read/write lock structure */
248 struct SilcRwLockStruct {
252 #endif /* SILC_THREADS */
253 unsigned int readers : 31;
254 unsigned int locked : 1;
257 SilcBool silc_rwlock_alloc(SilcRwLock *rwlock)
260 *rwlock = (SilcRwLock)silc_calloc(1, sizeof(**rwlock));
263 if (!silc_mutex_alloc(&(*rwlock)->mutex)) {
267 if (!silc_cond_alloc(&(*rwlock)->cond)) {
268 silc_mutex_free((*rwlock)->mutex);
275 #endif /* SILC_THREADS */
278 void silc_rwlock_free(SilcRwLock rwlock)
282 silc_mutex_free(rwlock->mutex);
283 silc_cond_free(rwlock->cond);
286 #endif /* SILC_THREADS */
289 void silc_rwlock_rdlock(SilcRwLock rwlock)
293 silc_mutex_lock(rwlock->mutex);
295 silc_mutex_unlock(rwlock->mutex);
297 #endif /* SILC_THREADS */
300 void silc_rwlock_wrlock(SilcRwLock rwlock)
304 silc_mutex_lock(rwlock->mutex);
305 while (rwlock->readers > 0)
306 silc_cond_wait(rwlock->cond, rwlock->mutex);
307 rwlock->locked = TRUE;
309 #endif /* SILC_THREADS */
312 void silc_rwlock_unlock(SilcRwLock rwlock)
316 if (rwlock->locked) {
318 rwlock->locked = FALSE;
319 silc_mutex_unlock(rwlock->mutex);
324 silc_mutex_lock(rwlock->mutex);
326 silc_cond_broadcast(rwlock->cond);
327 silc_mutex_unlock(rwlock->mutex);
329 #endif /* SILC_THREADS */
332 /****************************** SILC Cond API *******************************/
334 /* SILC Conditional Variable context */
335 struct SilcCondStruct {
340 #endif /* SILC_THREADS*/
343 SilcBool silc_cond_alloc(SilcCond *cond)
346 *cond = (SilcCond)silc_calloc(1, sizeof(**cond));
349 (*cond)->cond = new RCondVar();
350 if (!(*cond)->cond) {
354 if ((*cond)->cond->CreateLocal() != KErrNone) {
355 delete (*cond)->cond;
362 #endif /* SILC_THREADS*/
365 void silc_cond_free(SilcCond cond)
371 #endif /* SILC_THREADS*/
374 void silc_cond_signal(SilcCond cond)
377 cond->cond->Signal();
378 #endif /* SILC_THREADS*/
381 void silc_cond_broadcast(SilcCond cond)
384 cond->cond->Broadcast();
385 #endif /* SILC_THREADS*/
388 void silc_cond_wait(SilcCond cond, SilcMutex mutex)
391 cond->cond->Wait(*mutex->mutex);
392 #endif /* SILC_THREADS*/
395 SilcBool silc_cond_timedwait(SilcCond cond, SilcMutex mutex,
401 ret = cond->cond->TimedWait(*mutex->mutex, (TInt)timeout * 1000);
403 SILC_LOG_DEBUG(("TimedWait returned %d", ret));
404 return ret != KErrTimedOut;
406 return (cond->cond->Wait(*mutex->mutex) == KErrNone);
409 #endif /* SILC_THREADS*/