Added preliminary Symbian support.
[silc.git] / lib / silcutil / symbian / silcsymbianthread.cpp
diff --git a/lib/silcutil/symbian/silcsymbianthread.cpp b/lib/silcutil/symbian/silcsymbianthread.cpp
new file mode 100644 (file)
index 0000000..5d637b4
--- /dev/null
@@ -0,0 +1,270 @@
+/*\r
+\r
+  silcsymbianthread.cpp\r
+\r
+  Author: Pekka Riikonen <priikone@silcnet.org>\r
+\r
+  Copyright (C) 2006 Pekka Riikonen\r
+\r
+  This program is free software; you can redistribute it and/or modify\r
+  it under the terms of the GNU General Public License as published by\r
+  the Free Software Foundation; version 2 of the License.\r
+\r
+  This program is distributed in the hope that it will be useful,\r
+  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+  GNU General Public License for more details.\r
+\r
+*/\r
+\r
+#include "silc.h"\r
+#include <e32std.h>\r
+\r
+/**************************** SILC Thread API *******************************/\r
+\r
+/* Thread structure for Symbian */\r
+typedef struct {\r
+#ifdef SILC_THREADS\r
+  RThread *thread;\r
+  SilcThreadStart start_func;\r
+  void *context;\r
+  bool waitable;\r
+#else\r
+  void *tmp;\r
+#endif\r
+} *SilcSymbianThread;\r
+\r
+/* The actual thread function */\r
+\r
+TInt silc_thread_epoc_start(TAny *context)\r
+{\r
+#ifdef SILC_THREADS\r
+  SilcSymbianThread thread = (SilcSymbianThread)context;\r
+  void *ret;\r
+\r
+  ret = thread->start_func(thread->context);\r
+  silc_thread_exit(ret);\r
+\r
+#endif\r
+  return 0;\r
+}\r
+\r
+SilcThread silc_thread_create(SilcThreadStart start_func, void *context,\r
+                             bool waitable)\r
+{\r
+#ifdef SILC_THREADS\r
+  SilcSymbianThread thread;\r
+  TInt ret;\r
+  TBuf<32> name;\r
+\r
+  SILC_LOG_DEBUG(("Creating new thread"));\r
+\r
+  thread = (SilcSymbianThread)silc_calloc(1, sizeof(*thread));\r
+  if (!thread)\r
+    return NULL;\r
+  thread->start_func = start_func;\r
+  thread->context = context;\r
+  thread->waitable = waitable;\r
+\r
+  /* Create the thread */\r
+  /* XXX Unique name should be given for the thread */\r
+  thread->thread = new RThread();\r
+  if (!thread->thread) {\r
+    silc_free(thread);\r
+    return NULL;\r
+  }\r
+\r
+  name = (TText *)"silc" + time(NULL);\r
+  ret = thread->thread->Create(name, silc_thread_epoc_start,\r
+                              8192, 4096, 1024 * 1024, (TAny *)thread);\r
+  if (ret != KErrNone) {\r
+    SILC_LOG_ERROR(("Could not create new thread"));\r
+    delete thread->thread;\r
+    silc_free(thread);\r
+    return NULL;\r
+  }\r
+  thread->thread->Resume();\r
+\r
+  return (SilcThread)thread;\r
+#else\r
+  /* Call thread callback immediately */\r
+  (*start_func)(context);\r
+  return NULL;\r
+#endif\r
+}\r
+\r
+void silc_thread_exit(void *exit_value)\r
+{\r
+#ifdef SILC_THREADS\r
+  /* XXX */\r
+#endif\r
+}\r
+\r
+SilcThread silc_thread_self(void)\r
+{\r
+#ifdef SILC_THREADS\r
+  /* XXX */\r
+  return NULL;\r
+#else\r
+  return NULL;\r
+#endif\r
+}\r
+\r
+SilcBool silc_thread_wait(SilcThread thread, void **exit_value)\r
+{\r
+#ifdef SILC_THREADS\r
+  /* XXX */\r
+  return TRUE;\r
+#else\r
+  return FALSE;\r
+#endif\r
+}\r
+\r
+/***************************** SILC Mutex API *******************************/\r
+\r
+/* SILC Mutex structure */\r
+struct SilcMutexStruct {\r
+#ifdef SILC_THREADS\r
+  RMutex *mutex;\r
+#endif /* SILC_THREADS */\r
+  unsigned int locked : 1;\r
+};\r
+\r
+SilcBool silc_mutex_alloc(SilcMutex *mutex)\r
+{\r
+#ifdef SILC_THREADS\r
+  *mutex = (SilcMutex)silc_calloc(1, sizeof(**mutex));\r
+  if (*mutex == NULL)\r
+    return FALSE;\r
+  (*mutex)->mutex = new RMutex();\r
+  if (!(*mutex)->mutex) {\r
+    silc_free(*mutex);\r
+    return FALSE;\r
+  }\r
+  if ((*mutex)->mutex->CreateLocal() != KErrNone) {\r
+    delete (*mutex)->mutex;\r
+    silc_free(*mutex);\r
+    return FALSE;\r
+  }\r
+  (*mutex)->locked = FALSE;\r
+  return TRUE;\r
+#else\r
+  return FALSE;\r
+#endif /* SILC_THREADS */\r
+}\r
+\r
+void silc_mutex_free(SilcMutex mutex)\r
+{\r
+#ifdef SILC_THREADS\r
+  if (mutex) {\r
+    mutex->mutex->Close();\r
+    delete mutex->mutex;\r
+    silc_free(mutex);\r
+  }\r
+#endif /* SILC_THREADS */\r
+}\r
+\r
+void silc_mutex_lock(SilcMutex mutex)\r
+{\r
+#ifdef SILC_THREADS\r
+  if (mutex) {\r
+    mutex->mutex->Wait();\r
+    mutex->locked = TRUE;\r
+  }\r
+#endif /* SILC_THREADS */\r
+}\r
+\r
+void silc_mutex_unlock(SilcMutex mutex)\r
+{\r
+#ifdef SILC_THREADS\r
+  if (mutex) {\r
+    mutex->mutex->Signal();\r
+    mutex->locked = FALSE;\r
+  }\r
+#endif /* SILC_THREADS */\r
+}\r
+\r
+void silc_mutex_assert_locked(SilcMutex mutex)\r
+{\r
+#ifdef SILC_THREADS\r
+  if (mutex)\r
+    SILC_ASSERT(mutex->locked);\r
+#endif /* SILC_THREADS */\r
+}\r
+\r
+\r
+/****************************** SILC Cond API *******************************/\r
+\r
+/* SILC Conditional Variable context */\r
+struct SilcCondStruct {\r
+#ifdef SILC_THREADS\r
+  RCondVar *cond;\r
+#else\r
+  void *tmp;\r
+#endif /* SILC_THREADS*/\r
+};\r
+\r
+SilcBool silc_cond_alloc(SilcCond *cond)\r
+{\r
+#ifdef SILC_THREADS\r
+  *cond = (SilcCond)silc_calloc(1, sizeof(**cond));\r
+  if (*cond == NULL)\r
+    return FALSE;\r
+  (*cond)->cond = new RCondVar();\r
+  if (!(*cond)->cond) {\r
+    silc_free(*cond);\r
+    return FALSE;\r
+  }\r
+  if ((*cond)->cond->CreateLocal() != KErrNone) {\r
+    delete (*cond)->cond;\r
+    silc_free(*cond);\r
+    return FALSE;\r
+  }\r
+  return TRUE;\r
+#else\r
+  return FALSE;\r
+#endif /* SILC_THREADS*/\r
+}\r
+\r
+void silc_cond_free(SilcCond cond)\r
+{\r
+#ifdef SILC_THREADS\r
+  cond->cond->Close();\r
+  delete cond->cond;\r
+  silc_free(cond);\r
+#endif /* SILC_THREADS*/\r
+}\r
+\r
+void silc_cond_signal(SilcCond cond)\r
+{\r
+#ifdef SILC_THREADS\r
+  cond->cond->Signal();\r
+#endif /* SILC_THREADS*/\r
+}\r
+\r
+void silc_cond_broadcast(SilcCond cond)\r
+{\r
+#ifdef SILC_THREADS\r
+  cond->cond->Broadcast();\r
+#endif /* SILC_THREADS*/\r
+}\r
+\r
+void silc_cond_wait(SilcCond cond, SilcMutex mutex)\r
+{\r
+#ifdef SILC_THREADS\r
+  cond->cond->Wait(*mutex->mutex);\r
+#endif /* SILC_THREADS*/\r
+}\r
+\r
+SilcBool silc_cond_timedwait(SilcCond cond, SilcMutex mutex,\r
+                            int timeout)\r
+{\r
+#ifdef SILC_THREADS\r
+  if (timeout)\r
+    return (cond->cond->TimedWait(*mutex->mutex, (TInt)timeout * 1000) ==\r
+           KErrNone);\r
+  return (cond->cond->Wait(*mutex->mutex) == KErrNone);\r
+#else\r
+  return FALSE;\r
+#endif /* SILC_THREADS*/\r
+}\r