Use thread-local storage in Err.c

Fixes CLOWNFISH-24. Untested on Windows.


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/78f6a18a
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/78f6a18a
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/78f6a18a

Branch: refs/heads/thread_safe_errors
Commit: 78f6a18a2952df7d8f733c2ed4ca508f60c1e5de
Parents: 98282c9
Author: Nick Wellnhofer <[email protected]>
Authored: Thu Dec 4 20:41:02 2014 +0100
Committer: Nick Wellnhofer <[email protected]>
Committed: Thu Dec 4 22:02:50 2014 +0100

----------------------------------------------------------------------
 runtime/c/src/Clownfish/Err.c | 96 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 94 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/78f6a18a/runtime/c/src/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/runtime/c/src/Clownfish/Err.c b/runtime/c/src/Clownfish/Err.c
index d08b16f..a6e5090 100644
--- a/runtime/c/src/Clownfish/Err.c
+++ b/runtime/c/src/Clownfish/Err.c
@@ -34,18 +34,110 @@ typedef struct {
     jmp_buf *current_env;
 } cfish_ErrGlobals;
 
-/* TODO: Thread safety */
+/**************************** No thread support ****************************/
+#ifdef CFISH_NOTHREADS
+
 static cfish_ErrGlobals err_globals;
 
+void
+Err_init_class() {
+}
+
 static cfish_ErrGlobals*
 S_get_globals() {
     return &err_globals;
 }
 
+/********************************** Windows ********************************/
+#elif defined(CHY_HAS_WINDOWS_H)
+
+#include <windows.h>
+
+static DWORD err_globals_tls_index;
+
 void
-Err_init_class(void) {
+Err_init_class() {
+    err_globals_tls_index = TlsAlloc();
+    if (err_globals_tls_index == TLS_OUT_OF_INDEXES) {
+        fprintf(stderr, "TlsAlloc failed (TLS_OUT_OF_INDEXES)\n");
+        abort();
+    }
 }
 
+static cfish_ErrGlobals*
+S_get_globals() {
+    cfish_ErrGlobals *globals
+        = (cfish_ErrGlobals*)TlsGetValue(err_globals_tls_index);
+
+    if (!globals) {
+        globals = (cfish_ErrGlobals*)MALLOCATE(sizeof(cfish_ErrGlobals));
+        if (!TlsSetValue(err_globals_tls_index, globals)) {
+            fprintf(stderr, "TlsSetValue failed: %d\n", GetLastError());
+            abort();
+        }
+    }
+
+    return globals;
+}
+
+BOOL WINAPI
+DllMain(HINSTANCE dll, DWORD reason, LPVOID reserved) {
+    if (reason == DLL_THREAD_DETACH) {
+        void *globals = TlsGetValue(err_globals_tls_index);
+        FREEMEM(globals);
+    }
+
+    return TRUE;
+}
+
+/******************************** pthreads *********************************/
+#elif defined(CHY_HAS_PTHREAD_H)
+
+#include <pthread.h>
+
+static pthread_key_t err_globals_key;
+
+static void
+S_destroy_globals(void *globals);
+
+void
+Err_init_class() {
+    int error = pthread_key_create(&err_globals_key, S_destroy_globals);
+    if (error) {
+        fprintf(stderr, "pthread_key_create failed: %d\n", error);
+        abort();
+    }
+}
+
+static cfish_ErrGlobals*
+S_get_globals() {
+    cfish_ErrGlobals *globals
+        = (cfish_ErrGlobals*)pthread_getspecific(err_globals_key);
+
+    if (!globals) {
+        globals = (cfish_ErrGlobals*)MALLOCATE(sizeof(cfish_ErrGlobals));
+        int error = pthread_setspecific(err_globals_key, globals);
+        if (error) {
+            fprintf(stderr, "pthread_setspecific failed: %d\n", error);
+            abort();
+        }
+    }
+
+    return globals;
+}
+
+static void
+S_destroy_globals(void *globals) {
+    FREEMEM(globals);
+}
+
+/****************** No support for thread-local storage ********************/
+#else
+
+#error "No support for thread-local storage."
+
+#endif
+
 Err*
 Err_get_error() {
     return S_get_globals()->current_error;

Reply via email to