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;
53 tls = silc_thread_tls_init();
55 CTrapCleanup *cs = CTrapCleanup::New();
57 CActiveScheduler *s = new CActiveScheduler;
59 CActiveScheduler::Install(s);
61 /* Call the thread function */
62 TRAPD(ret_val, ret = start_func(user_context));
70 silc_thread_exit(ret);
76 /* Executed new thread */
78 SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
82 SilcSymbianThread *tc;
88 SILC_LOG_DEBUG(("Creating new thread"));
90 tc = (SilcSymbianThread *)silc_calloc(1, sizeof(*tc));
93 tc->start_func = start_func;
94 tc->context = context;
95 tc->waitable = waitable;
104 /* Create the thread */
105 silc_snprintf(tmp, sizeof(tmp), "thread-%p", tc);
106 silc_utf8_c2w((const unsigned char *)tmp, strlen(tmp), wname,
107 sizeof(wname) / sizeof(wname[0]));
108 TBuf<24> name((unsigned short *)wname);
110 ret = thread->Create(name, silc_thread_start, 8192, NULL, tc);
111 if (ret != KErrNone) {
112 SILC_LOG_ERROR(("Could not create new thread, error %d", ret));
118 /* Start the thread */
121 /* Close our instance to the thread */
124 return (SilcThread)thread;
126 /* Call thread callback immediately */
127 (*start_func)(context);
132 /* Exits current thread */
134 void silc_thread_exit(void *exit_value)
137 RThread().Kill((TInt)exit_value);
141 /* Returns current thread context */
143 SilcThread silc_thread_self(void)
146 RThread thread = RThread();
147 return (SilcThread)&thread;
153 /* Blocks calling thread to wait for `thread' to finish. */
155 SilcBool silc_thread_wait(SilcThread thread, void **exit_value)
159 RThread *t = (RThread *)thread;
161 User::WaitForAnyRequest();
168 /* Yield processor */
170 void silc_thread_yield(void)
174 #endif /* SILC_THREADS */
177 /***************************** SILC Mutex API *******************************/
179 /* SILC Mutex structure */
180 struct SilcMutexStruct {
183 #endif /* SILC_THREADS */
184 unsigned int locked : 1;
187 SilcBool silc_mutex_alloc(SilcMutex *mutex)
190 *mutex = (SilcMutex)silc_calloc(1, sizeof(**mutex));
193 (*mutex)->mutex = new RMutex();
194 if (!(*mutex)->mutex) {
198 if ((*mutex)->mutex->CreateLocal() != KErrNone) {
199 delete (*mutex)->mutex;
203 (*mutex)->locked = FALSE;
207 #endif /* SILC_THREADS */
210 void silc_mutex_free(SilcMutex mutex)
214 mutex->mutex->Close();
218 #endif /* SILC_THREADS */
221 void silc_mutex_lock(SilcMutex mutex)
225 mutex->mutex->Wait();
226 mutex->locked = TRUE;
228 #endif /* SILC_THREADS */
231 void silc_mutex_unlock(SilcMutex mutex)
235 mutex->locked = FALSE;
236 mutex->mutex->Signal();
238 #endif /* SILC_THREADS */
241 void silc_mutex_assert_locked(SilcMutex mutex)
245 SILC_ASSERT(mutex->locked);
246 #endif /* SILC_THREADS */
249 /***************************** SILC Rwlock API *****************************/
251 /* SILC read/write lock structure */
252 struct SilcRwLockStruct {
256 #endif /* SILC_THREADS */
257 unsigned int readers : 31;
258 unsigned int locked : 1;
261 SilcBool silc_rwlock_alloc(SilcRwLock *rwlock)
264 *rwlock = (SilcRwLock)silc_calloc(1, sizeof(**rwlock));
267 if (!silc_mutex_alloc(&(*rwlock)->mutex)) {
271 if (!silc_cond_alloc(&(*rwlock)->cond)) {
272 silc_mutex_free((*rwlock)->mutex);
279 #endif /* SILC_THREADS */
282 void silc_rwlock_free(SilcRwLock rwlock)
286 silc_mutex_free(rwlock->mutex);
287 silc_cond_free(rwlock->cond);
290 #endif /* SILC_THREADS */
293 void silc_rwlock_rdlock(SilcRwLock rwlock)
297 silc_mutex_lock(rwlock->mutex);
299 silc_mutex_unlock(rwlock->mutex);
301 #endif /* SILC_THREADS */
304 void silc_rwlock_wrlock(SilcRwLock rwlock)
308 silc_mutex_lock(rwlock->mutex);
309 while (rwlock->readers > 0)
310 silc_cond_wait(rwlock->cond, rwlock->mutex);
311 rwlock->locked = TRUE;
313 #endif /* SILC_THREADS */
316 void silc_rwlock_unlock(SilcRwLock rwlock)
320 if (rwlock->locked) {
322 rwlock->locked = FALSE;
323 silc_mutex_unlock(rwlock->mutex);
328 silc_mutex_lock(rwlock->mutex);
330 silc_cond_broadcast(rwlock->cond);
331 silc_mutex_unlock(rwlock->mutex);
333 #endif /* SILC_THREADS */
336 /****************************** SILC Cond API *******************************/
338 /* SILC Conditional Variable context */
339 struct SilcCondStruct {
344 #endif /* SILC_THREADS*/
347 SilcBool silc_cond_alloc(SilcCond *cond)
350 *cond = (SilcCond)silc_calloc(1, sizeof(**cond));
353 (*cond)->cond = new RCondVar();
354 if (!(*cond)->cond) {
358 if ((*cond)->cond->CreateLocal() != KErrNone) {
359 delete (*cond)->cond;
366 #endif /* SILC_THREADS*/
369 void silc_cond_free(SilcCond cond)
375 #endif /* SILC_THREADS*/
378 void silc_cond_signal(SilcCond cond)
381 cond->cond->Signal();
382 #endif /* SILC_THREADS*/
385 void silc_cond_broadcast(SilcCond cond)
388 cond->cond->Broadcast();
389 #endif /* SILC_THREADS*/
392 void silc_cond_wait(SilcCond cond, SilcMutex mutex)
395 cond->cond->Wait(*mutex->mutex);
396 #endif /* SILC_THREADS*/
399 SilcBool silc_cond_timedwait(SilcCond cond, SilcMutex mutex,
405 ret = cond->cond->TimedWait(*mutex->mutex, (TInt)timeout * 1000);
407 SILC_LOG_DEBUG(("TimedWait returned %d", ret));
408 return ret != KErrTimedOut;
410 return (cond->cond->Wait(*mutex->mutex) == KErrNone);
413 #endif /* SILC_THREADS*/
416 /************************** Thread-local Storage ****************************/
418 SilcTls silc_thread_tls_init(void)
422 if (silc_thread_get_tls())
423 return silc_thread_get_tls();
425 /* Allocate Tls for the thread */
426 tls = (SilcTls)silc_calloc(1, sizeof(*tls));
435 SilcTls silc_thread_get_tls(void)
437 return STATIC_CAST(SilcTls, Dll::Tls());