2 * Part of the D programming language runtime library.
3 * Forms the symbols available to all D programs. Includes
4 * Object, which is the root of the class object hierarchy.
6 * This module is implicitly imported.
12 * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
13 * Written by Walter Bright
15 * This software is provided 'as-is', without any express or implied
16 * warranty. In no event will the authors be held liable for any damages
17 * arising from the use of this software.
19 * Permission is granted to anyone to use this software for any purpose,
20 * including commercial applications, and to alter it and redistribute it
21 * freely, in both source and binary form, subject to the following
24 * o The origin of this software must not be misrepresented; you must not
25 * claim that you wrote the original software. If you use this software
26 * in a product, an acknowledgment in the product documentation would be
27 * appreciated but is not required.
28 * o Altered source versions must be plainly marked as such, and must not
29 * be misrepresented as being the original software.
30 * o This notice may not be removed or altered from any source
35 * Modified by Sean Kelly for use with the D Runtime Project
45 debug(PRINTF) import stdc.stdio;
47 extern (C) void onOutOfMemoryError();
48 extern (C) Object _d_newclass(ClassInfo ci);
51 // NOTE: For some reason, this declaration method doesn't work
52 // in this particular file (and this file only). It must
54 //alias typeof(int.sizeof) size_t;
55 //alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t;
71 alias invariant(char)[] string;
72 alias invariant(wchar)[] wstring;
73 alias invariant(dchar)[] dstring;
76 * All D class objects inherit from Object.
81 * Convert Object to a human readable string.
85 return this.classinfo.name;
89 * Compute hash function for Object.
93 // BUG: this prevents a compacting GC from working, needs to be fixed
94 return cast(hash_t)cast(void*)this;
98 * Compare with another Object obj.
101 * $(TR $(TD this < obj) $(TD < 0))
102 * $(TR $(TD this == obj) $(TD 0))
103 * $(TR $(TD this > obj) $(TD > 0))
108 // BUG: this prevents a compacting GC from working, needs to be fixed
109 //return cast(int)cast(void*)this - cast(int)cast(void*)o;
111 throw new Exception("need opCmp for class " ~ this.classinfo.name);
116 * Returns !=0 if this object does have the same contents as obj.
118 equals_t opEquals(Object o)
131 * Information about an interface.
132 * When an object is accessed via an interface, an Interface* appears as the
133 * first entry in its vtbl.
137 ClassInfo classinfo; /// .classinfo for this interface (not for containing class)
139 ptrdiff_t offset; /// offset to Interface 'this' from Object 'this'
143 * Runtime type information about a class. Can be retrieved for any class type
144 * or instance by using the .classinfo property.
145 * A pointer to this appears as the first entry in the class's vtbl[].
147 class ClassInfo : Object
149 byte[] init; /** class static initializer
150 * (init.length gives size in bytes of class)
152 string name; /// class name
153 void*[] vtbl; /// virtual function pointer table
154 Interface[] interfaces; /// interfaces this class implements
155 ClassInfo base; /// base class
157 void function(Object) classInvariant;
159 // 1: // is IUnknown or is derived from IUnknown
160 // 2: // has no possible pointers into GC memory
161 // 4: // has offTi[] member
162 // 8: // has constructors
163 // 16: // has xgetMembers member
165 OffsetTypeInfo[] offTi;
166 void function(Object) defaultConstructor; // default Constructor
167 const(MemberInfo[]) function(in char[]) xgetMembers;
170 * Search all modules for ClassInfo corresponding to classname.
171 * Returns: null if not found
173 static ClassInfo find(in char[] classname)
175 foreach (m; ModuleInfo)
177 //writefln("module %s, %d", m.name, m.localClasses.length);
178 foreach (c; m.localClasses)
180 //writefln("\tclass %s", c.name);
181 if (c.name == classname)
189 * Create instance of Object represented by 'this'.
193 if (flags & 8 && !defaultConstructor)
195 Object o = _d_newclass(this);
196 if (flags & 8 && defaultConstructor)
198 defaultConstructor(o);
203 * Search for all members with the name 'name'.
204 * If name[] is null, return all members.
206 const(MemberInfo[]) getMembers(in char[] name)
208 if (flags & 16 && xgetMembers)
209 return xgetMembers(name);
215 * Array of pairs giving the offset and type information for each
216 * member in an aggregate.
218 struct OffsetTypeInfo
220 size_t offset; /// Offset of member from start of object
221 TypeInfo ti; /// TypeInfo for this member
225 * Runtime type information about a type.
226 * Can be retrieved for any type using a
227 * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
231 override hash_t toHash()
234 foreach (char c; this.toString())
239 override int opCmp(Object o)
243 TypeInfo ti = cast(TypeInfo)o;
246 return dstrcmp(this.toString(), ti.toString());
249 override equals_t opEquals(Object o)
251 /* TypeInfo instances are singletons, but duplicates can exist
252 * across DLL's. Therefore, comparing for a name match is
257 TypeInfo ti = cast(TypeInfo)o;
258 return ti && this.toString() == ti.toString();
261 /// Returns a hash of the instance of a type.
262 hash_t getHash(in void* p) { return cast(hash_t)p; }
264 /// Compares two instances for equality.
265 equals_t equals(in void* p1, in void* p2) { return p1 == p2; }
267 /// Compares two instances for <, ==, or >.
268 int compare(in void* p1, in void* p2) { return 0; }
270 /// Returns size of the type.
271 size_t tsize() { return 0; }
273 /// Swaps two instances of the type.
274 void swap(void* p1, void* p2)
277 for (size_t i = 0; i < n; i++)
279 byte t = (cast(byte *)p1)[i];
280 (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
281 (cast(byte*)p2)[i] = t;
285 /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
287 TypeInfo next() { return null; }
289 /// Return default initializer, null if default initialize to 0
290 void[] init() { return null; }
292 /// Get flags for type: 1 means GC should scan for pointers
293 uint flags() { return 0; }
295 /// Get type information on the contents of the type; null if not available
296 OffsetTypeInfo[] offTi() { return null; }
297 /// Run the destructor on the object and all its sub-objects
298 void destroy(void* p) {}
299 /// Run the postblit on the object and all its sub-objects
300 void postblit(void* p) {}
303 class TypeInfo_Typedef : TypeInfo
305 override string toString() { return name; }
307 override equals_t opEquals(Object o)
311 ((c = cast(TypeInfo_Typedef)o) !is null &&
312 this.name == c.name &&
313 this.base == c.base);
316 override hash_t getHash(in void* p) { return base.getHash(p); }
317 override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
318 override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
319 override size_t tsize() { return base.tsize(); }
320 override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
322 override TypeInfo next() { return base.next(); }
323 override uint flags() { return base.flags(); }
324 override void[] init() { return m_init.length ? m_init : base.init(); }
331 class TypeInfo_Enum : TypeInfo_Typedef
336 class TypeInfo_Pointer : TypeInfo
338 override string toString() { return m_next.toString() ~ "*"; }
340 override equals_t opEquals(Object o)
344 ((c = cast(TypeInfo_Pointer)o) !is null &&
345 this.m_next == c.m_next);
348 override hash_t getHash(in void* p)
350 return cast(hash_t)*cast(void**)p;
353 override equals_t equals(in void* p1, in void* p2)
355 return *cast(void**)p1 == *cast(void**)p2;
358 override int compare(in void* p1, in void* p2)
360 if (*cast(void**)p1 < *cast(void**)p2)
362 else if (*cast(void**)p1 > *cast(void**)p2)
368 override size_t tsize()
370 return (void*).sizeof;
373 override void swap(void* p1, void* p2)
375 void* tmp = *cast(void**)p1;
376 *cast(void**)p1 = *cast(void**)p2;
377 *cast(void**)p2 = tmp;
380 override TypeInfo next() { return m_next; }
381 override uint flags() { return 1; }
386 class TypeInfo_Array : TypeInfo
388 override string toString() { return value.toString() ~ "[]"; }
390 override equals_t opEquals(Object o)
394 ((c = cast(TypeInfo_Array)o) !is null &&
395 this.value == c.value);
398 override hash_t getHash(in void* p)
400 size_t sz = value.tsize();
402 void[] a = *cast(void[]*)p;
403 for (size_t i = 0; i < a.length; i++)
404 hash += value.getHash(a.ptr + i * sz);
408 override equals_t equals(in void* p1, in void* p2)
410 void[] a1 = *cast(void[]*)p1;
411 void[] a2 = *cast(void[]*)p2;
412 if (a1.length != a2.length)
414 size_t sz = value.tsize();
415 for (size_t i = 0; i < a1.length; i++)
417 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
423 override int compare(in void* p1, in void* p2)
425 void[] a1 = *cast(void[]*)p1;
426 void[] a2 = *cast(void[]*)p2;
427 size_t sz = value.tsize();
428 size_t len = a1.length;
432 for (size_t u = 0; u < len; u++)
434 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
438 return cast(int)a1.length - cast(int)a2.length;
441 override size_t tsize()
443 return (void[]).sizeof;
446 override void swap(void* p1, void* p2)
448 void[] tmp = *cast(void[]*)p1;
449 *cast(void[]*)p1 = *cast(void[]*)p2;
450 *cast(void[]*)p2 = tmp;
455 override TypeInfo next()
460 override uint flags() { return 1; }
463 class TypeInfo_StaticArray : TypeInfo
465 override string toString()
468 return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]");
471 override equals_t opEquals(Object o)
473 TypeInfo_StaticArray c;
475 ((c = cast(TypeInfo_StaticArray)o) !is null &&
477 this.value == c.value);
480 override hash_t getHash(in void* p)
482 size_t sz = value.tsize();
484 for (size_t i = 0; i < len; i++)
485 hash += value.getHash(p + i * sz);
489 override equals_t equals(in void* p1, in void* p2)
491 size_t sz = value.tsize();
493 for (size_t u = 0; u < len; u++)
495 if (!value.equals(p1 + u * sz, p2 + u * sz))
501 override int compare(in void* p1, in void* p2)
503 size_t sz = value.tsize();
505 for (size_t u = 0; u < len; u++)
507 int result = value.compare(p1 + u * sz, p2 + u * sz);
514 override size_t tsize()
516 return len * value.tsize();
519 override void swap(void* p1, void* p2)
522 size_t sz = value.tsize();
526 if (sz < buffer.sizeof)
529 tmp = pbuffer = (new void[sz]).ptr;
531 for (size_t u = 0; u < len; u += sz)
533 memcpy(tmp, p1 + o, sz);
534 memcpy(p1 + o, p2 + o, sz);
535 memcpy(p2 + o, tmp, sz);
541 override void[] init() { return value.init(); }
542 override TypeInfo next() { return value; }
543 override uint flags() { return value.flags(); }
545 override void destroy(void* p)
547 auto sz = value.tsize();
549 foreach (i; 0 .. len)
556 override void postblit(void* p)
558 auto sz = value.tsize();
559 foreach (i; 0 .. len)
570 class TypeInfo_AssociativeArray : TypeInfo
572 override string toString()
574 return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]");
577 override equals_t opEquals(Object o)
579 TypeInfo_AssociativeArray c;
581 ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
583 this.value == c.value);
586 // BUG: need to add the rest of the functions
588 override size_t tsize()
590 return (char[int]).sizeof;
593 override TypeInfo next() { return value; }
594 override uint flags() { return 1; }
600 class TypeInfo_Function : TypeInfo
602 override string toString()
604 return cast(string)(next.toString() ~ "()");
607 override equals_t opEquals(Object o)
611 ((c = cast(TypeInfo_Function)o) !is null &&
612 this.next == c.next);
615 // BUG: need to add the rest of the functions
617 override size_t tsize()
619 return 0; // no size for functions
625 class TypeInfo_Delegate : TypeInfo
627 override string toString()
629 return cast(string)(next.toString() ~ " delegate()");
632 override equals_t opEquals(Object o)
636 ((c = cast(TypeInfo_Delegate)o) !is null &&
637 this.next == c.next);
640 // BUG: need to add the rest of the functions
642 override size_t tsize()
644 alias int delegate() dg;
648 override uint flags() { return 1; }
653 class TypeInfo_Class : TypeInfo
655 override string toString() { return info.name; }
657 override equals_t opEquals(Object o)
661 ((c = cast(TypeInfo_Class)o) !is null &&
662 this.info.name == c.classinfo.name);
665 override hash_t getHash(in void* p)
667 Object o = *cast(Object*)p;
668 return o ? o.toHash() : 0;
671 override equals_t equals(in void* p1, in void* p2)
673 Object o1 = *cast(Object*)p1;
674 Object o2 = *cast(Object*)p2;
676 return (o1 is o2) || (o1 && o1.opEquals(o2));
679 override int compare(in void* p1, in void* p2)
681 Object o1 = *cast(Object*)p1;
682 Object o2 = *cast(Object*)p2;
685 // Regard null references as always being "less than"
701 override size_t tsize()
703 return Object.sizeof;
706 override uint flags() { return 1; }
708 override OffsetTypeInfo[] offTi()
710 return (info.flags & 4) ? info.offTi : null;
716 class TypeInfo_Interface : TypeInfo
718 override string toString() { return info.name; }
720 override equals_t opEquals(Object o)
722 TypeInfo_Interface c;
724 ((c = cast(TypeInfo_Interface)o) !is null &&
725 this.info.name == c.classinfo.name);
728 override hash_t getHash(in void* p)
730 Interface* pi = **cast(Interface ***)*cast(void**)p;
731 Object o = cast(Object)(*cast(void**)p - pi.offset);
736 override equals_t equals(in void* p1, in void* p2)
738 Interface* pi = **cast(Interface ***)*cast(void**)p1;
739 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
740 pi = **cast(Interface ***)*cast(void**)p2;
741 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
743 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
746 override int compare(in void* p1, in void* p2)
748 Interface* pi = **cast(Interface ***)*cast(void**)p1;
749 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
750 pi = **cast(Interface ***)*cast(void**)p2;
751 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
754 // Regard null references as always being "less than"
770 override size_t tsize()
772 return Object.sizeof;
775 override uint flags() { return 1; }
780 class TypeInfo_Struct : TypeInfo
782 override string toString() { return name; }
784 override equals_t opEquals(Object o)
788 ((s = cast(TypeInfo_Struct)o) !is null &&
789 this.name == s.name &&
790 this.init.length == s.init.length);
793 override hash_t getHash(in void* p)
798 debug(PRINTF) printf("getHash() using xtoHash\n");
799 return (*xtoHash)(p);
804 debug(PRINTF) printf("getHash() using default hash\n");
805 // A sorry hash algorithm.
806 // Should use the one for strings.
807 // BUG: relies on the GC not moving objects
808 auto q = cast(const(ubyte)*)p;
809 for (size_t i = 0; i < init.length; i++)
818 override equals_t equals(in void* p1, in void* p2)
825 return (*xopEquals)(p1, p2);
827 // BUG: relies on the GC not moving objects
828 return memcmp(p1, p2, init.length) == 0;
831 override int compare(in void* p1, in void* p2)
833 // Regard null references as always being "less than"
841 return (*xopCmp)(p2, p1);
843 // BUG: relies on the GC not moving objects
844 return memcmp(p1, p2, init.length);
852 override size_t tsize()
857 override void[] init() { return m_init; }
859 override uint flags() { return m_flags; }
861 override void destroy(void* p)
867 override void postblit(void* p)
874 void[] m_init; // initializer; init.ptr == null if 0 initialize
876 hash_t function(in void*) xtoHash;
877 equals_t function(in void*, in void*) xopEquals;
878 int function(in void*, in void*) xopCmp;
879 char[] function(in void*) xtoString;
883 const(MemberInfo[]) function(in char[]) xgetMembers;
884 void function(void*) xdtor;
885 void function(void*) xpostblit;
888 class TypeInfo_Tuple : TypeInfo
892 override string toString()
895 foreach (i, element; elements)
899 s ~= element.toString();
905 override equals_t opEquals(Object o)
910 auto t = cast(TypeInfo_Tuple)o;
911 if (t && elements.length == t.elements.length)
913 for (size_t i = 0; i < elements.length; i++)
915 if (elements[i] != t.elements[i])
923 override hash_t getHash(in void* p)
928 override equals_t equals(in void* p1, in void* p2)
933 override int compare(in void* p1, in void* p2)
938 override size_t tsize()
943 override void swap(void* p1, void* p2)
948 override void destroy(void* p)
953 override void postblit(void* p)
959 class TypeInfo_Const : TypeInfo
961 override string toString()
963 return cast(string) ("const(" ~ base.toString() ~ ")");
966 override equals_t opEquals(Object o) { return base.opEquals(o); }
967 override hash_t getHash(in void *p) { return base.getHash(p); }
968 override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); }
969 override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); }
970 override size_t tsize() { return base.tsize(); }
971 override void swap(void *p1, void *p2) { return base.swap(p1, p2); }
973 override TypeInfo next() { return base.next(); }
974 override uint flags() { return base.flags(); }
975 override void[] init() { return base.init(); }
980 class TypeInfo_Invariant : TypeInfo_Const
982 override string toString()
984 return cast(string) ("invariant(" ~ base.toString() ~ ")");
988 abstract class MemberInfo
993 class MemberInfo_field : MemberInfo
995 this(string name, TypeInfo ti, size_t offset)
1002 override string name() { return m_name; }
1003 TypeInfo typeInfo() { return m_typeinfo; }
1004 size_t offset() { return m_offset; }
1007 TypeInfo m_typeinfo;
1011 class MemberInfo_function : MemberInfo
1013 this(string name, TypeInfo ti, void* fp, uint flags)
1021 override string name() { return m_name; }
1022 TypeInfo typeInfo() { return m_typeinfo; }
1023 void* fp() { return m_fp; }
1024 uint flags() { return m_flags; }
1027 TypeInfo m_typeinfo;
1033 ///////////////////////////////////////////////////////////////////////////////
1035 ///////////////////////////////////////////////////////////////////////////////
1038 class Exception : Object
1042 int opApply( int delegate(inout char[]) );
1051 this( string msg, Exception next = null )
1055 this.info = traceContext();
1058 this( string msg, string file, size_t line, Exception next = null )
1063 this.info = traceContext();
1066 override string toString()
1073 alias Exception.TraceInfo function( void* ptr = null ) TraceHandler;
1074 private TraceHandler traceHandler = null;
1078 * Overrides the default trace hander with a user-supplied version.
1081 * h = The new trace handler. Set to null to use the default handler.
1083 extern (C) void rt_setTraceHandler( TraceHandler h )
1090 * This function will be called when an Exception is constructed. The
1091 * user-supplied trace handler will be called if one has been supplied,
1092 * otherwise no trace will be generated.
1095 * ptr = A pointer to the location from which to generate the trace, or null
1096 * if the trace should be generated from within the trace handler
1100 * An object describing the current calling context or null if no handler is
1103 Exception.TraceInfo traceContext( void* ptr = null )
1105 if( traceHandler is null )
1107 return traceHandler( ptr );
1111 ///////////////////////////////////////////////////////////////////////////////
1113 ///////////////////////////////////////////////////////////////////////////////
1118 MIctorstart = 1, // we've started constructing it
1119 MIctordone = 2, // finished construction
1120 MIstandalone = 4, // module ctor does not depend on other module
1121 // ctors being done first
1122 MIhasictor = 8, // has ictor member
1129 ModuleInfo[] importedModules;
1130 ClassInfo[] localClasses;
1133 void function() ctor; // module static constructor (order dependent)
1134 void function() dtor; // module static destructor
1135 void function() unitTest; // module unit tests
1137 void* xgetMembers; // module getMembers() function
1139 void function() ictor; // module static constructor (order independent)
1141 static int opApply( int delegate(inout ModuleInfo) dg )
1145 foreach( m; _moduleinfo_array )
1156 // Windows: this gets initialized by minit.asm
1157 // linux: this gets initialized in _moduleCtor()
1158 extern (C) ModuleInfo[] _moduleinfo_array;
1163 // This linked list is created by a compiler generated function inserted
1164 // into the .ctor list by the compiler.
1165 struct ModuleReference
1167 ModuleReference* next;
1171 extern (C) ModuleReference* _Dmodule_ref; // start of linked list
1174 ModuleInfo[] _moduleinfo_dtors;
1175 uint _moduleinfo_dtors_i;
1177 // Register termination function pointers
1178 extern (C) int _fatexit(void*);
1181 * Initialize the modules.
1184 extern (C) void _moduleCtor()
1186 debug(PRINTF) printf("_moduleCtor()\n");
1190 ModuleReference *mr;
1192 for (mr = _Dmodule_ref; mr; mr = mr.next)
1194 _moduleinfo_array = new ModuleInfo[len];
1196 for (mr = _Dmodule_ref; mr; mr = mr.next)
1197 { _moduleinfo_array[len] = mr.mod;
1204 // Ensure module destructors also get called on program termination
1205 //_fatexit(&_STD_moduleDtor);
1208 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
1209 debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
1210 _moduleIndependentCtors();
1211 _moduleCtor2(_moduleinfo_array, 0);
1214 extern (C) void _moduleIndependentCtors()
1216 debug(PRINTF) printf("_moduleIndependentCtors()\n");
1217 foreach (m; _moduleinfo_array)
1219 if (m && m.flags & MIhasictor && m.ictor)
1226 void _moduleCtor2(ModuleInfo[] mi, int skip)
1228 debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
1229 for (uint i = 0; i < mi.length; i++)
1231 ModuleInfo m = mi[i];
1233 debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
1236 debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
1237 if (m.flags & MIctordone)
1239 debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
1241 if (m.ctor || m.dtor)
1243 if (m.flags & MIctorstart)
1244 { if (skip || m.flags & MIstandalone)
1246 throw new Exception( "Cyclic dependency in module " ~ m.name );
1249 m.flags |= MIctorstart;
1250 _moduleCtor2(m.importedModules, 0);
1253 m.flags &= ~MIctorstart;
1254 m.flags |= MIctordone;
1256 // Now that construction is done, register the destructor
1257 //printf("\tadding module dtor x%x\n", m);
1258 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
1259 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
1263 m.flags |= MIctordone;
1264 _moduleCtor2(m.importedModules, 1);
1270 * Destruct the modules.
1273 // Starting the name with "_STD" means under linux a pointer to the
1274 // function gets put in the .dtors segment.
1276 extern (C) void _moduleDtor()
1278 debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
1280 for (uint i = _moduleinfo_dtors_i; i-- != 0;)
1282 ModuleInfo m = _moduleinfo_dtors[i];
1284 debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
1290 debug(PRINTF) printf("_moduleDtor() done\n");
1293 ///////////////////////////////////////////////////////////////////////////////
1295 ///////////////////////////////////////////////////////////////////////////////
1297 alias Object.Monitor IMonitor;
1298 alias void delegate(Object) DEvent;
1300 // NOTE: The dtor callback feature is only supported for monitors that are not
1301 // supplied by the user. The assumption is that any object with a user-
1302 // supplied monitor may have special storage or lifetime requirements and
1303 // that as a result, storing references to local objects within Monitor
1304 // may not be safe or desirable. Thus, devt is only valid if impl is
1314 Monitor* getMonitor(Object h)
1316 return cast(Monitor*) (cast(void**) h)[1];
1319 void setMonitor(Object h, Monitor* m)
1321 (cast(void**) h)[1] = m;
1324 extern (C) void _d_monitor_create(Object);
1325 extern (C) void _d_monitor_destroy(Object);
1326 extern (C) void _d_monitor_lock(Object);
1327 extern (C) int _d_monitor_unlock(Object);
1329 extern (C) void _d_monitordelete(Object h, bool det)
1331 Monitor* m = getMonitor(h);
1335 IMonitor i = m.impl;
1338 _d_monitor_devt(m, h);
1339 _d_monitor_destroy(h);
1340 setMonitor(h, null);
1343 if (det && (cast(void*) i) !is (cast(void*) h))
1345 setMonitor(h, null);
1349 extern (C) void _d_monitorenter(Object h)
1351 Monitor* m = getMonitor(h);
1355 _d_monitor_create(h);
1359 IMonitor i = m.impl;
1369 extern (C) void _d_monitorexit(Object h)
1371 Monitor* m = getMonitor(h);
1372 IMonitor i = m.impl;
1376 _d_monitor_unlock(h);
1382 extern (C) void _d_monitor_devt(Monitor* m, Object h)
1402 extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
1406 Monitor* m = getMonitor(h);
1407 assert(m.impl is null);
1409 foreach (inout v; m.devt)
1411 if (v is null || v == e)
1418 auto len = m.devt.length + 4; // grow by 4 elements
1419 auto pos = m.devt.length; // insert position
1420 auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
1422 onOutOfMemoryError();
1423 m.devt = (cast(DEvent*)p)[0 .. len];
1424 m.devt[pos+1 .. len] = null;
1429 extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
1433 Monitor* m = getMonitor(h);
1434 assert(m.impl is null);
1436 foreach (p, v; m.devt)
1442 (m.devt.length - p - 1) * DEvent.sizeof);
1443 m.devt[$ - 1] = null;