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.
23 /**************************** SILC Thread API *******************************/
27 /* Thread structure for Symbian */
30 SilcThreadStart start_func;
38 /* The actual thread function */
40 static TInt silc_thread_start(TAny *context)
43 SilcSymbianThread tc = (SilcSymbianThread)context;
44 SilcThreadStart start_func = tc->start_func;
45 void *user_context = tc->context;
46 SilcBool waitable = tc->waitable;
50 /* Call the thread function */
52 silc_thread_exit(start_func(user_context));
54 start_func(user_context);
60 /* Executed new thread */
62 SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
71 SILC_LOG_DEBUG(("Creating new thread"));
73 tc = (SilcSymbianThread)silc_calloc(1, sizeof(*thread));
76 tc->start_func = start_func;
77 tc->context = context;
78 tc->waitable = waitable;
81 thread = new RThread();
87 /* Create the thread */
88 name = (TText *)silc_time_string(0);
89 ret = thread->Create(name, silc_thread_start, 8192, 4096, 1024 * 1024,
91 if (ret != KErrNone) {
92 SILC_LOG_ERROR(("Could not create new thread"));
98 /* Start the thread */
101 /* Close our instance to the thread */
104 return (SilcThread)thread;
106 /* Call thread callback immediately */
107 (*start_func)(context);
112 /* Exits current thread */
114 void silc_thread_exit(void *exit_value)
117 RThread().Kill((TInt)exit_value);
121 /* Returns current thread context */
123 SilcThread silc_thread_self(void)
126 RThread thread = RThread();
127 return (SilcThread)&thread;
133 /* Blocks calling thread to wait for `thread' to finish. */
135 SilcBool silc_thread_wait(SilcThread thread, void **exit_value)
139 RThread *t = (RThread *)thread;
141 User::WaitForAnyRequest();
148 /* Yield processor */
150 void silc_thread_yield(void)
154 #endif /* SILC_THREADS */
157 /***************************** SILC Mutex API *******************************/
159 /* SILC Mutex structure */
160 struct SilcMutexStruct {
163 #endif /* SILC_THREADS */
164 unsigned int locked : 1;
167 SilcBool silc_mutex_alloc(SilcMutex *mutex)
170 *mutex = (SilcMutex)silc_calloc(1, sizeof(**mutex));
173 (*mutex)->mutex = new RMutex();
174 if (!(*mutex)->mutex) {
178 if ((*mutex)->mutex->CreateLocal() != KErrNone) {
179 delete (*mutex)->mutex;
183 (*mutex)->locked = FALSE;
187 #endif /* SILC_THREADS */
190 void silc_mutex_free(SilcMutex mutex)
194 mutex->mutex->Close();
198 #endif /* SILC_THREADS */
201 void silc_mutex_lock(SilcMutex mutex)
205 mutex->mutex->Wait();
206 mutex->locked = TRUE;
208 #endif /* SILC_THREADS */
211 void silc_mutex_unlock(SilcMutex mutex)
215 mutex->mutex->Signal();
216 mutex->locked = FALSE;
218 #endif /* SILC_THREADS */
221 void silc_mutex_assert_locked(SilcMutex mutex)
225 SILC_ASSERT(mutex->locked);
226 #endif /* SILC_THREADS */
229 /***************************** SILC Rwlock API *****************************/
231 /* SILC read/write lock structure */
232 struct SilcRwLockStruct {
236 #endif /* SILC_THREADS */
237 unsigned int readers : 31;
238 unsigned int locked : 1;
241 SilcBool silc_rwlock_alloc(SilcRwLock *rwlock)
244 *rwlock = (SilcRwLock)silc_calloc(1, sizeof(**rwlock));
247 if (!silc_mutex_alloc(&(*rwlock)->mutex)) {
251 if (!silc_cond_alloc(&(*rwlock)->cond)) {
252 silc_mutex_free((*rwlock)->mutex);
259 #endif /* SILC_THREADS */
262 void silc_rwlock_free(SilcRwLock rwlock)
266 silc_mutex_free(rwlock->mutex);
267 silc_cond_free(rwlock->cond);
270 #endif /* SILC_THREADS */
273 void silc_rwlock_rdlock(SilcRwLock rwlock)
277 silc_mutex_lock(rwlock->mutex);
279 silc_mutex_unlock(rwlock->mutex);
281 #endif /* SILC_THREADS */
284 void silc_rwlock_wrlock(SilcRwLock rwlock)
288 silc_mutex_lock(rwlock->mutex);
289 while (rwlock->readers > 0)
290 silc_cond_wait(rwlock->cond, rwlock->mutex);
291 rwlock->locked = TRUE;
293 #endif /* SILC_THREADS */
296 void silc_rwlock_unlock(SilcRwLock rwlock)
300 if (rwlock->locked) {
302 rwlock->locked = FALSE;
303 silc_mutex_unlock(rwlock->mutex);
308 silc_mutex_lock(rwlock->mutex);
310 silc_cond_broadcast(rwlock->cond);
311 silc_mutex_unlock(rwlock->mutex);
313 #endif /* SILC_THREADS */
316 /****************************** SILC Cond API *******************************/
318 /* SILC Conditional Variable context */
319 struct SilcCondStruct {
324 #endif /* SILC_THREADS*/
327 SilcBool silc_cond_alloc(SilcCond *cond)
330 *cond = (SilcCond)silc_calloc(1, sizeof(**cond));
333 (*cond)->cond = new RCondVar();
334 if (!(*cond)->cond) {
338 if ((*cond)->cond->CreateLocal() != KErrNone) {
339 delete (*cond)->cond;
346 #endif /* SILC_THREADS*/
349 void silc_cond_free(SilcCond cond)
355 #endif /* SILC_THREADS*/
358 void silc_cond_signal(SilcCond cond)
361 cond->cond->Signal();
362 #endif /* SILC_THREADS*/
365 void silc_cond_broadcast(SilcCond cond)
368 cond->cond->Broadcast();
369 #endif /* SILC_THREADS*/
372 void silc_cond_wait(SilcCond cond, SilcMutex mutex)
375 cond->cond->Wait(*mutex->mutex);
376 #endif /* SILC_THREADS*/
379 SilcBool silc_cond_timedwait(SilcCond cond, SilcMutex mutex,
384 return (cond->cond->TimedWait(*mutex->mutex, (TInt)timeout * 1000) ==
386 return (cond->cond->Wait(*mutex->mutex) == KErrNone);
389 #endif /* SILC_THREADS*/