Changeset 779
- Timestamp:
- 07/03/08 17:35:36 (3 months ago)
- Files:
-
- trunk/phobos/internal/monitor.c (deleted)
- trunk/phobos/internal/monitor.d (modified) (6 diffs)
- trunk/phobos/internal/object.d (modified) (10 diffs)
- trunk/phobos/linux.mak (modified) (1 diff)
- trunk/phobos/win32.mak (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/phobos/internal/monitor.d
r775 r779 4 4 /** 5 5 Part of the D programming language runtime library. 6 Implements _Object monitors used by $(D synchronized) methods and blocks6 Implements Object monitors used by $(D synchronized) methods and blocks 7 7 8 8 Author: Bartosz Milewski, Walter Bright … … 11 11 */ 12 12 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) 13 module internal.monitor; 14 15 extern (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) 19 26 T construct(T:Object, A...)(A args) 20 27 { 21 28 ClassInfo info = T.classinfo; 22 29 void * p = malloc(info.init.length); 30 if (!p) 31 _d_OutOfMemory(); 23 32 memcpy(p, info.init.ptr, info.init.length); 24 33 T obj = cast(T)p; 25 static if (is(typeof(obj._ctor) == function))34 static if (is(typeof(obj._ctor))) 26 35 obj._ctor(args); 27 36 return obj; … … 30 39 void destroy(T:Object)(T obj) 31 40 { 32 static if (is(typeof(obj._dtor) == function))41 static if (is(typeof(obj._dtor))) 33 42 obj._dtor(); 34 43 free(cast(void*) obj); 35 44 } 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 48 Because struct destructors don't work yet, I use artificial setup/teardown 49 */ 50 T * 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 */ 61 void 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 69 OsMutex * __monitor_mutex; 70 71 /** The layout of every object header */ 72 struct ObjectLayout 73 { 74 private: 75 void * _vtable; 76 FatLock * _fatLock; 77 } 78 79 /** For eny object return the layout of its header */ 80 ObjectLayout * ToLayout(Object o) 81 { 82 return cast(ObjectLayout *) cast(void *) o; 83 } 84 85 /** Access to the object's _fatLock */ 86 FatLock * GetFatLock(Object o) 87 { 88 return ToLayout(o)._fatLock; 89 } 90 91 final void SetFatLock(Object o, FatLock * other) 92 { 93 ToLayout(o)._fatLock = other; 94 } 95 96 /** Contains the object monitor and the array of delegates 97 that are used by signals and slots */ 98 struct FatLock 99 { 100 public void delegate(Object) [] delegates; 101 private OsMutex * mon; 102 void setup() { mon = conStruct!(OsMutex)(); } 103 void teardown() { deStruct(mon); } 51 104 public: 52 105 void lock() { mon.lock; } … … 54 107 } 55 108 56 / / Called only once by a single thread during startup109 /** Called only once by a single thread during startup */ 57 110 extern(C) void _STI_monitor_staticctor() 58 111 { 59 _monitor_critsect = construct!(OsMutex)(); 60 } 61 112 __monitor_mutex = conStruct!(OsMutex)(); 113 } 114 115 /** Called only once by a single thread during teardown */ 62 116 extern(C) void _STD_monitor_staticdtor() 63 117 { 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 122 extern(C) void _d_notify_release(Object); 123 124 /** Called by runtime when entering a synchronized block */ 70 125 extern(C) 71 void _d_monitorenter( _Object obj)72 { 73 //printf("_d_monitorenter(%p), %p\n", obj, obj ->monitor);126 void _d_monitorenter(Object obj) 127 { 128 //printf("_d_monitorenter(%p), %p\n", obj, obj.__monitor); 74 129 // Warning: data race 75 if ( obj._fatLockis null)76 { 77 scope lock = new OsLock (_monitor_critsect);78 if ( obj._fatLockis null) // if, in the meantime, another thread didn't set it130 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 79 134 { 80 obj._fatLock = new FatLock;135 SetFatLock(obj, conStruct!(FatLock)); 81 136 } 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 */ 86 143 extern(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. 144 void _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. 95 153 */ 96 154 97 155 extern(C) 98 void _d_monitorrelease(_Object obj) 99 { 100 if (obj._fatLock !is null) 156 void _d_monitorrelease(Object obj) 157 { 158 //printf("monitor release (%p), %p\n", obj, obj.__monitor); 159 if (GetFatLock(obj)) 101 160 { 102 161 _d_notify_release(obj); 103 162 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 } 126 166 } 127 167 … … 142 182 143 183 */ 144 class OsMutex 184 // replace setup/teardown with constructor/destructor for structs 185 struct OsMutex 145 186 { 146 187 public: 147 this()188 void setup() 148 189 { 149 190 InitializeCriticalSection (&_critSection); 150 191 } 151 ~this()192 void teardown() 152 193 { 153 194 DeleteCriticalSection (&_critSection); 154 195 } 155 finalvoid lock()196 void lock() 156 197 { 157 198 EnterCriticalSection (&_critSection); 158 199 } 159 finalvoid unlock()200 void unlock() 160 201 { 161 202 LeaveCriticalSection (&_critSection); … … 177 218 } 178 219 179 class OsMutex 220 // replace setup/teardown with constructor/destructor for structs 221 struct OsMutex 180 222 { 181 223 public: 182 this()224 void setup() 183 225 { 184 226 pthread_mutex_init(&_mtx, _monitors_attr); 185 227 } 186 ~this()228 void teardown() 187 229 { 188 230 pthread_mutex_destroy(&_mtx); 189 231 } 190 finalvoid lock()232 void lock() 191 233 { 192 234 pthread_mutex_lock(&_mtx); 193 235 } 194 finalvoid unlock()236 void unlock() 195 237 { 196 238 pthread_mutex_unlock(&_mtx); trunk/phobos/internal/object.d
r772 r779 4 4 * Forms the symbols available to all D programs. Includes 5 5 * Object, which is the root of the class object hierarchy. 6 * 7 * Authors: Walter Bright, Bartosz Milewski 6 8 * 7 9 * This module is implicitly imported. … … 37 39 38 40 import std.outofmemory; 41 import internal.monitor; 39 42 40 43 /** … … 77 80 alias invariant(dchar)[] dstring; 78 81 79 /* *************************80 * Internal struct pointed to by the hidden .monitor member.81 */82 struct Monitor83 {84 void delegate(Object)[] delegates;85 86 /* More stuff goes here defined by internal/monitor.c */87 }88 89 82 /****************** 90 83 * All D class objects inherit from Object. … … 92 85 class Object 93 86 { 94 final Monitor * getMonitorPtr()95 {96 Monitor * mon = cast(Monitor*)(cast(void**)this)[1];97 return mon;98 }99 100 87 void print() 101 88 { … … 162 149 // Important: Monitor is guaranteed to be initialized 163 150 // 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) 167 154 { 168 155 if (!x || x == dg) … … 173 160 174 161 // Increase size of delegates[] 175 auto len = m.delegates.length;162 auto len = fatLock.delegates.length; 176 163 auto startlen = len; 177 164 if (len == 0) … … 181 168 if (!p) 182 169 _d_OutOfMemory(); 183 m.delegates = (cast(void delegate(Object)*)p)[0 .. len];170 fatLock.delegates = (cast(void delegate(Object)*)p)[0 .. len]; 184 171 } 185 172 else 186 173 { 187 174 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); 189 176 if (!p) 190 177 _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; 193 180 } 194 m.delegates[startlen] = dg;181 fatLock.delegates[startlen] = dg; 195 182 } 196 183 } … … 205 192 synchronized (this) 206 193 { 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) 210 197 { 211 198 if (x == dg) … … 236 223 { 237 224 //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; 243 230 synchronized (o) 244 231 { 245 dgs = m.delegates;246 m.delegates = null;232 dgs = fatLock.delegates; 233 fatLock.delegates = null; 247 234 } 248 235 … … 950 937 assert(p); 951 938 if (xtoHash) 952 { //printf("getHash() using xtoHash\n"); 939 { 940 //printf("getHash() using xtoHash\n"); 953 941 h = (*xtoHash)(p); 954 942 } trunk/phobos/linux.mak
r759 r779 138 138 139 139 INTERNAL_MODULES = aApply aApplyR aaA adi alloca arraycast arraycat \ 140 cast cmath2 deh2 dmain2 invariant llmath memset obj object\141 qsort switch trace arrayassign142 INTERNAL_CMODULES = complex critical monitor140 cast cmath2 deh2 dmain2 invariant llmath memset monitor obj \ 141 object qsort switch trace arrayassign 142 INTERNAL_CMODULES = complex critical 143 143 INTERNAL_CMODULES_NOTBUILT = deh 144 144 INTERNAL_EXTRAFILES = internal/mars.h internal/minit.asm trunk/phobos/win32.mak
r777 r779 270 270 internal\switch.d internal\complex.c internal\critical.c \ 271 271 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 \ 273 273 internal\memset.d internal\arraycast.d internal\aaA.d internal\adi.d \ 274 274 internal\dmain2.d internal\cast.d internal\qsort.d internal\deh2.d \ … … 424 424 $(CC) -c internal\minit.asm 425 425 426 monitor.obj : internal\mars.h internal\monitor. c427 $( CC) -c $(CFLAGS) internal\monitor.c426 monitor.obj : internal\mars.h internal\monitor.d 427 $(DMD) -c $(DFLAGS) internal\monitor.d 428 428 429 429 obj.obj : internal\obj.d
