Use thread-local storage in Err.c Fixes CLOWNFISH-24.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/cd4f31b5 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/cd4f31b5 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/cd4f31b5 Branch: refs/heads/master Commit: cd4f31b5238462064185a422b79a6aa620d4a96b Parents: 924605b Author: Nick Wellnhofer <[email protected]> Authored: Thu Dec 4 20:41:02 2014 +0100 Committer: Nick Wellnhofer <[email protected]> Committed: Sat Dec 27 16:09:58 2014 +0100 ---------------------------------------------------------------------- runtime/c/src/Clownfish/Err.c | 103 ++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cd4f31b5/runtime/c/src/Clownfish/Err.c ---------------------------------------------------------------------- diff --git a/runtime/c/src/Clownfish/Err.c b/runtime/c/src/Clownfish/Err.c index d08b16f..ec588db 100644 --- a/runtime/c/src/Clownfish/Err.c +++ b/runtime/c/src/Clownfish/Err.c @@ -34,18 +34,117 @@ 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() { + 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*)CALLOCATE(1, 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) { + cfish_ErrGlobals *globals + = (cfish_ErrGlobals*)TlsGetValue(err_globals_tls_index); + + if (globals) { + DECREF(globals->current_error); + 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(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*)CALLOCATE(1, 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 *arg) { + cfish_ErrGlobals *globals = (cfish_ErrGlobals*)arg; + DECREF(globals->current_error); + 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;
