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)
130 * Create instance of class specified by classname.
131 * The class must either have no constructors or have
132 * a default constructor.
136 static Object factory(string classname)
138 auto ci = ClassInfo.find(classname);
148 * Information about an interface.
149 * When an object is accessed via an interface, an Interface* appears as the
150 * first entry in its vtbl.
154 ClassInfo classinfo; /// .classinfo for this interface (not for containing class)
156 ptrdiff_t offset; /// offset to Interface 'this' from Object 'this'
160 * Runtime type information about a class. Can be retrieved for any class type
161 * or instance by using the .classinfo property.
162 * A pointer to this appears as the first entry in the class's vtbl[].
164 class ClassInfo : Object
166 byte[] init; /** class static initializer
167 * (init.length gives size in bytes of class)
169 string name; /// class name
170 void*[] vtbl; /// virtual function pointer table
171 Interface[] interfaces; /// interfaces this class implements
172 ClassInfo base; /// base class
174 void function(Object) classInvariant;
176 // 1: // is IUnknown or is derived from IUnknown
177 // 2: // has no possible pointers into GC memory
178 // 4: // has offTi[] member
179 // 8: // has constructors
180 // 16: // has xgetMembers member
182 OffsetTypeInfo[] offTi;
183 void function(Object) defaultConstructor; // default Constructor
184 const(MemberInfo[]) function(in char[]) xgetMembers;
187 * Search all modules for ClassInfo corresponding to classname.
188 * Returns: null if not found
190 static ClassInfo find(in char[] classname)
192 foreach (m; ModuleInfo)
194 //writefln("module %s, %d", m.name, m.localClasses.length);
195 foreach (c; m.localClasses)
197 //writefln("\tclass %s", c.name);
198 if (c.name == classname)
206 * Create instance of Object represented by 'this'.
210 if (flags & 8 && !defaultConstructor)
212 Object o = _d_newclass(this);
213 if (flags & 8 && defaultConstructor)
215 defaultConstructor(o);
221 * Search for all members with the name 'name'.
222 * If name[] is null, return all members.
224 const(MemberInfo[]) getMembers(in char[] name)
226 if (flags & 16 && xgetMembers)
227 return xgetMembers(name);
233 * Array of pairs giving the offset and type information for each
234 * member in an aggregate.
236 struct OffsetTypeInfo
238 size_t offset; /// Offset of member from start of object
239 TypeInfo ti; /// TypeInfo for this member
243 * Runtime type information about a type.
244 * Can be retrieved for any type using a
245 * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
249 override hash_t toHash()
253 foreach (char c; this.toString())
258 override int opCmp(Object o)
262 TypeInfo ti = cast(TypeInfo)o;
265 return dstrcmp(this.toString(), ti.toString());
268 override equals_t opEquals(Object o)
270 /* TypeInfo instances are singletons, but duplicates can exist
271 * across DLL's. Therefore, comparing for a name match is
276 TypeInfo ti = cast(TypeInfo)o;
277 return ti && this.toString() == ti.toString();
280 /// Returns a hash of the instance of a type.
281 hash_t getHash(in void* p) { return cast(hash_t)p; }
283 /// Compares two instances for equality.
284 equals_t equals(in void* p1, in void* p2) { return p1 == p2; }
286 /// Compares two instances for <, ==, or >.
287 int compare(in void* p1, in void* p2) { return 0; }
289 /// Returns size of the type.
290 size_t tsize() { return 0; }
292 /// Swaps two instances of the type.
293 void swap(void* p1, void* p2)
296 for (size_t i = 0; i < n; i++)
298 byte t = (cast(byte *)p1)[i];
299 (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
300 (cast(byte*)p2)[i] = t;
304 /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
306 TypeInfo next() { return null; }
308 /// Return default initializer, null if default initialize to 0
309 void[] init() { return null; }
311 /// Get flags for type: 1 means GC should scan for pointers
312 uint flags() { return 0; }
314 /// Get type information on the contents of the type; null if not available
315 OffsetTypeInfo[] offTi() { return null; }
316 /// Run the destructor on the object and all its sub-objects
317 void destroy(void* p) {}
318 /// Run the postblit on the object and all its sub-objects
319 void postblit(void* p) {}
322 class TypeInfo_Typedef : TypeInfo
324 override string toString() { return name; }
326 override equals_t opEquals(Object o)
330 ((c = cast(TypeInfo_Typedef)o) !is null &&
331 this.name == c.name &&
332 this.base == c.base);
335 override hash_t getHash(in void* p) { return base.getHash(p); }
336 override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); }
337 override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); }
338 override size_t tsize() { return base.tsize(); }
339 override void swap(void* p1, void* p2) { return base.swap(p1, p2); }
341 override TypeInfo next() { return base.next(); }
342 override uint flags() { return base.flags(); }
343 override void[] init() { return m_init.length ? m_init : base.init(); }
350 class TypeInfo_Enum : TypeInfo_Typedef
355 class TypeInfo_Pointer : TypeInfo
357 override string toString() { return m_next.toString() ~ "*"; }
359 override equals_t opEquals(Object o)
363 ((c = cast(TypeInfo_Pointer)o) !is null &&
364 this.m_next == c.m_next);
367 override hash_t getHash(in void* p)
369 return cast(hash_t)*cast(void**)p;
372 override equals_t equals(in void* p1, in void* p2)
374 return *cast(void**)p1 == *cast(void**)p2;
377 override int compare(in void* p1, in void* p2)
379 if (*cast(void**)p1 < *cast(void**)p2)
381 else if (*cast(void**)p1 > *cast(void**)p2)
387 override size_t tsize()
389 return (void*).sizeof;
392 override void swap(void* p1, void* p2)
394 void* tmp = *cast(void**)p1;
395 *cast(void**)p1 = *cast(void**)p2;
396 *cast(void**)p2 = tmp;
399 override TypeInfo next() { return m_next; }
400 override uint flags() { return 1; }
405 class TypeInfo_Array : TypeInfo
407 override string toString() { return value.toString() ~ "[]"; }
409 override equals_t opEquals(Object o)
413 ((c = cast(TypeInfo_Array)o) !is null &&
414 this.value == c.value);
417 override hash_t getHash(in void* p)
419 size_t sz = value.tsize();
421 void[] a = *cast(void[]*)p;
422 for (size_t i = 0; i < a.length; i++)
423 hash += value.getHash(a.ptr + i * sz);
427 override equals_t equals(in void* p1, in void* p2)
429 void[] a1 = *cast(void[]*)p1;
430 void[] a2 = *cast(void[]*)p2;
431 if (a1.length != a2.length)
433 size_t sz = value.tsize();
434 for (size_t i = 0; i < a1.length; i++)
436 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
442 override int compare(in void* p1, in void* p2)
444 void[] a1 = *cast(void[]*)p1;
445 void[] a2 = *cast(void[]*)p2;
446 size_t sz = value.tsize();
447 size_t len = a1.length;
451 for (size_t u = 0; u < len; u++)
453 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
457 return cast(int)a1.length - cast(int)a2.length;
460 override size_t tsize()
462 return (void[]).sizeof;
465 override void swap(void* p1, void* p2)
467 void[] tmp = *cast(void[]*)p1;
468 *cast(void[]*)p1 = *cast(void[]*)p2;
469 *cast(void[]*)p2 = tmp;
474 override TypeInfo next()
479 override uint flags() { return 1; }
482 class TypeInfo_StaticArray : TypeInfo
484 override string toString()
487 return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]");
490 override equals_t opEquals(Object o)
492 TypeInfo_StaticArray c;
494 ((c = cast(TypeInfo_StaticArray)o) !is null &&
496 this.value == c.value);
499 override hash_t getHash(in void* p)
501 size_t sz = value.tsize();
503 for (size_t i = 0; i < len; i++)
504 hash += value.getHash(p + i * sz);
508 override equals_t equals(in void* p1, in void* p2)
510 size_t sz = value.tsize();
512 for (size_t u = 0; u < len; u++)
514 if (!value.equals(p1 + u * sz, p2 + u * sz))
520 override int compare(in void* p1, in void* p2)
522 size_t sz = value.tsize();
524 for (size_t u = 0; u < len; u++)
526 int result = value.compare(p1 + u * sz, p2 + u * sz);
533 override size_t tsize()
535 return len * value.tsize();
538 override void swap(void* p1, void* p2)
541 size_t sz = value.tsize();
545 if (sz < buffer.sizeof)
548 tmp = pbuffer = (new void[sz]).ptr;
550 for (size_t u = 0; u < len; u += sz)
552 memcpy(tmp, p1 + o, sz);
553 memcpy(p1 + o, p2 + o, sz);
554 memcpy(p2 + o, tmp, sz);
560 override void[] init() { return value.init(); }
561 override TypeInfo next() { return value; }
562 override uint flags() { return value.flags(); }
564 override void destroy(void* p)
566 auto sz = value.tsize();
568 foreach (i; 0 .. len)
575 override void postblit(void* p)
577 auto sz = value.tsize();
578 foreach (i; 0 .. len)
589 class TypeInfo_AssociativeArray : TypeInfo
591 override string toString()
593 return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]");
596 override equals_t opEquals(Object o)
598 TypeInfo_AssociativeArray c;
600 ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
602 this.value == c.value);
605 // BUG: need to add the rest of the functions
607 override size_t tsize()
609 return (char[int]).sizeof;
612 override TypeInfo next() { return value; }
613 override uint flags() { return 1; }
619 class TypeInfo_Function : TypeInfo
621 override string toString()
623 return cast(string)(next.toString() ~ "()");
626 override equals_t opEquals(Object o)
630 ((c = cast(TypeInfo_Function)o) !is null &&
631 this.next == c.next);
634 // BUG: need to add the rest of the functions
636 override size_t tsize()
638 return 0; // no size for functions
644 class TypeInfo_Delegate : TypeInfo
646 override string toString()
648 return cast(string)(next.toString() ~ " delegate()");
651 override equals_t opEquals(Object o)
655 ((c = cast(TypeInfo_Delegate)o) !is null &&
656 this.next == c.next);
659 // BUG: need to add the rest of the functions
661 override size_t tsize()
663 alias int delegate() dg;
667 override uint flags() { return 1; }
672 class TypeInfo_Class : TypeInfo
674 override string toString() { return info.name; }
676 override equals_t opEquals(Object o)
680 ((c = cast(TypeInfo_Class)o) !is null &&
681 this.info.name == c.classinfo.name);
684 override hash_t getHash(in void* p)
686 Object o = *cast(Object*)p;
687 return o ? o.toHash() : 0;
690 override equals_t equals(in void* p1, in void* p2)
692 Object o1 = *cast(Object*)p1;
693 Object o2 = *cast(Object*)p2;
695 return (o1 is o2) || (o1 && o1.opEquals(o2));
698 override int compare(in void* p1, in void* p2)
700 Object o1 = *cast(Object*)p1;
701 Object o2 = *cast(Object*)p2;
704 // Regard null references as always being "less than"
720 override size_t tsize()
722 return Object.sizeof;
725 override uint flags() { return 1; }
727 override OffsetTypeInfo[] offTi()
729 return (info.flags & 4) ? info.offTi : null;
735 class TypeInfo_Interface : TypeInfo
737 override string toString() { return info.name; }
739 override equals_t opEquals(Object o)
741 TypeInfo_Interface c;
743 ((c = cast(TypeInfo_Interface)o) !is null &&
744 this.info.name == c.classinfo.name);
747 override hash_t getHash(in void* p)
749 Interface* pi = **cast(Interface ***)*cast(void**)p;
750 Object o = cast(Object)(*cast(void**)p - pi.offset);
755 override equals_t equals(in void* p1, in void* p2)
757 Interface* pi = **cast(Interface ***)*cast(void**)p1;
758 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
759 pi = **cast(Interface ***)*cast(void**)p2;
760 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
762 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
765 override int compare(in void* p1, in void* p2)
767 Interface* pi = **cast(Interface ***)*cast(void**)p1;
768 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
769 pi = **cast(Interface ***)*cast(void**)p2;
770 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
773 // Regard null references as always being "less than"
789 override size_t tsize()
791 return Object.sizeof;
794 override uint flags() { return 1; }
799 class TypeInfo_Struct : TypeInfo
801 override string toString() { return name; }
803 override equals_t opEquals(Object o)
807 ((s = cast(TypeInfo_Struct)o) !is null &&
808 this.name == s.name &&
809 this.init.length == s.init.length);
812 override hash_t getHash(in void* p)
817 debug(PRINTF) printf("getHash() using xtoHash\n");
818 return (*xtoHash)(p);
823 debug(PRINTF) printf("getHash() using default hash\n");
824 // A sorry hash algorithm.
825 // Should use the one for strings.
826 // BUG: relies on the GC not moving objects
827 auto q = cast(const(ubyte)*)p;
828 for (size_t i = 0; i < init.length; i++)
837 override equals_t equals(in void* p1, in void* p2)
844 return (*xopEquals)(p1, p2);
846 // BUG: relies on the GC not moving objects
847 return memcmp(p1, p2, init.length) == 0;
850 override int compare(in void* p1, in void* p2)
852 // Regard null references as always being "less than"
860 return (*xopCmp)(p2, p1);
862 // BUG: relies on the GC not moving objects
863 return memcmp(p1, p2, init.length);
871 override size_t tsize()
876 override void[] init() { return m_init; }
878 override uint flags() { return m_flags; }
880 override void destroy(void* p)
886 override void postblit(void* p)
893 void[] m_init; // initializer; init.ptr == null if 0 initialize
895 hash_t function(in void*) xtoHash;
896 equals_t function(in void*, in void*) xopEquals;
897 int function(in void*, in void*) xopCmp;
898 char[] function(in void*) xtoString;
902 const(MemberInfo[]) function(in char[]) xgetMembers;
903 void function(void*) xdtor;
904 void function(void*) xpostblit;
907 class TypeInfo_Tuple : TypeInfo
911 override string toString()
914 foreach (i, element; elements)
918 s ~= element.toString();
924 override equals_t opEquals(Object o)
929 auto t = cast(TypeInfo_Tuple)o;
930 if (t && elements.length == t.elements.length)
932 for (size_t i = 0; i < elements.length; i++)
934 if (elements[i] != t.elements[i])
942 override hash_t getHash(in void* p)
947 override equals_t equals(in void* p1, in void* p2)
952 override int compare(in void* p1, in void* p2)
957 override size_t tsize()
962 override void swap(void* p1, void* p2)
967 override void destroy(void* p)
972 override void postblit(void* p)
978 class TypeInfo_Const : TypeInfo
980 override string toString()
982 return cast(string) ("const(" ~ base.toString() ~ ")");
985 override equals_t opEquals(Object o) { return base.opEquals(o); }
986 override hash_t getHash(in void *p) { return base.getHash(p); }
987 override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); }
988 override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); }
989 override size_t tsize() { return base.tsize(); }
990 override void swap(void *p1, void *p2) { return base.swap(p1, p2); }
992 override TypeInfo next() { return base.next(); }
993 override uint flags() { return base.flags(); }
994 override void[] init() { return base.init(); }
999 class TypeInfo_Invariant : TypeInfo_Const
1001 override string toString()
1003 return cast(string) ("invariant(" ~ base.toString() ~ ")");
1007 abstract class MemberInfo
1012 class MemberInfo_field : MemberInfo
1014 this(string name, TypeInfo ti, size_t offset)
1021 override string name() { return m_name; }
1022 TypeInfo typeInfo() { return m_typeinfo; }
1023 size_t offset() { return m_offset; }
1026 TypeInfo m_typeinfo;
1030 class MemberInfo_function : MemberInfo
1032 this(string name, TypeInfo ti, void* fp, uint flags)
1040 override string name() { return m_name; }
1041 TypeInfo typeInfo() { return m_typeinfo; }
1042 void* fp() { return m_fp; }
1043 uint flags() { return m_flags; }
1046 TypeInfo m_typeinfo;
1052 ///////////////////////////////////////////////////////////////////////////////
1054 ///////////////////////////////////////////////////////////////////////////////
1057 class Throwable : Object
1061 int opApply(int delegate(inout char[]));
1070 this(string msg, Throwable next = null)
1074 this.info = traceContext();
1077 this(string msg, string file, size_t line, Throwable next = null)
1082 this.info = traceContext();
1085 override string toString()
1090 for (Throwable e = this; e !is null; e = e.next)
1094 buf ~= e.classinfo.name ~ "@" ~ e.file ~ "(" ~ tmp.intToString(e.line) ~ "): " ~ e.msg;
1098 buf ~= e.classinfo.name ~ ": " ~ e.msg;
1102 buf ~= "\n----------------";
1109 return cast(string) buf;
1114 alias Throwable.TraceInfo function(void* ptr = null) TraceHandler;
1115 private TraceHandler traceHandler = null;
1119 * Overrides the default trace hander with a user-supplied version.
1122 * h = The new trace handler. Set to null to use the default handler.
1124 extern (C) void rt_setTraceHandler(TraceHandler h)
1131 * This function will be called when an exception is constructed. The
1132 * user-supplied trace handler will be called if one has been supplied,
1133 * otherwise no trace will be generated.
1136 * ptr = A pointer to the location from which to generate the trace, or null
1137 * if the trace should be generated from within the trace handler
1141 * An object describing the current calling context or null if no handler is
1144 Throwable.TraceInfo traceContext(void* ptr = null)
1146 if (traceHandler is null)
1148 return traceHandler(ptr);
1152 class Exception : Throwable
1154 this(string msg, Throwable next = null)
1159 this(string msg, string file, size_t line, Throwable next = null)
1161 super(msg, file, line, next);
1166 class Error : Throwable
1168 this(string msg, Throwable next = null)
1173 this(string msg, string file, size_t line, Throwable next = null)
1175 super(msg, file, line, next);
1180 ///////////////////////////////////////////////////////////////////////////////
1182 ///////////////////////////////////////////////////////////////////////////////
1187 MIctorstart = 1, // we've started constructing it
1188 MIctordone = 2, // finished construction
1189 MIstandalone = 4, // module ctor does not depend on other module
1190 // ctors being done first
1191 MIhasictor = 8, // has ictor member
1198 ModuleInfo[] importedModules;
1199 ClassInfo[] localClasses;
1202 void function() ctor; // module static constructor (order dependent)
1203 void function() dtor; // module static destructor
1204 void function() unitTest; // module unit tests
1206 void* xgetMembers; // module getMembers() function
1208 void function() ictor; // module static constructor (order independent)
1210 static int opApply(int delegate(inout ModuleInfo) dg)
1214 foreach (m; _moduleinfo_array)
1225 // Windows: this gets initialized by minit.asm
1226 // linux: this gets initialized in _moduleCtor()
1227 extern (C) ModuleInfo[] _moduleinfo_array;
1232 // This linked list is created by a compiler generated function inserted
1233 // into the .ctor list by the compiler.
1234 struct ModuleReference
1236 ModuleReference* next;
1240 extern (C) ModuleReference* _Dmodule_ref; // start of linked list
1243 ModuleInfo[] _moduleinfo_dtors;
1244 uint _moduleinfo_dtors_i;
1246 // Register termination function pointers
1247 extern (C) int _fatexit(void*);
1250 * Initialize the modules.
1253 extern (C) void _moduleCtor()
1255 debug(PRINTF) printf("_moduleCtor()\n");
1259 ModuleReference *mr;
1261 for (mr = _Dmodule_ref; mr; mr = mr.next)
1263 _moduleinfo_array = new ModuleInfo[len];
1265 for (mr = _Dmodule_ref; mr; mr = mr.next)
1266 { _moduleinfo_array[len] = mr.mod;
1273 // Ensure module destructors also get called on program termination
1274 //_fatexit(&_STD_moduleDtor);
1277 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
1278 debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors);
1279 _moduleIndependentCtors();
1280 _moduleCtor2(_moduleinfo_array, 0);
1283 extern (C) void _moduleIndependentCtors()
1285 debug(PRINTF) printf("_moduleIndependentCtors()\n");
1286 foreach (m; _moduleinfo_array)
1288 if (m && m.flags & MIhasictor && m.ictor)
1295 void _moduleCtor2(ModuleInfo[] mi, int skip)
1297 debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
1298 for (uint i = 0; i < mi.length; i++)
1300 ModuleInfo m = mi[i];
1302 debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
1305 debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
1306 if (m.flags & MIctordone)
1308 debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
1310 if (m.ctor || m.dtor)
1312 if (m.flags & MIctorstart)
1313 { if (skip || m.flags & MIstandalone)
1315 throw new Exception("Cyclic dependency in module " ~ m.name);
1318 m.flags |= MIctorstart;
1319 _moduleCtor2(m.importedModules, 0);
1322 m.flags &= ~MIctorstart;
1323 m.flags |= MIctordone;
1325 // Now that construction is done, register the destructor
1326 //printf("\tadding module dtor x%x\n", m);
1327 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
1328 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
1332 m.flags |= MIctordone;
1333 _moduleCtor2(m.importedModules, 1);
1339 * Destruct the modules.
1342 // Starting the name with "_STD" means under linux a pointer to the
1343 // function gets put in the .dtors segment.
1345 extern (C) void _moduleDtor()
1347 debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
1349 for (uint i = _moduleinfo_dtors_i; i-- != 0;)
1351 ModuleInfo m = _moduleinfo_dtors[i];
1353 debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
1359 debug(PRINTF) printf("_moduleDtor() done\n");
1362 ///////////////////////////////////////////////////////////////////////////////
1364 ///////////////////////////////////////////////////////////////////////////////
1366 alias Object.Monitor IMonitor;
1367 alias void delegate(Object) DEvent;
1369 // NOTE: The dtor callback feature is only supported for monitors that are not
1370 // supplied by the user. The assumption is that any object with a user-
1371 // supplied monitor may have special storage or lifetime requirements and
1372 // that as a result, storing references to local objects within Monitor
1373 // may not be safe or desirable. Thus, devt is only valid if impl is
1383 Monitor* getMonitor(Object h)
1385 return cast(Monitor*) (cast(void**) h)[1];
1388 void setMonitor(Object h, Monitor* m)
1390 (cast(void**) h)[1] = m;
1393 extern (C) void _d_monitor_create(Object);
1394 extern (C) void _d_monitor_destroy(Object);
1395 extern (C) void _d_monitor_lock(Object);
1396 extern (C) int _d_monitor_unlock(Object);
1398 extern (C) void _d_monitordelete(Object h, bool det)
1400 Monitor* m = getMonitor(h);
1404 IMonitor i = m.impl;
1407 _d_monitor_devt(m, h);
1408 _d_monitor_destroy(h);
1409 setMonitor(h, null);
1412 if (det && (cast(void*) i) !is (cast(void*) h))
1414 setMonitor(h, null);
1418 extern (C) void _d_monitorenter(Object h)
1420 Monitor* m = getMonitor(h);
1424 _d_monitor_create(h);
1428 IMonitor i = m.impl;
1438 extern (C) void _d_monitorexit(Object h)
1440 Monitor* m = getMonitor(h);
1441 IMonitor i = m.impl;
1445 _d_monitor_unlock(h);
1451 extern (C) void _d_monitor_devt(Monitor* m, Object h)
1471 extern (C) void rt_attachDisposeEvent(Object h, DEvent e)
1475 Monitor* m = getMonitor(h);
1476 assert(m.impl is null);
1478 foreach (inout v; m.devt)
1480 if (v is null || v == e)
1487 auto len = m.devt.length + 4; // grow by 4 elements
1488 auto pos = m.devt.length; // insert position
1489 auto p = realloc(m.devt.ptr, DEvent.sizeof * len);
1491 onOutOfMemoryError();
1492 m.devt = (cast(DEvent*)p)[0 .. len];
1493 m.devt[pos+1 .. len] = null;
1498 extern (C) void rt_detachDisposeEvent(Object h, DEvent e)
1502 Monitor* m = getMonitor(h);
1503 assert(m.impl is null);
1505 foreach (p, v; m.devt)
1511 (m.devt.length - p - 1) * DEvent.sizeof);
1512 m.devt[$ - 1] = null;