PageRenderTime 52ms CodeModel.GetById 33ms app.highlight 16ms RepoModel.GetById 1ms app.codeStats 1ms

/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
  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