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 /** 10 * D implementation written and ported to tango by Iain Buclaw. 11 */ 12 13 module rt.compiler.gdc.monitor_; 14 15 //debug=PRINTF; 16 17 private 18 { 19 debug(PRINTF) import tango.stdc.stdio; 20 import tango.stdc.stdlib; 21 22 version( linux ) 23 { 24 version = USE_PTHREADS; 25 } 26 else version( FreeBSD ) 27 { 28 version = USE_PTHREADS; 29 } 30 else version( OSX ) 31 { 32 version = USE_PTHREADS; 33 } 34 else version( Solaris ) 35 { 36 version = USE_PTHREADS; 37 } 38 39 // This is what the monitor reference in Object points to 40 alias Object.Monitor IMonitor; 41 alias void delegate(Object) DEvent; 42 43 version( Windows ) 44 { 45 import tango.sys.win32.UserGdi; 46 47 struct Monitor 48 { 49 IMonitor impl; // for user-level monitors 50 DEvent[] devt; // for internal monitors 51 CRITICAL_SECTION mon; 52 } 53 } 54 else version( USE_PTHREADS ) 55 { 56 import tango.stdc.posix.pthread; 57 58 struct Monitor 59 { 60 IMonitor impl; // for user-level monitors 61 DEvent[] devt; // for internal monitors 62 pthread_mutex_t mon; 63 } 64 } 65 else 66 { 67 version = NoSystem; 68 69 struct Monitor 70 { 71 IMonitor impl; // for user-level monitors 72 DEvent[] devt; // for internal monitors 73 } 74 } 75 76 Monitor* getMonitor(Object h) 77 { 78 return cast(Monitor*) h.__monitor; 79 } 80 81 void setMonitor(Object h, Monitor* m) 82 { 83 h.__monitor = m; 84 } 85 86 static int inited; 87 } 88 89 90 /* =============================== Win32 ============================ */ 91 92 version( Windows ) 93 { 94 static CRITICAL_SECTION _monitor_critsec; 95 96 extern (C) void _STI_monitor_staticctor() 97 { 98 debug(PRINTF) printf("+_STI_monitor_staticctor()\n"); 99 if (!inited) 100 { 101 InitializeCriticalSection(&_monitor_critsec); 102 inited = 1; 103 } 104 debug(PRINTF) printf("-_STI_monitor_staticctor()\n"); 105 } 106 107 extern (C) void _STD_monitor_staticdtor() 108 { 109 debug(PRINTF) printf("+_STI_monitor_staticdtor() - d\n"); 110 if (inited) 111 { 112 inited = 0; 113 DeleteCriticalSection(&_monitor_critsec); 114 } 115 debug(PRINTF) printf("-_STI_monitor_staticdtor() - d\n"); 116 } 117 118 extern (C) void _d_monitor_create(Object h) 119 { 120 /* 121 * NOTE: Assume this is only called when h.__monitor is null prior to the 122 * call. However, please note that another thread may call this function 123 * at the same time, so we can not assert this here. Instead, try and 124 * create a lock, and if one already exists then forget about it. 125 */ 126 127 debug(PRINTF) printf("+_d_monitor_create(%p)\n", h); 128 assert(h); 129 Monitor *cs; 130 EnterCriticalSection(&_monitor_critsec); 131 if (!h.__monitor) 132 { 133 cs = cast(Monitor *)calloc(Monitor.sizeof, 1); 134 assert(cs); 135 InitializeCriticalSection(&cs.mon); 136 setMonitor(h, cs); 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 174 version( USE_PTHREADS ) 175 { 176 // Includes attribute fixes from David Friedman's GDC port 177 static pthread_mutex_t _monitor_critsec; 178 static 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 = null; 221 } 222 pthread_mutex_unlock(&_monitor_critsec); 223 if (cs) 224 free(cs); 225 debug(PRINTF) printf("-_d_monitor_create(%p)\n", h); 226 } 227 228 extern (C) void _d_monitor_destroy(Object h) 229 { 230 debug(PRINTF) printf("+_d_monitor_destroy(%p)\n", h); 231 assert(h && h.__monitor && !getMonitor(h).impl); 232 pthread_mutex_destroy(&getMonitor(h).mon); 233 free(h.__monitor); 234 setMonitor(h, null); 235 debug(PRINTF) printf("-_d_monitor_destroy(%p)\n", h); 236 } 237 238 extern (C) void _d_monitor_lock(Object h) 239 { 240 debug(PRINTF) printf("+_d_monitor_acquire(%p)\n", h); 241 assert(h && h.__monitor && !getMonitor(h).impl); 242 pthread_mutex_lock(&getMonitor(h).mon); 243 debug(PRINTF) printf("-_d_monitor_acquire(%p)\n", h); 244 } 245 246 extern (C) void _d_monitor_unlock(Object h) 247 { 248 debug(PRINTF) printf("+_d_monitor_release(%p)\n", h); 249 assert(h && h.__monitor && !getMonitor(h).impl); 250 pthread_mutex_unlock(&getMonitor(h).mon); 251 debug(PRINTF) printf("-_d_monitor_release(%p)\n", h); 252 } 253 } 254 255 /* ================================= No System ============================ */ 256 257 version( NoSystem ) 258 { 259 void _STI_monitor_staticctor() { } 260 void _STD_monitor_staticdtor() { } 261 262 void _d_monitor_create(Object h) 263 { 264 debug(PRINTF) printf("+_d_monitor_create(%p)\n", h); 265 assert(h); 266 Monitor *cs; 267 if (!h.__monitor) 268 { 269 cs = cast(Monitor *)calloc(Monitor.sizeof, 1); 270 assert(cs); 271 setMonitor(h, cs); 272 cs = null; 273 } 274 if (cs) 275 free(cs); 276 debug(PRINTF) printf("-_d_monitor_create(%p)\n", h); 277 } 278 279 void _d_monitor_destroy(Object h) 280 { 281 debug(PRINTF) printf("+_d_monitor_destroy(%p)\n", h); 282 assert(h && h.__monitor && !getMonitor(h).impl); 283 free(h.__monitor); 284 setMonitor(h, null); 285 debug(PRINTF) printf("-_d_monitor_destroy(%p)\n", h); 286 } 287 288 void _d_monitor_lock(Object h) 289 { 290 debug(PRINTF) printf("+_d_monitor_acquire(%p)\n", h); 291 assert(h && h.__monitor && !getMonitor(h).impl); 292 debug(PRINTF) printf("-_d_monitor_acquire(%p)\n", h); 293 } 294 295 void _d_monitor_unlock(Object h) 296 { 297 debug(PRINTF) printf("+_d_monitor_release(%p)\n", h); 298 assert(h && h.__monitor && !getMonitor(h).impl); 299 debug(PRINTF) printf("-_d_monitor_release(%p)\n", h); 300 } 301 } 302 303