Index: src/runtime/threading.m ================================================================== --- src/runtime/threading.m +++ src/runtime/threading.m @@ -22,26 +22,23 @@ #import "runtime.h" #import "runtime-private.h" #import "threading.h" static of_rmutex_t global_mutex; -static bool global_mutex_init = false; +static of_once_t once_control = OF_ONCE_INIT; static void -objc_global_mutex_new(void) +init(void) { if (!of_rmutex_new(&global_mutex)) OBJC_ERROR("Failed to create global mutex!"); - - global_mutex_init = true; } void objc_global_mutex_lock(void) { - if (!global_mutex_init) - objc_global_mutex_new(); + of_once(&once_control, init); if (!of_rmutex_lock(&global_mutex)) OBJC_ERROR("Failed to lock global mutex!"); } Index: src/socket.m ================================================================== --- src/socket.m +++ src/socket.m @@ -15,27 +15,40 @@ */ #include "config.h" #import "socket.h" +#ifdef OF_HAVE_THREADS +# include "threading.h" +static of_once_t onceControl = OF_ONCE_INIT; +#endif static bool initialized = false; + +static void +init(void) +{ +#if defined(_WIN32) + WSADATA wsa; + + if (WSAStartup(MAKEWORD(2, 0), &wsa)) + return; +#elif defined(__wii__) + if (net_init() < 0) + return; +#endif + + initialized = true; +} bool of_init_sockets() { - if (initialized) - return true; - -#ifdef _WIN32 - WSADATA wsa; - - if (WSAStartup(MAKEWORD(2, 0), &wsa)) - return false; -#elif defined(__wii__) - if (net_init() < 0) - return false; +#ifdef OF_HAVE_THREADS + of_once(&onceControl, init); +#else + if (!initialized) + init(); #endif - initialized = true; - return true; + return initialized; } Index: src/threading.h ================================================================== --- src/threading.h +++ src/threading.h @@ -31,10 +31,12 @@ # include typedef pthread_t of_thread_t; typedef pthread_key_t of_tlskey_t; typedef pthread_mutex_t of_mutex_t; typedef pthread_cond_t of_condition_t; +typedef pthread_once_t of_once_t; +# define OF_ONCE_INIT PTHREAD_ONCE_INIT #elif defined(_WIN32) /* * winsock2.h needs to be included before windows.h. Not including it here * would make it impossible to use sockets after threading.h has been * imported. @@ -48,10 +50,12 @@ typedef CRITICAL_SECTION of_mutex_t; typedef struct { HANDLE event; int count; } of_condition_t; +typedef volatile LONG of_once_t; +# define OF_ONCE_INIT 0 #else # error No threads available! #endif #if defined(OF_HAVE_ATOMIC_OPS) @@ -148,10 +152,31 @@ ExitThread(0); #else # error of_thread_exit not implemented! #endif } + +static OF_INLINE void +of_once(of_once_t *control, void (*func)(void)) +{ +#if defined(OF_HAVE_PTHREADS) + pthread_once(control, func); +#elif defined(_WIN32) + switch (InterlockedCompareExchange(control, 1, 0)) { + case 0: + func(); + InterlockedIncrement(control); + break; + case 1: + while (*control == 1) + Sleep(0); + break; + } +#else +# error of_once not implemented! +#endif +} static OF_INLINE bool of_mutex_new(of_mutex_t *mutex) { #if defined(OF_HAVE_PTHREADS)