/src/rt/monitor_.d
D | 255 lines | 195 code | 31 blank | 29 comment | 24 complexity | c3164e30f2af3b51cd4e25238f7f6968 MD5 | raw file
1/** 2 * Contains the implementation for object monitors. 3 * 4 * Copyright: Copyright Digital Mars 2000 - 2011. 5 * License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 6 * Authors: Walter Bright, Sean Kelly 7 */ 8 9/* Copyright Digital Mars 2000 - 2011. 10 * Distributed under the Boost Software License, Version 1.0. 11 * (See accompanying file LICENSE or copy at 12 * http://www.boost.org/LICENSE_1_0.txt) 13 */ 14module rt.monitor_; 15 16//debug=PRINTF; 17 18private 19{ 20 debug(PRINTF) import core.stdc.stdio; 21 import core.stdc.stdlib; 22 23 version( linux ) 24 { 25 version = USE_PTHREADS; 26 } 27 else version( FreeBSD ) 28 { 29 version = USE_PTHREADS; 30 } 31 else version( OSX ) 32 { 33 version = USE_PTHREADS; 34 } 35 else version( Solaris ) 36 { 37 version = USE_PTHREADS; 38 } 39 40 // This is what the monitor reference in Object points to 41 alias Object.Monitor IMonitor; 42 alias void delegate(Object) DEvent; 43 44 version( Windows ) 45 { 46 version (DigitalMars) version (Win32) 47 pragma(lib, "snn.lib"); 48 import core.sys.windows.windows; 49 50 struct Monitor 51 { 52 IMonitor impl; // for user-level monitors 53 DEvent[] devt; // for internal monitors 54 size_t refs; // reference count 55 CRITICAL_SECTION mon; 56 } 57 } 58 else version( USE_PTHREADS ) 59 { 60 import core.sys.posix.pthread; 61 62 struct Monitor 63 { 64 IMonitor impl; // for user-level monitors 65 DEvent[] devt; // for internal monitors 66 size_t refs; // reference count 67 pthread_mutex_t mon; 68 } 69 } 70 else 71 { 72 static assert(0, "Unsupported platform"); 73 } 74 75 Monitor* getMonitor(Object h) 76 { 77 return cast(Monitor*) h.__monitor; 78 } 79 80 void setMonitor(Object h, Monitor* m) 81 { 82 h.__monitor = m; 83 } 84 85 static __gshared int inited; 86} 87 88 89/* =============================== Win32 ============================ */ 90 91version( Windows ) version( LDC ) 92{ 93 static __gshared CRITICAL_SECTION _monitor_critsec; 94 95 extern (C) void _STI_monitor_staticctor() 96 { 97 debug(PRINTF) printf("+_STI_monitor_staticctor()\n"); 98 if (!inited) 99 { 100 InitializeCriticalSection(&_monitor_critsec); 101 inited = 1; 102 } 103 debug(PRINTF) printf("-_STI_monitor_staticctor()\n"); 104 } 105 106 extern (C) void _STD_monitor_staticdtor() 107 { 108 debug(PRINTF) printf("+_STI_monitor_staticdtor() - d\n"); 109 if (inited) 110 { 111 inited = 0; 112 DeleteCriticalSection(&_monitor_critsec); 113 } 114 debug(PRINTF) printf("-_STI_monitor_staticdtor() - d\n"); 115 } 116 117 extern (C) void _d_monitor_create(Object h) 118 { 119 /* 120 * NOTE: Assume this is only called when h.__monitor is null prior to the 121 * call. However, please note that another thread may call this function 122 * at the same time, so we can not assert this here. Instead, try and 123 * create a lock, and if one already exists then forget about it. 124 */ 125 126 debug(PRINTF) printf("+_d_monitor_create(%p)\n", h); 127 assert(h); 128 Monitor *cs; 129 EnterCriticalSection(&_monitor_critsec); 130 if (!h.__monitor) 131 { 132 cs = cast(Monitor *)calloc(Monitor.sizeof, 1); 133 assert(cs); 134 InitializeCriticalSection(&cs.mon); 135 setMonitor(h, cs); 136 cs.refs = 1; 137 cs = null; 138 } 139 LeaveCriticalSection(&_monitor_critsec); 140 if (cs) 141 free(cs); 142 debug(PRINTF) printf("-_d_monitor_create(%p)\n", h); 143 } 144 145 extern (C) void _d_monitor_destroy(Object h) 146 { 147 debug(PRINTF) printf("+_d_monitor_destroy(%p)\n", h); 148 assert(h && h.__monitor && !getMonitor(h).impl); 149 DeleteCriticalSection(&getMonitor(h).mon); 150 free(h.__monitor); 151 setMonitor(h, null); 152 debug(PRINTF) printf("-_d_monitor_destroy(%p)\n", h); 153 } 154 155 extern (C) void _d_monitor_lock(Object h) 156 { 157 debug(PRINTF) printf("+_d_monitor_acquire(%p)\n", h); 158 assert(h && h.__monitor && !getMonitor(h).impl); 159 EnterCriticalSection(&getMonitor(h).mon); 160 debug(PRINTF) printf("-_d_monitor_acquire(%p)\n", h); 161 } 162 163 extern (C) void _d_monitor_unlock(Object h) 164 { 165 debug(PRINTF) printf("+_d_monitor_release(%p)\n", h); 166 assert(h && h.__monitor && !getMonitor(h).impl); 167 LeaveCriticalSection(&getMonitor(h).mon); 168 debug(PRINTF) printf("-_d_monitor_release(%p)\n", h); 169 } 170} 171 172/* =============================== linux ============================ */ 173 174version( USE_PTHREADS ) 175{ 176 // Includes attribute fixes from David Friedman's GDC port 177 static __gshared pthread_mutex_t _monitor_critsec; 178 static __gshared pthread_mutexattr_t _monitors_attr; 179 180 extern (C) void _STI_monitor_staticctor() 181 { 182 if (!inited) 183 { 184 pthread_mutexattr_init(&_monitors_attr); 185 pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE); 186 pthread_mutex_init(&_monitor_critsec, &_monitors_attr); 187 inited = 1; 188 } 189 } 190 191 extern (C) void _STD_monitor_staticdtor() 192 { 193 if (inited) 194 { 195 inited = 0; 196 pthread_mutex_destroy(&_monitor_critsec); 197 pthread_mutexattr_destroy(&_monitors_attr); 198 } 199 } 200 201 extern (C) void _d_monitor_create(Object h) 202 { 203 /* 204 * NOTE: Assume this is only called when h.__monitor is null prior to the 205 * call. However, please note that another thread may call this function 206 * at the same time, so we can not assert this here. Instead, try and 207 * create a lock, and if one already exists then forget about it. 208 */ 209 210 debug(PRINTF) printf("+_d_monitor_create(%p)\n", h); 211 assert(h); 212 Monitor *cs; 213 pthread_mutex_lock(&_monitor_critsec); 214 if (!h.__monitor) 215 { 216 cs = cast(Monitor *)calloc(Monitor.sizeof, 1); 217 assert(cs); 218 pthread_mutex_init(&cs.mon, &_monitors_attr); 219 setMonitor(h, cs); 220 cs.refs = 1; 221 cs = null; 222 } 223 pthread_mutex_unlock(&_monitor_critsec); 224 if (cs) 225 free(cs); 226 debug(PRINTF) printf("-_d_monitor_create(%p)\n", h); 227 } 228 229 extern (C) void _d_monitor_destroy(Object h) 230 { 231 debug(PRINTF) printf("+_d_monitor_destroy(%p)\n", h); 232 assert(h && h.__monitor && !getMonitor(h).impl); 233 pthread_mutex_destroy(&getMonitor(h).mon); 234 free(h.__monitor); 235 setMonitor(h, null); 236 debug(PRINTF) printf("-_d_monitor_destroy(%p)\n", h); 237 } 238 239 extern (C) void _d_monitor_lock(Object h) 240 { 241 debug(PRINTF) printf("+_d_monitor_acquire(%p)\n", h); 242 assert(h && h.__monitor && !getMonitor(h).impl); 243 pthread_mutex_lock(&getMonitor(h).mon); 244 debug(PRINTF) printf("-_d_monitor_acquire(%p)\n", h); 245 } 246 247 extern (C) void _d_monitor_unlock(Object h) 248 { 249 debug(PRINTF) printf("+_d_monitor_release(%p)\n", h); 250 assert(h && h.__monitor && !getMonitor(h).impl); 251 pthread_mutex_unlock(&getMonitor(h).mon); 252 debug(PRINTF) printf("-_d_monitor_release(%p)\n", h); 253 } 254} 255