/src/rt/monitor_.d

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