132
|
1 /**
|
|
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.
|
|
5 *
|
|
6 * This module is implicitly imported.
|
|
7 * Macros:
|
|
8 * WIKI = Object
|
|
9 */
|
|
10
|
|
11 /*
|
|
12 * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
|
|
13 * Written by Walter Bright
|
|
14 *
|
|
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.
|
|
18 *
|
|
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
|
|
22 * restrictions:
|
|
23 *
|
|
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
|
|
31 * distribution.
|
|
32 */
|
|
33
|
|
34 /*
|
|
35 * Modified by Sean Kelly <sean@f4.ca> for use with Tango.
|
|
36 */
|
|
37
|
|
38 module object;
|
|
39
|
|
40 private
|
|
41 {
|
|
42 import tango.stdc.string; // : memcmp, memcpy;
|
|
43 import tango.stdc.stdlib; // : calloc, realloc, free;
|
|
44 import util.string;
|
|
45 debug(PRINTF) import tango.stdc.stdio; // : printf;
|
|
46
|
|
47 extern (C) void onOutOfMemoryError();
|
|
48 extern (C) Object _d_newclass(ClassInfo ci);
|
|
49 }
|
|
50
|
|
51 // NOTE: For some reason, this declaration method doesn't work
|
|
52 // in this particular file (and this file only). It must
|
|
53 // be a DMD thing.
|
|
54 //alias typeof(int.sizeof) size_t;
|
|
55 //alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t;
|
|
56
|
|
57 version( X86_64 )
|
|
58 {
|
|
59 alias ulong size_t;
|
|
60 alias long ptrdiff_t;
|
|
61 }
|
|
62 else
|
|
63 {
|
|
64 alias uint size_t;
|
|
65 alias int ptrdiff_t;
|
|
66 }
|
|
67
|
|
68 alias size_t hash_t;
|
|
69
|
|
70 /**
|
|
71 * All D class objects inherit from Object.
|
|
72 */
|
|
73 class Object
|
|
74 {
|
|
75 /**
|
|
76 * Convert Object to a human readable string.
|
|
77 */
|
|
78 char[] toString()
|
|
79 {
|
|
80 return this.classinfo.name;
|
|
81 }
|
|
82
|
|
83 /**
|
|
84 * Compute hash function for Object.
|
|
85 */
|
|
86 hash_t toHash()
|
|
87 {
|
|
88 // BUG: this prevents a compacting GC from working, needs to be fixed
|
|
89 return cast(hash_t)cast(void*)this;
|
|
90 }
|
|
91
|
|
92 /**
|
|
93 * Compare with another Object obj.
|
|
94 * Returns:
|
|
95 * $(TABLE
|
|
96 * $(TR $(TD this < obj) $(TD < 0))
|
|
97 * $(TR $(TD this == obj) $(TD 0))
|
|
98 * $(TR $(TD this > obj) $(TD > 0))
|
|
99 * )
|
|
100 */
|
|
101 int opCmp(Object o)
|
|
102 {
|
|
103 // BUG: this prevents a compacting GC from working, needs to be fixed
|
|
104 //return cast(int)cast(void*)this - cast(int)cast(void*)o;
|
|
105
|
|
106 //throw new Exception("need opCmp for class " ~ this.classinfo.name);
|
|
107 return this !is o;
|
|
108 }
|
|
109
|
|
110 /**
|
|
111 * Returns !=0 if this object does have the same contents as obj.
|
|
112 */
|
|
113 int opEquals(Object o)
|
|
114 {
|
|
115 return cast(int)(this is o);
|
|
116 }
|
|
117
|
|
118 interface Monitor
|
|
119 {
|
|
120 void lock();
|
|
121 void unlock();
|
|
122 }
|
|
123 }
|
|
124
|
|
125 /**
|
|
126 * Information about an interface.
|
|
127 * A pointer to this appears as the first entry in the interface's vtbl[].
|
|
128 */
|
|
129 struct Interface
|
|
130 {
|
|
131 ClassInfo classinfo; /// .classinfo for this interface (not for containing class)
|
|
132 void*[] vtbl;
|
|
133 ptrdiff_t offset; /// offset to Interface 'this' from Object 'this'
|
|
134 }
|
|
135
|
|
136 /**
|
|
137 * Runtime type information about a class. Can be retrieved for any class type
|
|
138 * or instance by using the .classinfo property.
|
|
139 * A pointer to this appears as the first entry in the class's vtbl[].
|
|
140 */
|
|
141 class ClassInfo : Object
|
|
142 {
|
|
143 byte[] init; /** class static initializer
|
|
144 * (init.length gives size in bytes of class)
|
|
145 */
|
|
146 char[] name; /// class name
|
|
147 void*[] vtbl; /// virtual function pointer table
|
|
148 Interface[] interfaces; /// interfaces this class implements
|
|
149 ClassInfo base; /// base class
|
|
150 void* destructor;
|
|
151 void function(Object) classInvariant;
|
|
152 uint flags;
|
|
153 // 1: // IUnknown
|
|
154 // 2: // has no possible pointers into GC memory
|
|
155 // 4: // has offTi[] member
|
|
156 // 8: // has constructors
|
|
157 void* deallocator;
|
|
158 OffsetTypeInfo[] offTi;
|
|
159 void function(Object) defaultConstructor; // default Constructor
|
|
160
|
|
161 /**
|
|
162 * Search all modules for ClassInfo corresponding to classname.
|
|
163 * Returns: null if not found
|
|
164 */
|
|
165 static ClassInfo find(char[] classname)
|
|
166 {
|
|
167 foreach (m; ModuleInfo)
|
|
168 {
|
|
169 //writefln("module %s, %d", m.name, m.localClasses.length);
|
|
170 foreach (c; m.localClasses)
|
|
171 {
|
|
172 //writefln("\tclass %s", c.name);
|
|
173 if (c.name == classname)
|
|
174 return c;
|
|
175 }
|
|
176 }
|
|
177 return null;
|
|
178 }
|
|
179
|
|
180 /**
|
|
181 * Create instance of Object represented by 'this'.
|
|
182 */
|
|
183 Object create()
|
|
184 {
|
|
185 if (flags & 8 && !defaultConstructor)
|
|
186 return null;
|
|
187 Object o = _d_newclass(this);
|
|
188 if (flags & 8 && defaultConstructor)
|
|
189 {
|
|
190 defaultConstructor(o);
|
|
191 }
|
|
192 return o;
|
|
193 }
|
|
194 }
|
|
195
|
|
196 /**
|
|
197 * Array of pairs giving the offset and type information for each
|
|
198 * member in an aggregate.
|
|
199 */
|
|
200 struct OffsetTypeInfo
|
|
201 {
|
|
202 size_t offset; /// Offset of member from start of object
|
|
203 TypeInfo ti; /// TypeInfo for this member
|
|
204 }
|
|
205
|
|
206 /**
|
|
207 * Runtime type information about a type.
|
|
208 * Can be retrieved for any type using a
|
|
209 * <a href="../expression.html#typeidexpression">TypeidExpression</a>.
|
|
210 */
|
|
211 class TypeInfo
|
|
212 {
|
|
213 hash_t toHash()
|
|
214 { hash_t hash;
|
|
215
|
|
216 foreach (char c; this.toString())
|
|
217 hash = hash * 9 + c;
|
|
218 return hash;
|
|
219 }
|
|
220
|
|
221 int opCmp(Object o)
|
|
222 {
|
|
223 if (this is o)
|
|
224 return 0;
|
|
225 TypeInfo ti = cast(TypeInfo)o;
|
|
226 if (ti is null)
|
|
227 return 1;
|
|
228 return stringCompare(this.toString(), ti.toString());
|
|
229 }
|
|
230
|
|
231 int opEquals(Object o)
|
|
232 {
|
|
233 /* TypeInfo instances are singletons, but duplicates can exist
|
|
234 * across DLL's. Therefore, comparing for a name match is
|
|
235 * sufficient.
|
|
236 */
|
|
237 if (this is o)
|
|
238 return 1;
|
|
239 TypeInfo ti = cast(TypeInfo)o;
|
|
240 return cast(int)(ti && this.toString() == ti.toString());
|
|
241 }
|
|
242
|
|
243 /// Returns a hash of the instance of a type.
|
|
244 hash_t getHash(void *p) { return cast(hash_t)p; }
|
|
245
|
|
246 /// Compares two instances for equality.
|
|
247 int equals(void *p1, void *p2) { return cast(int)(p1 == p2); }
|
|
248
|
|
249 /// Compares two instances for <, ==, or >.
|
|
250 int compare(void *p1, void *p2) { return 0; }
|
|
251
|
|
252 /// Returns size of the type.
|
|
253 size_t tsize() { return 0; }
|
|
254
|
|
255 /// Swaps two instances of the type.
|
|
256 void swap(void *p1, void *p2)
|
|
257 {
|
|
258 size_t n = tsize();
|
|
259 for (size_t i = 0; i < n; i++)
|
|
260 { byte t;
|
|
261
|
|
262 t = (cast(byte *)p1)[i];
|
|
263 (cast(byte *)p1)[i] = (cast(byte *)p2)[i];
|
|
264 (cast(byte *)p2)[i] = t;
|
|
265 }
|
|
266 }
|
|
267
|
|
268 /// Get TypeInfo for 'next' type, as defined by what kind of type this is,
|
|
269 /// null if none.
|
|
270 TypeInfo next() { return null; }
|
|
271
|
|
272 /// Return default initializer, null if default initialize to 0
|
|
273 void[] init() { return null; }
|
|
274
|
|
275 /// Get flags for type: 1 means GC should scan for pointers
|
|
276 uint flags() { return 0; }
|
|
277
|
|
278 /// Get type information on the contents of the type; null if not available
|
|
279 OffsetTypeInfo[] offTi() { return null; }
|
|
280 }
|
|
281
|
|
282 class TypeInfo_Typedef : TypeInfo
|
|
283 {
|
|
284 char[] toString() { return name; }
|
|
285
|
|
286 int opEquals(Object o)
|
|
287 { TypeInfo_Typedef c;
|
|
288
|
|
289 return cast(int)
|
|
290 (this is o ||
|
|
291 ((c = cast(TypeInfo_Typedef)o) !is null &&
|
|
292 this.name == c.name &&
|
|
293 this.base == c.base));
|
|
294 }
|
|
295
|
|
296 hash_t getHash(void *p) { return base.getHash(p); }
|
|
297 int equals(void *p1, void *p2) { return base.equals(p1, p2); }
|
|
298 int compare(void *p1, void *p2) { return base.compare(p1, p2); }
|
|
299 size_t tsize() { return base.tsize(); }
|
|
300 void swap(void *p1, void *p2) { return base.swap(p1, p2); }
|
|
301
|
|
302 TypeInfo next() { return base.next(); }
|
|
303 uint flags() { return base.flags(); }
|
|
304 void[] init() { return m_init.length ? m_init : base.init(); }
|
|
305
|
|
306 TypeInfo base;
|
|
307 char[] name;
|
|
308 void[] m_init;
|
|
309 }
|
|
310
|
|
311 class TypeInfo_Enum : TypeInfo_Typedef
|
|
312 {
|
|
313 }
|
|
314
|
|
315 class TypeInfo_Pointer : TypeInfo
|
|
316 {
|
|
317 char[] toString() { return m_next.toString() ~ "*"; }
|
|
318
|
|
319 int opEquals(Object o)
|
|
320 { TypeInfo_Pointer c;
|
|
321
|
|
322 return this is o ||
|
|
323 ((c = cast(TypeInfo_Pointer)o) !is null &&
|
|
324 this.m_next == c.m_next);
|
|
325 }
|
|
326
|
|
327 hash_t getHash(void *p)
|
|
328 {
|
|
329 return cast(hash_t)*cast(void**)p;
|
|
330 }
|
|
331
|
|
332 int equals(void *p1, void *p2)
|
|
333 {
|
|
334 return cast(int)(*cast(void* *)p1 == *cast(void* *)p2);
|
|
335 }
|
|
336
|
|
337 int compare(void *p1, void *p2)
|
|
338 {
|
|
339 if (*cast(void* *)p1 < *cast(void* *)p2)
|
|
340 return -1;
|
|
341 else if (*cast(void* *)p1 > *cast(void* *)p2)
|
|
342 return 1;
|
|
343 else
|
|
344 return 0;
|
|
345 }
|
|
346
|
|
347 size_t tsize()
|
|
348 {
|
|
349 return (void*).sizeof;
|
|
350 }
|
|
351
|
|
352 void swap(void *p1, void *p2)
|
|
353 { void* tmp;
|
|
354 tmp = *cast(void**)p1;
|
|
355 *cast(void**)p1 = *cast(void**)p2;
|
|
356 *cast(void**)p2 = tmp;
|
|
357 }
|
|
358
|
|
359 TypeInfo next() { return m_next; }
|
|
360 uint flags() { return 1; }
|
|
361
|
|
362 TypeInfo m_next;
|
|
363 }
|
|
364
|
|
365 class TypeInfo_Array : TypeInfo
|
|
366 {
|
|
367 char[] toString() { return value.toString() ~ "[]"; }
|
|
368
|
|
369 int opEquals(Object o)
|
|
370 { TypeInfo_Array c;
|
|
371
|
|
372 return cast(int)
|
|
373 (this is o ||
|
|
374 ((c = cast(TypeInfo_Array)o) !is null &&
|
|
375 this.value == c.value));
|
|
376 }
|
|
377
|
|
378 hash_t getHash(void *p)
|
|
379 { size_t sz = value.tsize();
|
|
380 hash_t hash = 0;
|
|
381 void[] a = *cast(void[]*)p;
|
|
382 for (size_t i = 0; i < a.length; i++)
|
|
383 hash += value.getHash(a.ptr + i * sz);
|
|
384 return hash;
|
|
385 }
|
|
386
|
|
387 int equals(void *p1, void *p2)
|
|
388 {
|
|
389 void[] a1 = *cast(void[]*)p1;
|
|
390 void[] a2 = *cast(void[]*)p2;
|
|
391 if (a1.length != a2.length)
|
|
392 return 0;
|
|
393 size_t sz = value.tsize();
|
|
394 for (size_t i = 0; i < a1.length; i++)
|
|
395 {
|
|
396 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
|
|
397 return 0;
|
|
398 }
|
|
399 return 1;
|
|
400 }
|
|
401
|
|
402 int compare(void *p1, void *p2)
|
|
403 {
|
|
404 void[] a1 = *cast(void[]*)p1;
|
|
405 void[] a2 = *cast(void[]*)p2;
|
|
406 size_t sz = value.tsize();
|
|
407 size_t len = a1.length;
|
|
408
|
|
409 if (a2.length < len)
|
|
410 len = a2.length;
|
|
411 for (size_t u = 0; u < len; u++)
|
|
412 {
|
|
413 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
|
|
414 if (result)
|
|
415 return result;
|
|
416 }
|
|
417 return cast(int)a1.length - cast(int)a2.length;
|
|
418 }
|
|
419
|
|
420 size_t tsize()
|
|
421 {
|
|
422 return (void[]).sizeof;
|
|
423 }
|
|
424
|
|
425 void swap(void *p1, void *p2)
|
|
426 { void[] tmp;
|
|
427 tmp = *cast(void[]*)p1;
|
|
428 *cast(void[]*)p1 = *cast(void[]*)p2;
|
|
429 *cast(void[]*)p2 = tmp;
|
|
430 }
|
|
431
|
|
432 TypeInfo value;
|
|
433
|
|
434 TypeInfo next()
|
|
435 {
|
|
436 return value;
|
|
437 }
|
|
438
|
|
439 uint flags() { return 1; }
|
|
440 }
|
|
441
|
|
442 class TypeInfo_StaticArray : TypeInfo
|
|
443 {
|
|
444 char[] toString()
|
|
445 {
|
|
446 char [10] tmp = void;
|
|
447 return value.toString() ~ "[" ~ intToUtf8(tmp, len) ~ "]";
|
|
448 }
|
|
449
|
|
450 int opEquals(Object o)
|
|
451 { TypeInfo_StaticArray c;
|
|
452
|
|
453 return cast(int)
|
|
454 (this is o ||
|
|
455 ((c = cast(TypeInfo_StaticArray)o) !is null &&
|
|
456 this.len == c.len &&
|
|
457 this.value == c.value));
|
|
458 }
|
|
459
|
|
460 hash_t getHash(void *p)
|
|
461 { size_t sz = value.tsize();
|
|
462 hash_t hash = 0;
|
|
463 for (size_t i = 0; i < len; i++)
|
|
464 hash += value.getHash(p + i * sz);
|
|
465 return hash;
|
|
466 }
|
|
467
|
|
468 int equals(void *p1, void *p2)
|
|
469 {
|
|
470 size_t sz = value.tsize();
|
|
471
|
|
472 for (size_t u = 0; u < len; u++)
|
|
473 {
|
|
474 if (!value.equals(p1 + u * sz, p2 + u * sz))
|
|
475 return 0;
|
|
476 }
|
|
477 return 1;
|
|
478 }
|
|
479
|
|
480 int compare(void *p1, void *p2)
|
|
481 {
|
|
482 size_t sz = value.tsize();
|
|
483
|
|
484 for (size_t u = 0; u < len; u++)
|
|
485 {
|
|
486 int result = value.compare(p1 + u * sz, p2 + u * sz);
|
|
487 if (result)
|
|
488 return result;
|
|
489 }
|
|
490 return 0;
|
|
491 }
|
|
492
|
|
493 size_t tsize()
|
|
494 {
|
|
495 return len * value.tsize();
|
|
496 }
|
|
497
|
|
498 void swap(void *p1, void *p2)
|
|
499 { void* tmp;
|
|
500 size_t sz = value.tsize();
|
|
501 ubyte[16] buffer;
|
|
502 void* pbuffer;
|
|
503
|
|
504 if (sz < buffer.sizeof)
|
|
505 tmp = buffer.ptr;
|
|
506 else
|
|
507 tmp = pbuffer = (new void[sz]).ptr;
|
|
508
|
|
509 for (size_t u = 0; u < len; u += sz)
|
|
510 { size_t o = u * sz;
|
|
511 memcpy(tmp, p1 + o, sz);
|
|
512 memcpy(p1 + o, p2 + o, sz);
|
|
513 memcpy(p2 + o, tmp, sz);
|
|
514 }
|
|
515 if (pbuffer)
|
|
516 delete pbuffer;
|
|
517 }
|
|
518
|
|
519 void[] init() { return value.init(); }
|
|
520 TypeInfo next() { return value; }
|
|
521 uint flags() { return value.flags(); }
|
|
522
|
|
523 TypeInfo value;
|
|
524 size_t len;
|
|
525 }
|
|
526
|
|
527 class TypeInfo_AssociativeArray : TypeInfo
|
|
528 {
|
|
529 char[] toString()
|
|
530 {
|
|
531 return next.toString() ~ "[" ~ key.toString() ~ "]";
|
|
532 }
|
|
533
|
|
534 int opEquals(Object o)
|
|
535 { TypeInfo_AssociativeArray c;
|
|
536
|
|
537 return this is o ||
|
|
538 ((c = cast(TypeInfo_AssociativeArray)o) !is null &&
|
|
539 this.key == c.key &&
|
|
540 this.value == c.value);
|
|
541 }
|
|
542
|
|
543 // BUG: need to add the rest of the functions
|
|
544
|
|
545 size_t tsize()
|
|
546 {
|
|
547 return (char[int]).sizeof;
|
|
548 }
|
|
549
|
|
550 TypeInfo next() { return value; }
|
|
551 uint flags() { return 1; }
|
|
552
|
|
553 TypeInfo value;
|
|
554 TypeInfo key;
|
|
555 }
|
|
556
|
|
557 class TypeInfo_Function : TypeInfo
|
|
558 {
|
|
559 char[] toString()
|
|
560 {
|
|
561 return next.toString() ~ "()";
|
|
562 }
|
|
563
|
|
564 int opEquals(Object o)
|
|
565 { TypeInfo_Function c;
|
|
566
|
|
567 return this is o ||
|
|
568 ((c = cast(TypeInfo_Function)o) !is null &&
|
|
569 this.next == c.next);
|
|
570 }
|
|
571
|
|
572 // BUG: need to add the rest of the functions
|
|
573
|
|
574 size_t tsize()
|
|
575 {
|
|
576 return 0; // no size for functions
|
|
577 }
|
|
578
|
|
579 TypeInfo next;
|
|
580 }
|
|
581
|
|
582 class TypeInfo_Delegate : TypeInfo
|
|
583 {
|
|
584 char[] toString()
|
|
585 {
|
|
586 return next.toString() ~ " delegate()";
|
|
587 }
|
|
588
|
|
589 int opEquals(Object o)
|
|
590 { TypeInfo_Delegate c;
|
|
591
|
|
592 return this is o ||
|
|
593 ((c = cast(TypeInfo_Delegate)o) !is null &&
|
|
594 this.next == c.next);
|
|
595 }
|
|
596
|
|
597 // BUG: need to add the rest of the functions
|
|
598
|
|
599 size_t tsize()
|
|
600 { alias int delegate() dg;
|
|
601 return dg.sizeof;
|
|
602 }
|
|
603
|
|
604 uint flags() { return 1; }
|
|
605
|
|
606 TypeInfo next;
|
|
607 }
|
|
608
|
|
609 class TypeInfo_Class : TypeInfo
|
|
610 {
|
|
611 char[] toString() { return info.name; }
|
|
612
|
|
613 int opEquals(Object o)
|
|
614 { TypeInfo_Class c;
|
|
615
|
|
616 return this is o ||
|
|
617 ((c = cast(TypeInfo_Class)o) !is null &&
|
|
618 this.info.name == c.classinfo.name);
|
|
619 }
|
|
620
|
|
621 hash_t getHash(void *p)
|
|
622 {
|
|
623 Object o = *cast(Object*)p;
|
|
624 assert(o);
|
|
625 return o.toHash();
|
|
626 }
|
|
627
|
|
628 int equals(void *p1, void *p2)
|
|
629 {
|
|
630 Object o1 = *cast(Object*)p1;
|
|
631 Object o2 = *cast(Object*)p2;
|
|
632
|
|
633 return (o1 is o2) || (o1 && o1.opEquals(o2));
|
|
634 }
|
|
635
|
|
636 int compare(void *p1, void *p2)
|
|
637 {
|
|
638 Object o1 = *cast(Object*)p1;
|
|
639 Object o2 = *cast(Object*)p2;
|
|
640 int c = 0;
|
|
641
|
|
642 // Regard null references as always being "less than"
|
|
643 if (o1 !is o2)
|
|
644 {
|
|
645 if (o1)
|
|
646 { if (!o2)
|
|
647 c = 1;
|
|
648 else
|
|
649 c = o1.opCmp(o2);
|
|
650 }
|
|
651 else
|
|
652 c = -1;
|
|
653 }
|
|
654 return c;
|
|
655 }
|
|
656
|
|
657 size_t tsize()
|
|
658 {
|
|
659 return Object.sizeof;
|
|
660 }
|
|
661
|
|
662 uint flags() { return 1; }
|
|
663
|
|
664 OffsetTypeInfo[] offTi()
|
|
665 {
|
|
666 return (info.flags & 4) ? info.offTi : null;
|
|
667 }
|
|
668
|
|
669 ClassInfo info;
|
|
670 }
|
|
671
|
|
672 class TypeInfo_Interface : TypeInfo
|
|
673 {
|
|
674 char[] toString() { return info.name; }
|
|
675
|
|
676 int opEquals(Object o)
|
|
677 { TypeInfo_Interface c;
|
|
678
|
|
679 return this is o ||
|
|
680 ((c = cast(TypeInfo_Interface)o) !is null &&
|
|
681 this.info.name == c.classinfo.name);
|
|
682 }
|
|
683
|
|
684 hash_t getHash(void *p)
|
|
685 {
|
|
686 Interface* pi = **cast(Interface ***)*cast(void**)p;
|
|
687 Object o = cast(Object)(*cast(void**)p - pi.offset);
|
|
688 assert(o);
|
|
689 return o.toHash();
|
|
690 }
|
|
691
|
|
692 int equals(void *p1, void *p2)
|
|
693 {
|
|
694 Interface* pi = **cast(Interface ***)*cast(void**)p1;
|
|
695 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
|
|
696 pi = **cast(Interface ***)*cast(void**)p2;
|
|
697 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
|
|
698
|
|
699 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
|
|
700 }
|
|
701
|
|
702 int compare(void *p1, void *p2)
|
|
703 {
|
|
704 Interface* pi = **cast(Interface ***)*cast(void**)p1;
|
|
705 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
|
|
706 pi = **cast(Interface ***)*cast(void**)p2;
|
|
707 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
|
|
708 int c = 0;
|
|
709
|
|
710 // Regard null references as always being "less than"
|
|
711 if (o1 != o2)
|
|
712 {
|
|
713 if (o1)
|
|
714 { if (!o2)
|
|
715 c = 1;
|
|
716 else
|
|
717 c = o1.opCmp(o2);
|
|
718 }
|
|
719 else
|
|
720 c = -1;
|
|
721 }
|
|
722 return c;
|
|
723 }
|
|
724
|
|
725 size_t tsize()
|
|
726 {
|
|
727 return Object.sizeof;
|
|
728 }
|
|
729
|
|
730 uint flags() { return 1; }
|
|
731
|
|
732 ClassInfo info;
|
|
733 }
|
|
734
|
|
735 class TypeInfo_Struct : TypeInfo
|
|
736 {
|
|
737 char[] toString() { return name; }
|
|
738
|
|
739 int opEquals(Object o)
|
|
740 { TypeInfo_Struct s;
|
|
741
|
|
742 return this is o ||
|
|
743 ((s = cast(TypeInfo_Struct)o) !is null &&
|
|
744 this.name == s.name &&
|
|
745 this.init.length == s.init.length);
|
|
746 }
|
|
747
|
|
748 hash_t getHash(void *p)
|
|
749 { hash_t h;
|
|
750
|
|
751 assert(p);
|
|
752 if (xtoHash)
|
|
753 { debug(PRINTF) printf("getHash() using xtoHash\n");
|
|
754 h = (*xtoHash)(p);
|
|
755 }
|
|
756 else
|
|
757 {
|
|
758 debug(PRINTF) printf("getHash() using default hash\n");
|
|
759 // A sorry hash algorithm.
|
|
760 // Should use the one for strings.
|
|
761 // BUG: relies on the GC not moving objects
|
|
762 for (size_t i = 0; i < init.length; i++)
|
|
763 { h = h * 9 + *cast(ubyte*)p;
|
|
764 p++;
|
|
765 }
|
|
766 }
|
|
767 return h;
|
|
768 }
|
|
769
|
|
770 int equals(void *p2, void *p1)
|
|
771 { int c;
|
|
772
|
|
773 if (p1 == p2)
|
|
774 c = 1;
|
|
775 else if (!p1 || !p2)
|
|
776 c = 0;
|
|
777 else if (xopEquals)
|
|
778 c = (*xopEquals)(p1, p2);
|
|
779 else
|
|
780 // BUG: relies on the GC not moving objects
|
|
781 c = (memcmp(p1, p2, init.length) == 0);
|
|
782 return c;
|
|
783 }
|
|
784
|
|
785 int compare(void *p2, void *p1)
|
|
786 {
|
|
787 int c = 0;
|
|
788
|
|
789 // Regard null references as always being "less than"
|
|
790 if (p1 != p2)
|
|
791 {
|
|
792 if (p1)
|
|
793 { if (!p2)
|
|
794 c = 1;
|
|
795 else if (xopCmp)
|
|
796 c = (*xopCmp)(p1, p2);
|
|
797 else
|
|
798 // BUG: relies on the GC not moving objects
|
|
799 c = memcmp(p1, p2, init.length);
|
|
800 }
|
|
801 else
|
|
802 c = -1;
|
|
803 }
|
|
804 return c;
|
|
805 }
|
|
806
|
|
807 size_t tsize()
|
|
808 {
|
|
809 return init.length;
|
|
810 }
|
|
811
|
|
812 void[] init() { return m_init; }
|
|
813
|
|
814 uint flags() { return m_flags; }
|
|
815
|
|
816 char[] name;
|
|
817 void[] m_init; // initializer; init.ptr == null if 0 initialize
|
|
818
|
|
819 hash_t function(void*) xtoHash;
|
|
820 int function(void*,void*) xopEquals;
|
|
821 int function(void*,void*) xopCmp;
|
|
822 char[] function(void*) xtoString;
|
|
823
|
|
824 uint m_flags;
|
|
825 }
|
|
826
|
|
827 class TypeInfo_Tuple : TypeInfo
|
|
828 {
|
|
829 TypeInfo[] elements;
|
|
830
|
|
831 char[] toString()
|
|
832 {
|
|
833 char[] s;
|
|
834 s = "(";
|
|
835 foreach (i, element; elements)
|
|
836 {
|
|
837 if (i)
|
|
838 s ~= ',';
|
|
839 s ~= element.toString();
|
|
840 }
|
|
841 s ~= ")";
|
|
842 return s;
|
|
843 }
|
|
844
|
|
845 int opEquals(Object o)
|
|
846 {
|
|
847 if (this is o)
|
|
848 return 1;
|
|
849
|
|
850 auto t = cast(TypeInfo_Tuple)o;
|
|
851 if (t && elements.length == t.elements.length)
|
|
852 {
|
|
853 for (size_t i = 0; i < elements.length; i++)
|
|
854 {
|
|
855 if (elements[i] != t.elements[i])
|
|
856 return 0;
|
|
857 }
|
|
858 return 1;
|
|
859 }
|
|
860 return 0;
|
|
861 }
|
|
862
|
|
863 hash_t getHash(void *p)
|
|
864 {
|
|
865 assert(0);
|
|
866 }
|
|
867
|
|
868 int equals(void *p1, void *p2)
|
|
869 {
|
|
870 assert(0);
|
|
871 }
|
|
872
|
|
873 int compare(void *p1, void *p2)
|
|
874 {
|
|
875 assert(0);
|
|
876 }
|
|
877
|
|
878 size_t tsize()
|
|
879 {
|
|
880 assert(0);
|
|
881 }
|
|
882
|
|
883 void swap(void *p1, void *p2)
|
|
884 {
|
|
885 assert(0);
|
|
886 }
|
|
887 }
|
|
888
|
|
889 class Exception : Object
|
|
890 {
|
|
891 char[] msg;
|
|
892 char[] file;
|
|
893 size_t line;
|
|
894 Exception next;
|
|
895
|
|
896 this(char[] msg, Exception next = null)
|
|
897 {
|
|
898 this.msg = msg;
|
|
899 this.next = next;
|
|
900 }
|
|
901
|
|
902 this(char[] msg, char[] file, size_t line, Exception next = null)
|
|
903 {
|
|
904 this(msg, next);
|
|
905 this.file = file;
|
|
906 this.line = line;
|
|
907 }
|
|
908
|
|
909 char[] toString()
|
|
910 {
|
|
911 return msg;
|
|
912 }
|
|
913 }
|
|
914
|
|
915
|
|
916 ////////////////////////////////////////////////////////////////////////////////
|
|
917 // ModuleInfo
|
|
918 ////////////////////////////////////////////////////////////////////////////////
|
|
919
|
|
920
|
|
921 enum
|
|
922 {
|
|
923 MIctorstart = 1, // we've started constructing it
|
|
924 MIctordone = 2, // finished construction
|
|
925 MIstandalone = 4, // module ctor does not depend on other module
|
|
926 // ctors being done first
|
|
927 MIhasictor = 8, // has ictor member
|
|
928 }
|
|
929
|
|
930
|
|
931 class ModuleInfo
|
|
932 {
|
|
933 char[] name;
|
|
934 ModuleInfo[] importedModules;
|
|
935 ClassInfo[] localClasses;
|
|
936 uint flags;
|
|
937
|
|
938 void function() ctor; // module static constructor (order dependent)
|
|
939 void function() dtor; // module static destructor
|
|
940 void function() unitTest; // module unit tests
|
|
941
|
|
942 void* xgetMembers; // module getMembers() function
|
|
943
|
|
944 void function() ictor; // module static constructor (order independent)
|
|
945
|
|
946 static int opApply( int delegate( inout ModuleInfo ) dg )
|
|
947 {
|
|
948 int ret = 0;
|
|
949
|
|
950 foreach( m; _moduleinfo_array )
|
|
951 {
|
|
952 ret = dg( m );
|
|
953 if( ret )
|
|
954 break;
|
|
955 }
|
|
956 return ret;
|
|
957 }
|
|
958 }
|
|
959
|
|
960
|
|
961 // Win32: this gets initialized by minit.asm
|
|
962 // linux: this gets initialized in _moduleCtor()
|
|
963 extern (C) ModuleInfo[] _moduleinfo_array;
|
|
964
|
|
965
|
|
966 version (linux)
|
|
967 {
|
|
968 // This linked list is created by a compiler generated function inserted
|
|
969 // into the .ctor list by the compiler.
|
|
970 struct ModuleReference
|
|
971 {
|
|
972 ModuleReference* next;
|
|
973 ModuleInfo mod;
|
|
974 }
|
|
975
|
|
976 extern (C) ModuleReference* _Dmodule_ref; // start of linked list
|
|
977 }
|
|
978
|
|
979 ModuleInfo[] _moduleinfo_dtors;
|
|
980 uint _moduleinfo_dtors_i;
|
|
981
|
|
982 // Register termination function pointers
|
|
983 extern (C) int _fatexit(void *);
|
|
984
|
|
985 /**
|
|
986 * Initialize the modules.
|
|
987 */
|
|
988
|
|
989 extern (C) void _moduleCtor()
|
|
990 {
|
|
991 debug(PRINTF) printf("_moduleCtor()\n");
|
|
992 version (linux)
|
|
993 {
|
|
994 int len = 0;
|
|
995 ModuleReference *mr;
|
|
996
|
|
997 for (mr = _Dmodule_ref; mr; mr = mr.next)
|
|
998 len++;
|
|
999 _moduleinfo_array = new ModuleInfo[len];
|
|
1000 len = 0;
|
|
1001 for (mr = _Dmodule_ref; mr; mr = mr.next)
|
|
1002 { _moduleinfo_array[len] = mr.mod;
|
|
1003 len++;
|
|
1004 }
|
|
1005 }
|
|
1006
|
|
1007 version (Win32)
|
|
1008 {
|
|
1009 // Ensure module destructors also get called on program termination
|
|
1010 //_fatexit(&_STD_moduleDtor);
|
|
1011 }
|
|
1012
|
|
1013 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
|
|
1014 debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
|
|
1015 _moduleIndependentCtors();
|
|
1016 _moduleCtor2(_moduleinfo_array, 0);
|
|
1017 }
|
|
1018
|
|
1019 extern (C) void _moduleIndependentCtors()
|
|
1020 {
|
|
1021 debug(PRINTF) printf("_moduleIndependentCtors()\n");
|
|
1022 foreach (m; _moduleinfo_array)
|
|
1023 {
|
|
1024 if (m && m.flags & MIhasictor && m.ictor)
|
|
1025 {
|
|
1026 (*m.ictor)();
|
|
1027 }
|
|
1028 }
|
|
1029 }
|
|
1030
|
|
1031 void _moduleCtor2(ModuleInfo[] mi, int skip)
|
|
1032 {
|
|
1033 debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length);
|
|
1034 for (uint i = 0; i < mi.length; i++)
|
|
1035 {
|
|
1036 ModuleInfo m = mi[i];
|
|
1037
|
|
1038 debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m);
|
|
1039 if (!m)
|
|
1040 continue;
|
|
1041 debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name);
|
|
1042 if (m.flags & MIctordone)
|
|
1043 continue;
|
|
1044 debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m);
|
|
1045
|
|
1046 if (m.ctor || m.dtor)
|
|
1047 {
|
|
1048 if (m.flags & MIctorstart)
|
|
1049 { if (skip || m.flags & MIstandalone)
|
|
1050 continue;
|
|
1051 throw new Exception( "Cyclic dependency in module " ~ m.name );
|
|
1052 }
|
|
1053
|
|
1054 m.flags |= MIctorstart;
|
|
1055 _moduleCtor2(m.importedModules, 0);
|
|
1056 if (m.ctor)
|
|
1057 (*m.ctor)();
|
|
1058 m.flags &= ~MIctorstart;
|
|
1059 m.flags |= MIctordone;
|
|
1060
|
|
1061 // Now that construction is done, register the destructor
|
|
1062 //printf("\tadding module dtor x%x\n", m);
|
|
1063 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length);
|
|
1064 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m;
|
|
1065 }
|
|
1066 else
|
|
1067 {
|
|
1068 m.flags |= MIctordone;
|
|
1069 _moduleCtor2(m.importedModules, 1);
|
|
1070 }
|
|
1071 }
|
|
1072 }
|
|
1073
|
|
1074 /**
|
|
1075 * Destruct the modules.
|
|
1076 */
|
|
1077
|
|
1078 // Starting the name with "_STD" means under linux a pointer to the
|
|
1079 // function gets put in the .dtors segment.
|
|
1080
|
|
1081 extern (C) void _moduleDtor()
|
|
1082 {
|
|
1083 debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i);
|
|
1084
|
|
1085 for (uint i = _moduleinfo_dtors_i; i-- != 0;)
|
|
1086 {
|
|
1087 ModuleInfo m = _moduleinfo_dtors[i];
|
|
1088
|
|
1089 debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m);
|
|
1090 if (m.dtor)
|
|
1091 {
|
|
1092 (*m.dtor)();
|
|
1093 }
|
|
1094 }
|
|
1095 debug(PRINTF) printf("_moduleDtor() done\n");
|
|
1096 }
|
|
1097
|
|
1098 ////////////////////////////////////////////////////////////////////////////////
|
|
1099 // Monitor
|
|
1100 ////////////////////////////////////////////////////////////////////////////////
|
|
1101
|
|
1102 alias Object.Monitor IMonitor;
|
|
1103
|
|
1104 struct Monitor
|
|
1105 {
|
|
1106 IMonitor impl;
|
|
1107 /* stuff */
|
|
1108 }
|
|
1109
|
|
1110 Monitor* getMonitor(Object h)
|
|
1111 {
|
|
1112 return cast(Monitor*) (cast(void**) h)[1];
|
|
1113 }
|
|
1114
|
|
1115 void setMonitor(Object h, Monitor* m)
|
|
1116 {
|
|
1117 (cast(void**) h)[1] = m;
|
|
1118 }
|
|
1119
|
|
1120 extern (C) void _d_monitor_create(Object);
|
|
1121 extern (C) void _d_monitor_destroy(Object);
|
|
1122 extern (C) void _d_monitor_lock(Object);
|
|
1123 extern (C) int _d_monitor_unlock(Object);
|
|
1124
|
|
1125 extern (C) void _d_monitordelete(Object h, bool det)
|
|
1126 {
|
|
1127 Monitor* m = getMonitor(h);
|
|
1128
|
|
1129 if (m !is null)
|
|
1130 {
|
|
1131 IMonitor i = m.impl;
|
|
1132 if (i is null)
|
|
1133 {
|
|
1134 _d_monitor_destroy(h);
|
|
1135 setMonitor(h, null);
|
|
1136 return;
|
|
1137 }
|
|
1138 if (det && (cast(void*) i) !is (cast(void*) h))
|
|
1139 delete i;
|
|
1140 setMonitor(h, null);
|
|
1141 }
|
|
1142 }
|
|
1143
|
|
1144 extern (C) void _d_monitorenter(Object h)
|
|
1145 {
|
|
1146 Monitor* m = getMonitor(h);
|
|
1147
|
|
1148 if (m is null)
|
|
1149 {
|
|
1150 _d_monitor_create(h);
|
|
1151 m = getMonitor(h);
|
|
1152 }
|
|
1153
|
|
1154 IMonitor i = m.impl;
|
|
1155
|
|
1156 if (i is null)
|
|
1157 {
|
|
1158 _d_monitor_lock(h);
|
|
1159 return;
|
|
1160 }
|
|
1161 i.lock();
|
|
1162 }
|
|
1163
|
|
1164 extern (C) void _d_monitorexit(Object h)
|
|
1165 {
|
|
1166 Monitor* m = getMonitor(h);
|
|
1167 IMonitor i = m.impl;
|
|
1168
|
|
1169 if (i is null)
|
|
1170 {
|
|
1171 _d_monitor_unlock(h);
|
|
1172 return;
|
|
1173 }
|
|
1174 i.unlock();
|
|
1175 }
|