// D programming language runtime library // Public Domain // written by Walter Bright, Digital Mars // www.digitalmars.com // This is written in C because nobody has written a pthreads interface // to D yet. #include #include #include #if _WIN32 #elif linux || __APPLE__ || (defined (__SVR4) && defined (__sun)) #define USE_PTHREADS 1 #else #endif #if _WIN32 #include #endif #if USE_PTHREADS #include #endif #include "mars.h" // This is what the monitor reference in Object points to typedef struct Monitor { void* impl; // for user-level monitors Array devt; // for internal monitors #if _WIN32 CRITICAL_SECTION mon; #endif #if USE_PTHREADS pthread_mutex_t mon; #endif } Monitor; #define MONPTR(h) (&((Monitor *)(h)->monitor)->mon) static volatile int inited; /* =============================== Win32 ============================ */ #if _WIN32 static CRITICAL_SECTION _monitor_critsec; void _STI_monitor_staticctor() { if (!inited) { InitializeCriticalSection(&_monitor_critsec); inited = 1; } } void _STD_monitor_staticdtor() { if (inited) { inited = 0; DeleteCriticalSection(&_monitor_critsec); } } void _d_monitor_create(Object *h) { /* * NOTE: Assume this is only called when h->monitor is null prior to the * call. However, please note that another thread may call this function * at the same time, so we can not assert this here. Instead, try and * create a lock, and if one already exists then forget about it. */ //printf("+_d_monitor_create(%p)\n", h); assert(h); Monitor *cs = NULL; EnterCriticalSection(&_monitor_critsec); if (!h->monitor) { cs = (Monitor *)calloc(sizeof(Monitor), 1); assert(cs); InitializeCriticalSection(&cs->mon); h->monitor = (void *)cs; cs = NULL; } LeaveCriticalSection(&_monitor_critsec); if (cs) free(cs); //printf("-_d_monitor_create(%p)\n", h); } void _d_monitor_destroy(Object *h) { //printf("+_d_monitor_destroy(%p)\n", h); assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); DeleteCriticalSection(MONPTR(h)); free((void *)h->monitor); h->monitor = NULL; //printf("-_d_monitor_destroy(%p)\n", h); } int _d_monitor_lock(Object *h) { //printf("+_d_monitor_acquire(%p)\n", h); assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); EnterCriticalSection(MONPTR(h)); //printf("-_d_monitor_acquire(%p)\n", h); } void _d_monitor_unlock(Object *h) { //printf("+_d_monitor_release(%p)\n", h); assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); LeaveCriticalSection(MONPTR(h)); //printf("-_d_monitor_release(%p)\n", h); } #endif /* =============================== linux ============================ */ #if USE_PTHREADS #if !linux #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE #endif // Includes attribute fixes from David Friedman's GDC port static pthread_mutex_t _monitor_critsec; static pthread_mutexattr_t _monitors_attr; void _STI_monitor_staticctor() { if (!inited) { pthread_mutexattr_init(&_monitors_attr); pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE_NP); pthread_mutex_init(&_monitor_critsec, 0); inited = 1; } } void _STD_monitor_staticdtor() { if (inited) { inited = 0; pthread_mutex_destroy(&_monitor_critsec); pthread_mutexattr_destroy(&_monitors_attr); } } void _d_monitor_create(Object *h) { /* * NOTE: Assume this is only called when h->monitor is null prior to the * call. However, please note that another thread may call this function * at the same time, so we can not assert this here. Instead, try and * create a lock, and if one already exists then forget about it. */ //printf("+_d_monitor_create(%p)\n", h); assert(h); Monitor *cs = NULL; pthread_mutex_lock(&_monitor_critsec); if (!h->monitor) { cs = (Monitor *)calloc(sizeof(Monitor), 1); assert(cs); pthread_mutex_init(&cs->mon, & _monitors_attr); h->monitor = (void *)cs; cs = NULL; } pthread_mutex_unlock(&_monitor_critsec); if (cs) free(cs); //printf("-_d_monitor_create(%p)\n", h); } void _d_monitor_destroy(Object *h) { //printf("+_d_monitor_destroy(%p)\n", h); assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); pthread_mutex_destroy(MONPTR(h)); free((void *)h->monitor); h->monitor = NULL; //printf("-_d_monitor_destroy(%p)\n", h); } int _d_monitor_lock(Object *h) { //printf("+_d_monitor_acquire(%p)\n", h); assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); pthread_mutex_lock(MONPTR(h)); //printf("-_d_monitor_acquire(%p)\n", h); } void _d_monitor_unlock(Object *h) { //printf("+_d_monitor_release(%p)\n", h); assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); pthread_mutex_unlock(MONPTR(h)); //printf("-_d_monitor_release(%p)\n", h); } #endif