Porting Toolkit to Symbian. It should work while some sporadic
[silc.git] / lib / silcutil / symbian / silcsymbianthread.cpp
index d4d788dc81824f279bd001b94752968c00650561..f3aa6f26a0dc29e64c7b91e90f6bea244fa90502 100644 (file)
 */
 
 #include "silc.h"
+#include <e32base.h>
 #include <e32std.h>
 
 /**************************** SILC Thread API *******************************/
 
+extern "C" {
+
 /* Thread structure for Symbian */
-typedef struct {
+struct SilcSymbianThread {
 #ifdef SILC_THREADS
   SilcThreadStart start_func;
   void *context;
@@ -31,25 +34,36 @@ typedef struct {
 #else
   void *tmp;
 #endif
-} *SilcSymbianThread;
+};
 
 /* The actual thread function */
 
 static TInt silc_thread_start(TAny *context)
 {
 #ifdef SILC_THREADS
-  SilcSymbianThread tc = (SilcSymbianThread)context;
+  SilcSymbianThread *tc = (SilcSymbianThread *)context;
   SilcThreadStart start_func = tc->start_func;
-  void *context = tc->context;
+  void *user_context = tc->context;
   SilcBool waitable = tc->waitable;
+  void *ret = NULL;
 
   silc_free(tc);
 
-  /* Call the thread function */
-  if (waitable)
-    silc_thread_exit(start_func(context));
-  else
-    start_func(context);
+  CTrapCleanup *cs = CTrapCleanup::New();
+  if (cs) {
+    CActiveScheduler *s = new CActiveScheduler;
+    if(s) {
+      CActiveScheduler::Install(s);
+
+      /* Call the thread function */
+      TRAPD(ret_val, ret = start_func(user_context));
+
+      delete s;
+    }
+    delete cs;
+  }
+
+  silc_thread_exit(ret);
 
 #endif
   return KErrNone;
@@ -58,17 +72,18 @@ static TInt silc_thread_start(TAny *context)
 /* Executed new thread */
 
 SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
-                             bool waitable)
+                             SilcBool waitable)
 {
 #ifdef SILC_THREADS
-  SilcSymbianThread tc;
+  SilcSymbianThread *tc;
   RThread *thread;
   TInt ret;
-  TBuf<32> name;
+  char tmp[24];
+  SilcUInt16 wname[24];
 
   SILC_LOG_DEBUG(("Creating new thread"));
 
-  tc = (SilcSymbianThread)silc_calloc(1, sizeof(*thread));
+  tc = (SilcSymbianThread *)silc_calloc(1, sizeof(*tc));
   if (!tc)
     return NULL;
   tc->start_func = start_func;
@@ -76,18 +91,21 @@ SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
   tc->waitable = waitable;
 
   /* Allocate thread */
-  thread = new RThread();
+  thread = new RThread;
   if (!thread) {
     silc_free(tc);
     return NULL;
   }
 
   /* Create the thread */
-  name = (TText *)silc_time_string(0);
-  ret = thread->Create(name, silc_thread_start, 8192, 4096, 1024 * 1024,
-                      (TAny *)tc);
+  silc_snprintf(tmp, sizeof(tmp), "thread-%p", tc);
+  silc_utf8_c2w((const unsigned char *)tmp, strlen(tmp), wname,
+               sizeof(wname) / sizeof(wname[0]));
+  TBuf<24> name((unsigned short *)wname);
+  name.PtrZ();
+  ret = thread->Create(name, silc_thread_start, 8192, NULL, tc);
   if (ret != KErrNone) {
-    SILC_LOG_ERROR(("Could not create new thread"));
+    SILC_LOG_ERROR(("Could not create new thread, error %d", ret));
     delete thread;
     silc_free(tc);
     return NULL;
@@ -112,7 +130,7 @@ SilcThread silc_thread_create(SilcThreadStart start_func, void *context,
 void silc_thread_exit(void *exit_value)
 {
 #ifdef SILC_THREADS
-  RThread().Kill((Tint)exit_value);
+  RThread().Kill((TInt)exit_value);
 #endif
 }
 
@@ -121,7 +139,8 @@ void silc_thread_exit(void *exit_value)
 SilcThread silc_thread_self(void)
 {
 #ifdef SILC_THREADS
-  return (SilcThread)&RThread();
+  RThread thread = RThread();
+  return (SilcThread)&thread;
 #else
   return NULL;
 #endif
@@ -142,6 +161,15 @@ SilcBool silc_thread_wait(SilcThread thread, void **exit_value)
 #endif
 }
 
+/* Yield processor */
+
+void silc_thread_yield(void)
+{
+#ifdef SILC_THREADS
+  User::After(1);
+#endif /* SILC_THREADS */
+}
+
 /***************************** SILC Mutex API *******************************/
 
 /* SILC Mutex structure */
@@ -250,7 +278,7 @@ SilcBool silc_rwlock_alloc(SilcRwLock *rwlock)
 void silc_rwlock_free(SilcRwLock rwlock)
 {
 #ifdef SILC_THREADS
-  if (mutex) {
+  if (rwlock) {
     silc_mutex_free(rwlock->mutex);
     silc_cond_free(rwlock->cond);
     silc_free(rwlock);
@@ -368,11 +396,17 @@ SilcBool silc_cond_timedwait(SilcCond cond, SilcMutex mutex,
                             int timeout)
 {
 #ifdef SILC_THREADS
-  if (timeout)
-    return (cond->cond->TimedWait(*mutex->mutex, (TInt)timeout * 1000) ==
-           KErrNone);
+  TInt ret;
+  if (timeout) {
+    ret = cond->cond->TimedWait(*mutex->mutex, (TInt)timeout * 1000);
+    if (ret != KErrNone)
+      SILC_LOG_DEBUG(("TimedWait returned %d", ret));
+    return ret != KErrTimedOut;
+  }
   return (cond->cond->Wait(*mutex->mutex) == KErrNone);
 #else
   return FALSE;
 #endif /* SILC_THREADS*/
 }
+
+} /* extern "C" */