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;
