Changeset 779

Show
Ignore:
Timestamp:
07/03/08 17:35:36 (3 months ago)
Author:
Bartosz
Message:

Rewrote internal/monitor.c in D

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/internal/monitor.d

    r775 r779  
    44/** 
    55Part of the D programming language runtime library. 
    6 Implements _Object monitors used by $(D synchronized) methods and blocks 
     6Implements Object monitors used by $(D synchronized) methods and blocks 
    77 
    88Author: Bartosz Milewski, Walter Bright 
     
    1111*/ 
    1212 
    13 module monitor; 
    14  
    15 import std.c.stdlib : malloc, free; 
    16 import std.c.string : memcpy; 
    17  
    18 // Don't publicize it: it wonn't work with signals and slots (see std.signals) 
     13module internal.monitor; 
     14 
     15extern (C) 
     16{   /// C's printf function. 
     17    int printf(const char *, ...); 
     18 
     19    void* memcpy(void *, in void *, size_t); 
     20    void* malloc(size_t); 
     21    void free(void*); 
     22
     23 
     24/+ 
     25// Don't publicize it: malloc won't work with signals and slots (see std.signals) 
    1926T construct(T:Object, A...)(A args) 
    2027{ 
    2128    ClassInfo info = T.classinfo; 
    2229    void * p = malloc(info.init.length); 
     30    if (!p) 
     31        _d_OutOfMemory(); 
    2332    memcpy(p, info.init.ptr, info.init.length); 
    2433    T obj = cast(T)p; 
    25     static if (is(typeof(obj._ctor) == function)) 
     34    static if (is(typeof(obj._ctor))) 
    2635        obj._ctor(args); 
    2736    return obj; 
     
    3039void destroy(T:Object)(T obj) 
    3140{ 
    32     static if (is(typeof(obj._dtor) == function)) 
     41    static if (is(typeof(obj._dtor))) 
    3342        obj._dtor(); 
    3443    free(cast(void*) obj); 
    3544} 
    36  
    37 /* This is what _Object will look like: */ 
    38 class _Object 
    39 
    40 public: 
    41     FatLock _fatLock; 
    42 
    43  
    44 // Global mutex used when lazily initializing _Object._fatLock 
    45 OsMutex _monitor_critsect; 
    46  
    47 class FatLock 
    48 
    49     void delegate(_Object) [] delegates; 
    50     OsMutex mon; 
     45+/ 
     46 
     47/** construct a struct using malloc  
     48Because struct destructors don't work yet, I use artificial setup/teardown 
     49*/ 
     50T * conStruct(T, A...)(A args) 
     51
     52    static assert(is(T == struct)); 
     53    T * p =cast(T*) malloc(T.sizeof); 
     54    *p = T.init; 
     55    static if (is(typeof(T.setup) == function)) 
     56        p.setup(args); 
     57    return p; 
     58
     59 
     60/** Destruct a struct allocated using malloc */ 
     61void deStruct(T)(T * p) 
     62
     63    static if (is(typeof(p.teardown) == function)) 
     64        p.teardown(); 
     65    free(p); 
     66
     67 
     68// Global mutex used when lazily initializing Object._fatLock 
     69OsMutex * __monitor_mutex; 
     70 
     71/** The layout of every object header */ 
     72struct ObjectLayout 
     73
     74private: 
     75    void * _vtable; 
     76    FatLock * _fatLock; 
     77
     78 
     79/** For eny object return the layout of its header */ 
     80ObjectLayout * ToLayout(Object o) 
     81
     82    return cast(ObjectLayout *) cast(void *) o; 
     83
     84 
     85/** Access to the object's _fatLock */ 
     86FatLock * GetFatLock(Object o)  
     87
     88    return ToLayout(o)._fatLock; 
     89
     90 
     91final void SetFatLock(Object o, FatLock * other) 
     92
     93    ToLayout(o)._fatLock = other; 
     94
     95 
     96/** Contains the object monitor and the array of delegates 
     97that are used by signals and slots */ 
     98struct FatLock 
     99
     100    public  void delegate(Object) [] delegates; 
     101    private OsMutex * mon; 
     102    void setup() { mon = conStruct!(OsMutex)(); } 
     103    void teardown() { deStruct(mon); } 
    51104public: 
    52105    void lock() { mon.lock; } 
     
    54107} 
    55108 
    56 // Called only once by a single thread during startup 
     109/** Called only once by a single thread during startup */ 
    57110extern(C) void _STI_monitor_staticctor() 
    58111{ 
    59     _monitor_critsect = construct!(OsMutex)(); 
    60 
    61  
     112    __monitor_mutex = conStruct!(OsMutex)(); 
     113
     114 
     115/** Called only once by a single thread during teardown */ 
    62116extern(C) void _STD_monitor_staticdtor() 
    63117{ 
    64     destroy(_monitor_critsect); 
    65 
    66  
    67 extern(C) void _d_notify_release(_Object); 
    68  
    69 // Called when entering synchronized block 
     118    deStruct(__monitor_mutex); 
     119
     120 
     121// De-register observers from signalers 
     122extern(C) void _d_notify_release(Object); 
     123 
     124/** Called by runtime when entering a synchronized block */ 
    70125extern(C)  
    71 void _d_monitorenter(_Object obj) 
    72 { 
    73     //printf("_d_monitorenter(%p), %p\n", obj, obj->monitor); 
     126void _d_monitorenter(Object obj) 
     127{ 
     128    //printf("_d_monitorenter(%p), %p\n", obj, obj.__monitor); 
    74129    // Warning: data race 
    75     if (obj._fatLock is null) 
    76     { 
    77     scope lock = new OsLock (_monitor_critsect)
    78         if (obj._fatLock is null) // if, in the meantime, another thread didn't set it 
     130    if (GetFatLock(obj) is null) 
     131    { 
     132    __monitor_mutex.lock
     133        if (GetFatLock(obj) is null) // if, in the meantime, another thread didn't set it 
    79134        { 
    80         obj._fatLock = new FatLock
     135        SetFatLock(obj, conStruct!(FatLock))
    81136        } 
    82     } 
    83     obj._fatLock.lock; 
    84 
    85  
     137    __monitor_mutex.unlock; 
     138    } 
     139    GetFatLock(obj).lock; 
     140
     141 
     142/** Called by runtime when exiting a synchronized block */ 
    86143extern(C)  
    87 void _d_monitorexit(_Object obj) 
    88 
    89     assert(obj._fatLock !is null); 
    90     obj._fatLock.unlock; 
    91 
    92  
    93 /*************************************** 
    94  * Called by garbage collector when _Object is free'd. 
     144void _d_monitorexit(Object obj) 
     145
     146    //printf("monitor exit (%p), %p\n", obj, obj.__monitor); 
     147    assert(GetFatLock(obj)); 
     148    GetFatLock(obj).unlock; 
     149
     150 
     151/** 
     152 * Called by garbage collector when Object is free'd. 
    95153 */ 
    96154 
    97155extern(C)  
    98 void _d_monitorrelease(_Object obj) 
    99 
    100     if (obj._fatLock !is null) 
     156void _d_monitorrelease(Object obj) 
     157
     158    //printf("monitor release (%p), %p\n", obj, obj.__monitor); 
     159    if (GetFatLock(obj)) 
    101160    { 
    102161    _d_notify_release(obj); 
    103162 
    104         delete obj._fatLock; 
    105         obj._fatLock = null; 
    106     } 
    107 
    108  
    109 /** 
    110 Scoped locking of OsMutex 
    111 */ 
    112 scope class OsLock 
    113 
    114 public: 
    115     this (OsMutex mtx) 
    116     { 
    117         _mtx = mtx; 
    118         _mtx.lock (); 
    119     } 
    120     ~this () 
    121     { 
    122         _mtx.unlock (); 
    123     } 
    124 private: 
    125     OsMutex _mtx; 
     163        deStruct(GetFatLock(obj)); 
     164        SetFatLock(obj, null); 
     165    } 
    126166} 
    127167 
     
    142182 
    143183*/ 
    144 class OsMutex 
     184// replace setup/teardown with constructor/destructor for structs 
     185struct OsMutex 
    145186{ 
    146187public: 
    147     this() 
     188    void setup() 
    148189    { 
    149190        InitializeCriticalSection (&_critSection); 
    150191    } 
    151     ~this() 
     192    void teardown() 
    152193    { 
    153194        DeleteCriticalSection (&_critSection); 
    154195    } 
    155     final void lock()  
     196    void lock()  
    156197    { 
    157198        EnterCriticalSection (&_critSection); 
    158199    } 
    159     final void unlock()  
     200    void unlock()  
    160201    {  
    161202        LeaveCriticalSection (&_critSection); 
     
    177218} 
    178219 
    179 class OsMutex 
     220// replace setup/teardown with constructor/destructor for structs 
     221struct OsMutex 
    180222{ 
    181223public: 
    182     this() 
     224    void setup() 
    183225    { 
    184226        pthread_mutex_init(&_mtx, _monitors_attr); 
    185227    } 
    186     ~this() 
     228    void teardown() 
    187229    { 
    188230        pthread_mutex_destroy(&_mtx); 
    189231    } 
    190     final void lock() 
     232    void lock() 
    191233    { 
    192234        pthread_mutex_lock(&_mtx); 
    193235    } 
    194     final void unlock() 
     236    void unlock() 
    195237    { 
    196238        pthread_mutex_unlock(&_mtx); 
  • trunk/phobos/internal/object.d

    r772 r779  
    44 * Forms the symbols available to all D programs. Includes 
    55 * Object, which is the root of the class object hierarchy. 
     6 * 
     7 * Authors: Walter Bright, Bartosz Milewski 
    68 * 
    79 * This module is implicitly imported. 
     
    3739 
    3840import std.outofmemory; 
     41import internal.monitor; 
    3942 
    4043/** 
     
    7780alias invariant(dchar)[] dstring; 
    7881 
    79 /* ************************* 
    80  * Internal struct pointed to by the hidden .monitor member. 
    81  */ 
    82 struct Monitor 
    83 { 
    84     void delegate(Object)[] delegates; 
    85  
    86     /* More stuff goes here defined by internal/monitor.c */ 
    87 } 
    88  
    8982/****************** 
    9083 * All D class objects inherit from Object. 
     
    9285class Object 
    9386{ 
    94     final Monitor * getMonitorPtr() 
    95     { 
    96         Monitor * mon = cast(Monitor*)(cast(void**)this)[1]; 
    97         return mon; 
    98     } 
    99  
    10087    void print() 
    10188    { 
     
    162149            // Important: Monitor is guaranteed to be initialized 
    163150            // as the side-effect of the synchronized clause above 
    164             Monitor * m = getMonitorPtr(); 
    165             assert(m != null); 
    166             foreach (inout x; m.delegates) 
     151            FatLock * fatLock = GetFatLock(this); 
     152            assert(fatLock); 
     153            foreach (inout x; fatLock.delegates) 
    167154            { 
    168155                if (!x || x == dg) 
     
    173160 
    174161            // Increase size of delegates[] 
    175             auto len = m.delegates.length; 
     162            auto len = fatLock.delegates.length; 
    176163            auto startlen = len; 
    177164            if (len == 0) 
     
    181168                if (!p) 
    182169                    _d_OutOfMemory(); 
    183                 m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; 
     170                fatLock.delegates = (cast(void delegate(Object)*)p)[0 .. len]; 
    184171            } 
    185172            else 
    186173            { 
    187174                len += len + 4; 
    188                 auto p = realloc(m.delegates.ptr, (void delegate(Object)).sizeof * len); 
     175                auto p = realloc(fatLock.delegates.ptr, (void delegate(Object)).sizeof * len); 
    189176                if (!p) 
    190177                    _d_OutOfMemory(); 
    191                 m.delegates = (cast(void delegate(Object)*)p)[0 .. len]; 
    192                 m.delegates[startlen .. len] = null; 
     178                fatLock.delegates = (cast(void delegate(Object)*)p)[0 .. len]; 
     179                fatLock.delegates[startlen .. len] = null; 
    193180            } 
    194             m.delegates[startlen] = dg; 
     181            fatLock.delegates[startlen] = dg; 
    195182        } 
    196183    } 
     
    205192        synchronized (this) 
    206193        { 
    207             Monitor* m = getMonitorPtr(); 
    208             assert(m != null); 
    209             foreach (inout x; m.delegates) 
     194            FatLock * fatLock = GetFatLock(this); 
     195            assert(fatLock); 
     196            foreach (inout x; fatLock.delegates) 
    210197            { 
    211198                if (x == dg) 
     
    236223{ 
    237224    //printf("_d_notify_release(o = %p)\n", o); 
    238     Monitor* m = o.getMonitorPtr(); 
    239     assert(m != null); 
    240     if (m.delegates.length) 
    241     { 
    242         auto dgs = m.delegates; 
     225    FatLock * fatLock = GetFatLock(o); 
     226    assert(fatLock); 
     227    if (fatLock.delegates.length) 
     228    { 
     229        auto dgs = fatLock.delegates; 
    243230        synchronized (o) 
    244231        { 
    245             dgs = m.delegates; 
    246             m.delegates = null; 
     232            dgs = fatLock.delegates; 
     233            fatLock.delegates = null; 
    247234        } 
    248235 
     
    950937        assert(p); 
    951938        if (xtoHash) 
    952         {   //printf("getHash() using xtoHash\n"); 
     939        { 
     940            //printf("getHash() using xtoHash\n"); 
    953941            h = (*xtoHash)(p); 
    954942        } 
  • trunk/phobos/linux.mak

    r759 r779  
    138138 
    139139INTERNAL_MODULES = aApply aApplyR aaA adi alloca arraycast arraycat \ 
    140     cast cmath2 deh2 dmain2 invariant llmath memset obj object
    141     qsort switch trace arrayassign 
    142 INTERNAL_CMODULES = complex critical monitor 
     140    cast cmath2 deh2 dmain2 invariant llmath memset monitor obj     
     141    object qsort switch trace arrayassign 
     142INTERNAL_CMODULES = complex critical 
    143143INTERNAL_CMODULES_NOTBUILT = deh 
    144144INTERNAL_EXTRAFILES = internal/mars.h internal/minit.asm 
  • trunk/phobos/win32.mak

    r777 r779  
    270270    internal\switch.d internal\complex.c internal\critical.c \ 
    271271    internal\minit.asm internal\alloca.d internal\llmath.d internal\deh.c \ 
    272     internal\arraycat.d internal\invariant.d internal\monitor.c
     272    internal\arraycat.d internal\invariant.d internal\monitor.d
    273273    internal\memset.d internal\arraycast.d internal\aaA.d internal\adi.d \ 
    274274    internal\dmain2.d internal\cast.d internal\qsort.d internal\deh2.d \ 
     
    424424    $(CC) -c internal\minit.asm 
    425425 
    426 monitor.obj : internal\mars.h internal\monitor.c 
    427     $(CC) -c $(CFLAGS) internal\monitor.c 
     426monitor.obj : internal\mars.h internal\monitor.d 
     427    $(DMD) -c $(DFLAGS) internal\monitor.d 
    428428 
    429429obj.obj : internal\obj.d