Added preliminary Symbian support.
[silc.git] / lib / silcutil / symbian / silcsymbianthread.cpp
1 /*\r
2 \r
3   silcsymbianthread.cpp\r
4 \r
5   Author: Pekka Riikonen <priikone@silcnet.org>\r
6 \r
7   Copyright (C) 2006 Pekka Riikonen\r
8 \r
9   This program is free software; you can redistribute it and/or modify\r
10   it under the terms of the GNU General Public License as published by\r
11   the Free Software Foundation; version 2 of the License.\r
12 \r
13   This program is distributed in the hope that it will be useful,\r
14   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16   GNU General Public License for more details.\r
17 \r
18 */\r
19 \r
20 #include "silc.h"\r
21 #include <e32std.h>\r
22 \r
23 /**************************** SILC Thread API *******************************/\r
24 \r
25 /* Thread structure for Symbian */\r
26 typedef struct {\r
27 #ifdef SILC_THREADS\r
28   RThread *thread;\r
29   SilcThreadStart start_func;\r
30   void *context;\r
31   bool waitable;\r
32 #else\r
33   void *tmp;\r
34 #endif\r
35 } *SilcSymbianThread;\r
36 \r
37 /* The actual thread function */\r
38 \r
39 TInt silc_thread_epoc_start(TAny *context)\r
40 {\r
41 #ifdef SILC_THREADS\r
42   SilcSymbianThread thread = (SilcSymbianThread)context;\r
43   void *ret;\r
44 \r
45   ret = thread->start_func(thread->context);\r
46   silc_thread_exit(ret);\r
47 \r
48 #endif\r
49   return 0;\r
50 }\r
51 \r
52 SilcThread silc_thread_create(SilcThreadStart start_func, void *context,\r
53                               bool waitable)\r
54 {\r
55 #ifdef SILC_THREADS\r
56   SilcSymbianThread thread;\r
57   TInt ret;\r
58   TBuf<32> name;\r
59 \r
60   SILC_LOG_DEBUG(("Creating new thread"));\r
61 \r
62   thread = (SilcSymbianThread)silc_calloc(1, sizeof(*thread));\r
63   if (!thread)\r
64     return NULL;\r
65   thread->start_func = start_func;\r
66   thread->context = context;\r
67   thread->waitable = waitable;\r
68 \r
69   /* Create the thread */\r
70   /* XXX Unique name should be given for the thread */\r
71   thread->thread = new RThread();\r
72   if (!thread->thread) {\r
73     silc_free(thread);\r
74     return NULL;\r
75   }\r
76 \r
77   name = (TText *)"silc" + time(NULL);\r
78   ret = thread->thread->Create(name, silc_thread_epoc_start,\r
79                                8192, 4096, 1024 * 1024, (TAny *)thread);\r
80   if (ret != KErrNone) {\r
81     SILC_LOG_ERROR(("Could not create new thread"));\r
82     delete thread->thread;\r
83     silc_free(thread);\r
84     return NULL;\r
85   }\r
86   thread->thread->Resume();\r
87 \r
88   return (SilcThread)thread;\r
89 #else\r
90   /* Call thread callback immediately */\r
91   (*start_func)(context);\r
92   return NULL;\r
93 #endif\r
94 }\r
95 \r
96 void silc_thread_exit(void *exit_value)\r
97 {\r
98 #ifdef SILC_THREADS\r
99   /* XXX */\r
100 #endif\r
101 }\r
102 \r
103 SilcThread silc_thread_self(void)\r
104 {\r
105 #ifdef SILC_THREADS\r
106   /* XXX */\r
107   return NULL;\r
108 #else\r
109   return NULL;\r
110 #endif\r
111 }\r
112 \r
113 SilcBool silc_thread_wait(SilcThread thread, void **exit_value)\r
114 {\r
115 #ifdef SILC_THREADS\r
116   /* XXX */\r
117   return TRUE;\r
118 #else\r
119   return FALSE;\r
120 #endif\r
121 }\r
122 \r
123 /***************************** SILC Mutex API *******************************/\r
124 \r
125 /* SILC Mutex structure */\r
126 struct SilcMutexStruct {\r
127 #ifdef SILC_THREADS\r
128   RMutex *mutex;\r
129 #endif /* SILC_THREADS */\r
130   unsigned int locked : 1;\r
131 };\r
132 \r
133 SilcBool silc_mutex_alloc(SilcMutex *mutex)\r
134 {\r
135 #ifdef SILC_THREADS\r
136   *mutex = (SilcMutex)silc_calloc(1, sizeof(**mutex));\r
137   if (*mutex == NULL)\r
138     return FALSE;\r
139   (*mutex)->mutex = new RMutex();\r
140   if (!(*mutex)->mutex) {\r
141     silc_free(*mutex);\r
142     return FALSE;\r
143   }\r
144   if ((*mutex)->mutex->CreateLocal() != KErrNone) {\r
145     delete (*mutex)->mutex;\r
146     silc_free(*mutex);\r
147     return FALSE;\r
148   }\r
149   (*mutex)->locked = FALSE;\r
150   return TRUE;\r
151 #else\r
152   return FALSE;\r
153 #endif /* SILC_THREADS */\r
154 }\r
155 \r
156 void silc_mutex_free(SilcMutex mutex)\r
157 {\r
158 #ifdef SILC_THREADS\r
159   if (mutex) {\r
160     mutex->mutex->Close();\r
161     delete mutex->mutex;\r
162     silc_free(mutex);\r
163   }\r
164 #endif /* SILC_THREADS */\r
165 }\r
166 \r
167 void silc_mutex_lock(SilcMutex mutex)\r
168 {\r
169 #ifdef SILC_THREADS\r
170   if (mutex) {\r
171     mutex->mutex->Wait();\r
172     mutex->locked = TRUE;\r
173   }\r
174 #endif /* SILC_THREADS */\r
175 }\r
176 \r
177 void silc_mutex_unlock(SilcMutex mutex)\r
178 {\r
179 #ifdef SILC_THREADS\r
180   if (mutex) {\r
181     mutex->mutex->Signal();\r
182     mutex->locked = FALSE;\r
183   }\r
184 #endif /* SILC_THREADS */\r
185 }\r
186 \r
187 void silc_mutex_assert_locked(SilcMutex mutex)\r
188 {\r
189 #ifdef SILC_THREADS\r
190   if (mutex)\r
191     SILC_ASSERT(mutex->locked);\r
192 #endif /* SILC_THREADS */\r
193 }\r
194 \r
195 \r
196 /****************************** SILC Cond API *******************************/\r
197 \r
198 /* SILC Conditional Variable context */\r
199 struct SilcCondStruct {\r
200 #ifdef SILC_THREADS\r
201   RCondVar *cond;\r
202 #else\r
203   void *tmp;\r
204 #endif /* SILC_THREADS*/\r
205 };\r
206 \r
207 SilcBool silc_cond_alloc(SilcCond *cond)\r
208 {\r
209 #ifdef SILC_THREADS\r
210   *cond = (SilcCond)silc_calloc(1, sizeof(**cond));\r
211   if (*cond == NULL)\r
212     return FALSE;\r
213   (*cond)->cond = new RCondVar();\r
214   if (!(*cond)->cond) {\r
215     silc_free(*cond);\r
216     return FALSE;\r
217   }\r
218   if ((*cond)->cond->CreateLocal() != KErrNone) {\r
219     delete (*cond)->cond;\r
220     silc_free(*cond);\r
221     return FALSE;\r
222   }\r
223   return TRUE;\r
224 #else\r
225   return FALSE;\r
226 #endif /* SILC_THREADS*/\r
227 }\r
228 \r
229 void silc_cond_free(SilcCond cond)\r
230 {\r
231 #ifdef SILC_THREADS\r
232   cond->cond->Close();\r
233   delete cond->cond;\r
234   silc_free(cond);\r
235 #endif /* SILC_THREADS*/\r
236 }\r
237 \r
238 void silc_cond_signal(SilcCond cond)\r
239 {\r
240 #ifdef SILC_THREADS\r
241   cond->cond->Signal();\r
242 #endif /* SILC_THREADS*/\r
243 }\r
244 \r
245 void silc_cond_broadcast(SilcCond cond)\r
246 {\r
247 #ifdef SILC_THREADS\r
248   cond->cond->Broadcast();\r
249 #endif /* SILC_THREADS*/\r
250 }\r
251 \r
252 void silc_cond_wait(SilcCond cond, SilcMutex mutex)\r
253 {\r
254 #ifdef SILC_THREADS\r
255   cond->cond->Wait(*mutex->mutex);\r
256 #endif /* SILC_THREADS*/\r
257 }\r
258 \r
259 SilcBool silc_cond_timedwait(SilcCond cond, SilcMutex mutex,\r
260                              int timeout)\r
261 {\r
262 #ifdef SILC_THREADS\r
263   if (timeout)\r
264     return (cond->cond->TimedWait(*mutex->mutex, (TInt)timeout * 1000) ==\r
265             KErrNone);\r
266   return (cond->cond->Wait(*mutex->mutex) == KErrNone);\r
267 #else\r
268   return FALSE;\r
269 #endif /* SILC_THREADS*/\r
270 }\r