Mercurial > projects > ldc
comparison druntime/src/compiler/ldc/genobj.d @ 1458:e0b2d67cfe7c
Added druntime (this should be removed once it works).
author | Robert Clipsham <robert@octarineparrot.com> |
---|---|
date | Tue, 02 Jun 2009 17:43:06 +0100 |
parents | |
children | a5526b7a5ae6 |
comparison
equal
deleted
inserted
replaced
1456:7b218ec1044f | 1458:e0b2d67cfe7c |
---|---|
1 /** | |
2 * Forms the symbols available to all D programs. Includes Object, which is | |
3 * the root of the class object hierarchy. This module is implicitly | |
4 * imported. | |
5 * Macros: | |
6 * WIKI = Object | |
7 * | |
8 * Copyright: Copyright Digital Mars 2000 - 2009. | |
9 * License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>. | |
10 * Authors: Walter Bright, Sean Kelly | |
11 * | |
12 * Copyright Digital Mars 2000 - 2009. | |
13 * Distributed under the Boost Software License, Version 1.0. | |
14 * (See accompanying file LICENSE_1_0.txt or copy at | |
15 * http://www.boost.org/LICENSE_1_0.txt) | |
16 */ | |
17 | |
18 module object; | |
19 | |
20 private | |
21 { | |
22 import core.stdc.string; | |
23 import core.stdc.stdlib; | |
24 import util.string; | |
25 debug(PRINTF) import core.stdc.stdio; | |
26 | |
27 extern (C) void onOutOfMemoryError(); | |
28 extern (C) Object _d_newclass(ClassInfo ci); | |
29 } | |
30 | |
31 // NOTE: For some reason, this declaration method doesn't work | |
32 // in this particular file (and this file only). It must | |
33 // be a DMD thing. | |
34 //alias typeof(int.sizeof) size_t; | |
35 //alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; | |
36 | |
37 version(X86_64) | |
38 { | |
39 alias ulong size_t; | |
40 alias long ptrdiff_t; | |
41 } | |
42 else | |
43 { | |
44 alias uint size_t; | |
45 alias int ptrdiff_t; | |
46 } | |
47 | |
48 alias size_t hash_t; | |
49 alias bool equals_t; | |
50 | |
51 alias immutable(char)[] string; | |
52 alias immutable(wchar)[] wstring; | |
53 alias immutable(dchar)[] dstring; | |
54 | |
55 /** | |
56 * All D class objects inherit from Object. | |
57 */ | |
58 class Object | |
59 { | |
60 /** | |
61 * Convert Object to a human readable string. | |
62 */ | |
63 string toString() | |
64 { | |
65 return this.classinfo.name; | |
66 } | |
67 | |
68 /** | |
69 * Compute hash function for Object. | |
70 */ | |
71 hash_t toHash() | |
72 { | |
73 // BUG: this prevents a compacting GC from working, needs to be fixed | |
74 return cast(hash_t)cast(void*)this; | |
75 } | |
76 | |
77 /** | |
78 * Compare with another Object obj. | |
79 * Returns: | |
80 * $(TABLE | |
81 * $(TR $(TD this < obj) $(TD < 0)) | |
82 * $(TR $(TD this == obj) $(TD 0)) | |
83 * $(TR $(TD this > obj) $(TD > 0)) | |
84 * ) | |
85 */ | |
86 int opCmp(Object o) | |
87 { | |
88 // BUG: this prevents a compacting GC from working, needs to be fixed | |
89 //return cast(int)cast(void*)this - cast(int)cast(void*)o; | |
90 | |
91 throw new Exception("need opCmp for class " ~ this.classinfo.name); | |
92 //return this !is o; | |
93 } | |
94 | |
95 /** | |
96 * Returns !=0 if this object does have the same contents as obj. | |
97 */ | |
98 equals_t opEquals(Object o) | |
99 { | |
100 return this is o; | |
101 } | |
102 | |
103 interface Monitor | |
104 { | |
105 void lock(); | |
106 void unlock(); | |
107 } | |
108 | |
109 /** | |
110 * Create instance of class specified by classname. | |
111 * The class must either have no constructors or have | |
112 * a default constructor. | |
113 * Returns: | |
114 * null if failed | |
115 */ | |
116 static Object factory(string classname) | |
117 { | |
118 auto ci = ClassInfo.find(classname); | |
119 if (ci) | |
120 { | |
121 return ci.create(); | |
122 } | |
123 return null; | |
124 } | |
125 } | |
126 | |
127 /** | |
128 * Information about an interface. | |
129 * When an object is accessed via an interface, an Interface* appears as the | |
130 * first entry in its vtbl. | |
131 */ | |
132 struct Interface | |
133 { | |
134 ClassInfo classinfo; /// .classinfo for this interface (not for containing class) | |
135 void*[] vtbl; | |
136 ptrdiff_t offset; /// offset to Interface 'this' from Object 'this' | |
137 } | |
138 | |
139 /** | |
140 * Runtime type information about a class. Can be retrieved for any class type | |
141 * or instance by using the .classinfo property. | |
142 * A pointer to this appears as the first entry in the class's vtbl[]. | |
143 */ | |
144 class ClassInfo : Object | |
145 { | |
146 byte[] init; /** class static initializer | |
147 * (init.length gives size in bytes of class) | |
148 */ | |
149 string name; /// class name | |
150 void*[] vtbl; /// virtual function pointer table | |
151 Interface[] interfaces; /// interfaces this class implements | |
152 ClassInfo base; /// base class | |
153 void* destructor; | |
154 void* classInvariant; | |
155 uint flags; | |
156 // 1: // is IUnknown or is derived from IUnknown | |
157 // 2: // has no possible pointers into GC memory | |
158 // 4: // has offTi[] member | |
159 // 8: // has constructors | |
160 // 16: // has xgetMembers member | |
161 // 32: // has typeinfo member | |
162 void* deallocator; | |
163 OffsetTypeInfo[] offTi; | |
164 void* defaultConstructor; // default Constructor | |
165 const(MemberInfo[]) function(in char[]) xgetMembers; | |
166 TypeInfo typeinfo; | |
167 | |
168 /** | |
169 * Search all modules for ClassInfo corresponding to classname. | |
170 * Returns: null if not found | |
171 */ | |
172 static ClassInfo find(in char[] classname) | |
173 { | |
174 foreach (m; ModuleInfo) | |
175 { | |
176 //writefln("module %s, %d", m.name, m.localClasses.length); | |
177 foreach (c; m.localClasses) | |
178 { | |
179 //writefln("\tclass %s", c.name); | |
180 if (c.name == classname) | |
181 return c; | |
182 } | |
183 } | |
184 return null; | |
185 } | |
186 | |
187 /** | |
188 * Create instance of Object represented by 'this'. | |
189 */ | |
190 Object create() | |
191 { | |
192 if (flags & 8 && !defaultConstructor) | |
193 return null; | |
194 Object o = _d_newclass(this); | |
195 if (flags & 8 && defaultConstructor) | |
196 { | |
197 Object delegate() ctor; | |
198 ctor.ptr = cast(void*)o; | |
199 ctor.funcptr = cast(Object function())defaultConstructor; | |
200 ctor(); | |
201 //defaultConstructor(o); | |
202 } | |
203 return o; | |
204 } | |
205 | |
206 /** | |
207 * Search for all members with the name 'name'. | |
208 * If name[] is null, return all members. | |
209 */ | |
210 const(MemberInfo[]) getMembers(in char[] name) | |
211 { | |
212 if (flags & 16 && xgetMembers) | |
213 return xgetMembers(name); | |
214 return null; | |
215 } | |
216 } | |
217 | |
218 /** | |
219 * Array of pairs giving the offset and type information for each | |
220 * member in an aggregate. | |
221 */ | |
222 struct OffsetTypeInfo | |
223 { | |
224 size_t offset; /// Offset of member from start of object | |
225 TypeInfo ti; /// TypeInfo for this member | |
226 } | |
227 | |
228 /** | |
229 * Runtime type information about a type. | |
230 * Can be retrieved for any type using a | |
231 * <a href="../expression.html#typeidexpression">TypeidExpression</a>. | |
232 */ | |
233 class TypeInfo | |
234 { | |
235 override hash_t toHash() | |
236 { | |
237 hash_t hash; | |
238 | |
239 foreach (char c; this.toString()) | |
240 hash = hash * 9 + c; | |
241 return hash; | |
242 } | |
243 | |
244 override int opCmp(Object o) | |
245 { | |
246 if (this is o) | |
247 return 0; | |
248 TypeInfo ti = cast(TypeInfo)o; | |
249 if (ti is null) | |
250 return 1; | |
251 return dstrcmp(this.toString(), ti.toString()); | |
252 } | |
253 | |
254 override equals_t opEquals(Object o) | |
255 { | |
256 /* TypeInfo instances are singletons, but duplicates can exist | |
257 * across DLL's. Therefore, comparing for a name match is | |
258 * sufficient. | |
259 */ | |
260 if (this is o) | |
261 return true; | |
262 TypeInfo ti = cast(TypeInfo)o; | |
263 return ti && this.toString() == ti.toString(); | |
264 } | |
265 | |
266 /// Returns a hash of the instance of a type. | |
267 hash_t getHash(in void* p) { return cast(hash_t)p; } | |
268 | |
269 /// Compares two instances for equality. | |
270 equals_t equals(in void* p1, in void* p2) { return p1 == p2; } | |
271 | |
272 /// Compares two instances for <, ==, or >. | |
273 int compare(in void* p1, in void* p2) { return 0; } | |
274 | |
275 /// Returns size of the type. | |
276 size_t tsize() { return 0; } | |
277 | |
278 /// Swaps two instances of the type. | |
279 void swap(void* p1, void* p2) | |
280 { | |
281 size_t n = tsize(); | |
282 for (size_t i = 0; i < n; i++) | |
283 { | |
284 byte t = (cast(byte *)p1)[i]; | |
285 (cast(byte*)p1)[i] = (cast(byte*)p2)[i]; | |
286 (cast(byte*)p2)[i] = t; | |
287 } | |
288 } | |
289 | |
290 /// Get TypeInfo for 'next' type, as defined by what kind of type this is, | |
291 /// null if none. | |
292 TypeInfo next() { return null; } | |
293 | |
294 /// Return default initializer, null if default initialize to 0 | |
295 void[] init() { return null; } | |
296 | |
297 /// Get flags for type: 1 means GC should scan for pointers | |
298 uint flags() { return 0; } | |
299 | |
300 /// Get type information on the contents of the type; null if not available | |
301 OffsetTypeInfo[] offTi() { return null; } | |
302 /// Run the destructor on the object and all its sub-objects | |
303 void destroy(void* p) {} | |
304 /// Run the postblit on the object and all its sub-objects | |
305 void postblit(void* p) {} | |
306 } | |
307 | |
308 class TypeInfo_Typedef : TypeInfo | |
309 { | |
310 override string toString() { return name; } | |
311 | |
312 override equals_t opEquals(Object o) | |
313 { | |
314 TypeInfo_Typedef c; | |
315 return this is o || | |
316 ((c = cast(TypeInfo_Typedef)o) !is null && | |
317 this.name == c.name && | |
318 this.base == c.base); | |
319 } | |
320 | |
321 override hash_t getHash(in void* p) { return base.getHash(p); } | |
322 override equals_t equals(in void* p1, in void* p2) { return base.equals(p1, p2); } | |
323 override int compare(in void* p1, in void* p2) { return base.compare(p1, p2); } | |
324 override size_t tsize() { return base.tsize(); } | |
325 override void swap(void* p1, void* p2) { return base.swap(p1, p2); } | |
326 | |
327 override TypeInfo next() { return base.next(); } | |
328 override uint flags() { return base.flags(); } | |
329 override void[] init() { return m_init.length ? m_init : base.init(); } | |
330 | |
331 TypeInfo base; | |
332 string name; | |
333 void[] m_init; | |
334 } | |
335 | |
336 class TypeInfo_Enum : TypeInfo_Typedef | |
337 { | |
338 | |
339 } | |
340 | |
341 class TypeInfo_Pointer : TypeInfo | |
342 { | |
343 override string toString() { return m_next.toString() ~ "*"; } | |
344 | |
345 override equals_t opEquals(Object o) | |
346 { | |
347 TypeInfo_Pointer c; | |
348 return this is o || | |
349 ((c = cast(TypeInfo_Pointer)o) !is null && | |
350 this.m_next == c.m_next); | |
351 } | |
352 | |
353 override hash_t getHash(in void* p) | |
354 { | |
355 return cast(hash_t)*cast(void**)p; | |
356 } | |
357 | |
358 override equals_t equals(in void* p1, in void* p2) | |
359 { | |
360 return *cast(void**)p1 == *cast(void**)p2; | |
361 } | |
362 | |
363 override int compare(in void* p1, in void* p2) | |
364 { | |
365 if (*cast(void**)p1 < *cast(void**)p2) | |
366 return -1; | |
367 else if (*cast(void**)p1 > *cast(void**)p2) | |
368 return 1; | |
369 else | |
370 return 0; | |
371 } | |
372 | |
373 override size_t tsize() | |
374 { | |
375 return (void*).sizeof; | |
376 } | |
377 | |
378 override void swap(void* p1, void* p2) | |
379 { | |
380 void* tmp = *cast(void**)p1; | |
381 *cast(void**)p1 = *cast(void**)p2; | |
382 *cast(void**)p2 = tmp; | |
383 } | |
384 | |
385 override TypeInfo next() { return m_next; } | |
386 override uint flags() { return 1; } | |
387 | |
388 TypeInfo m_next; | |
389 } | |
390 | |
391 class TypeInfo_Array : TypeInfo | |
392 { | |
393 override string toString() { return value.toString() ~ "[]"; } | |
394 | |
395 override equals_t opEquals(Object o) | |
396 { | |
397 TypeInfo_Array c; | |
398 return this is o || | |
399 ((c = cast(TypeInfo_Array)o) !is null && | |
400 this.value == c.value); | |
401 } | |
402 | |
403 override hash_t getHash(in void* p) | |
404 { | |
405 size_t sz = value.tsize(); | |
406 hash_t hash = 0; | |
407 void[] a = *cast(void[]*)p; | |
408 for (size_t i = 0; i < a.length; i++) | |
409 hash += value.getHash(a.ptr + i * sz) * 11; | |
410 return hash; | |
411 } | |
412 | |
413 override equals_t equals(in void* p1, in void* p2) | |
414 { | |
415 void[] a1 = *cast(void[]*)p1; | |
416 void[] a2 = *cast(void[]*)p2; | |
417 if (a1.length != a2.length) | |
418 return false; | |
419 size_t sz = value.tsize(); | |
420 for (size_t i = 0; i < a1.length; i++) | |
421 { | |
422 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) | |
423 return false; | |
424 } | |
425 return true; | |
426 } | |
427 | |
428 override int compare(in void* p1, in void* p2) | |
429 { | |
430 void[] a1 = *cast(void[]*)p1; | |
431 void[] a2 = *cast(void[]*)p2; | |
432 size_t sz = value.tsize(); | |
433 size_t len = a1.length; | |
434 | |
435 if (a2.length < len) | |
436 len = a2.length; | |
437 for (size_t u = 0; u < len; u++) | |
438 { | |
439 int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); | |
440 if (result) | |
441 return result; | |
442 } | |
443 return cast(int)a1.length - cast(int)a2.length; | |
444 } | |
445 | |
446 override size_t tsize() | |
447 { | |
448 return (void[]).sizeof; | |
449 } | |
450 | |
451 override void swap(void* p1, void* p2) | |
452 { | |
453 void[] tmp = *cast(void[]*)p1; | |
454 *cast(void[]*)p1 = *cast(void[]*)p2; | |
455 *cast(void[]*)p2 = tmp; | |
456 } | |
457 | |
458 TypeInfo value; | |
459 | |
460 override TypeInfo next() | |
461 { | |
462 return value; | |
463 } | |
464 | |
465 override uint flags() { return 1; } | |
466 } | |
467 | |
468 class TypeInfo_StaticArray : TypeInfo | |
469 { | |
470 override string toString() | |
471 { | |
472 char[10] tmp = void; | |
473 return cast(string)(value.toString() ~ "[" ~ tmp.intToString(len) ~ "]"); | |
474 } | |
475 | |
476 override equals_t opEquals(Object o) | |
477 { | |
478 TypeInfo_StaticArray c; | |
479 return this is o || | |
480 ((c = cast(TypeInfo_StaticArray)o) !is null && | |
481 this.len == c.len && | |
482 this.value == c.value); | |
483 } | |
484 | |
485 override hash_t getHash(in void* p) | |
486 { | |
487 size_t sz = value.tsize(); | |
488 hash_t hash = 0; | |
489 for (size_t i = 0; i < len; i++) | |
490 hash += value.getHash(p + i * sz); | |
491 return hash; | |
492 } | |
493 | |
494 override equals_t equals(in void* p1, in void* p2) | |
495 { | |
496 size_t sz = value.tsize(); | |
497 | |
498 for (size_t u = 0; u < len; u++) | |
499 { | |
500 if (!value.equals(p1 + u * sz, p2 + u * sz)) | |
501 return false; | |
502 } | |
503 return true; | |
504 } | |
505 | |
506 override int compare(in void* p1, in void* p2) | |
507 { | |
508 size_t sz = value.tsize(); | |
509 | |
510 for (size_t u = 0; u < len; u++) | |
511 { | |
512 int result = value.compare(p1 + u * sz, p2 + u * sz); | |
513 if (result) | |
514 return result; | |
515 } | |
516 return 0; | |
517 } | |
518 | |
519 override size_t tsize() | |
520 { | |
521 return len * value.tsize(); | |
522 } | |
523 | |
524 override void swap(void* p1, void* p2) | |
525 { | |
526 void* tmp; | |
527 size_t sz = value.tsize(); | |
528 ubyte[16] buffer; | |
529 void* pbuffer; | |
530 | |
531 if (sz < buffer.sizeof) | |
532 tmp = buffer.ptr; | |
533 else | |
534 tmp = pbuffer = (new void[sz]).ptr; | |
535 | |
536 for (size_t u = 0; u < len; u += sz) | |
537 { size_t o = u * sz; | |
538 memcpy(tmp, p1 + o, sz); | |
539 memcpy(p1 + o, p2 + o, sz); | |
540 memcpy(p2 + o, tmp, sz); | |
541 } | |
542 if (pbuffer) | |
543 delete pbuffer; | |
544 } | |
545 | |
546 override void[] init() { return value.init(); } | |
547 override TypeInfo next() { return value; } | |
548 override uint flags() { return value.flags(); } | |
549 | |
550 override void destroy(void* p) | |
551 { | |
552 auto sz = value.tsize(); | |
553 p += sz * len; | |
554 foreach (i; 0 .. len) | |
555 { | |
556 p -= sz; | |
557 value.destroy(p); | |
558 } | |
559 } | |
560 | |
561 override void postblit(void* p) | |
562 { | |
563 auto sz = value.tsize(); | |
564 foreach (i; 0 .. len) | |
565 { | |
566 value.postblit(p); | |
567 p += sz; | |
568 } | |
569 } | |
570 | |
571 TypeInfo value; | |
572 size_t len; | |
573 } | |
574 | |
575 class TypeInfo_AssociativeArray : TypeInfo | |
576 { | |
577 override string toString() | |
578 { | |
579 return cast(string)(next.toString() ~ "[" ~ key.toString() ~ "]"); | |
580 } | |
581 | |
582 override equals_t opEquals(Object o) | |
583 { | |
584 TypeInfo_AssociativeArray c; | |
585 return this is o || | |
586 ((c = cast(TypeInfo_AssociativeArray)o) !is null && | |
587 this.key == c.key && | |
588 this.value == c.value); | |
589 } | |
590 | |
591 // BUG: need to add the rest of the functions | |
592 | |
593 override size_t tsize() | |
594 { | |
595 return (char[int]).sizeof; | |
596 } | |
597 | |
598 override TypeInfo next() { return value; } | |
599 override uint flags() { return 1; } | |
600 | |
601 TypeInfo value; | |
602 TypeInfo key; | |
603 } | |
604 | |
605 class TypeInfo_Function : TypeInfo | |
606 { | |
607 override string toString() | |
608 { | |
609 return cast(string)(next.toString() ~ "()"); | |
610 } | |
611 | |
612 override equals_t opEquals(Object o) | |
613 { | |
614 TypeInfo_Function c; | |
615 return this is o || | |
616 ((c = cast(TypeInfo_Function)o) !is null && | |
617 this.next == c.next); | |
618 } | |
619 | |
620 // BUG: need to add the rest of the functions | |
621 | |
622 override size_t tsize() | |
623 { | |
624 return 0; // no size for functions | |
625 } | |
626 | |
627 TypeInfo next; | |
628 } | |
629 | |
630 class TypeInfo_Delegate : TypeInfo | |
631 { | |
632 override string toString() | |
633 { | |
634 return cast(string)(next.toString() ~ " delegate()"); | |
635 } | |
636 | |
637 override equals_t opEquals(Object o) | |
638 { | |
639 TypeInfo_Delegate c; | |
640 return this is o || | |
641 ((c = cast(TypeInfo_Delegate)o) !is null && | |
642 this.next == c.next); | |
643 } | |
644 | |
645 // BUG: need to add the rest of the functions | |
646 | |
647 override size_t tsize() | |
648 { | |
649 alias int delegate() dg; | |
650 return dg.sizeof; | |
651 } | |
652 | |
653 override uint flags() { return 1; } | |
654 | |
655 TypeInfo next; | |
656 } | |
657 | |
658 class TypeInfo_Class : TypeInfo | |
659 { | |
660 override string toString() { return info.name; } | |
661 | |
662 override equals_t opEquals(Object o) | |
663 { | |
664 TypeInfo_Class c; | |
665 return this is o || | |
666 ((c = cast(TypeInfo_Class)o) !is null && | |
667 this.info.name == c.classinfo.name); | |
668 } | |
669 | |
670 override hash_t getHash(in void* p) | |
671 { | |
672 Object o = *cast(Object*)p; | |
673 return o ? o.toHash() : 0; | |
674 } | |
675 | |
676 override equals_t equals(in void* p1, in void* p2) | |
677 { | |
678 Object o1 = *cast(Object*)p1; | |
679 Object o2 = *cast(Object*)p2; | |
680 | |
681 return (o1 is o2) || (o1 && o1.opEquals(o2)); | |
682 } | |
683 | |
684 override int compare(in void* p1, in void* p2) | |
685 { | |
686 Object o1 = *cast(Object*)p1; | |
687 Object o2 = *cast(Object*)p2; | |
688 int c = 0; | |
689 | |
690 // Regard null references as always being "less than" | |
691 if (o1 !is o2) | |
692 { | |
693 if (o1) | |
694 { | |
695 if (!o2) | |
696 c = 1; | |
697 else | |
698 c = o1.opCmp(o2); | |
699 } | |
700 else | |
701 c = -1; | |
702 } | |
703 return c; | |
704 } | |
705 | |
706 override size_t tsize() | |
707 { | |
708 return Object.sizeof; | |
709 } | |
710 | |
711 override uint flags() { return 1; } | |
712 | |
713 override OffsetTypeInfo[] offTi() | |
714 { | |
715 return (info.flags & 4) ? info.offTi : null; | |
716 } | |
717 | |
718 ClassInfo info; | |
719 } | |
720 | |
721 class TypeInfo_Interface : TypeInfo | |
722 { | |
723 override string toString() { return info.name; } | |
724 | |
725 override equals_t opEquals(Object o) | |
726 { | |
727 TypeInfo_Interface c; | |
728 return this is o || | |
729 ((c = cast(TypeInfo_Interface)o) !is null && | |
730 this.info.name == c.classinfo.name); | |
731 } | |
732 | |
733 override hash_t getHash(in void* p) | |
734 { | |
735 Interface* pi = **cast(Interface ***)*cast(void**)p; | |
736 Object o = cast(Object)(*cast(void**)p - pi.offset); | |
737 assert(o); | |
738 return o.toHash(); | |
739 } | |
740 | |
741 override equals_t equals(in void* p1, in void* p2) | |
742 { | |
743 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
744 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
745 pi = **cast(Interface ***)*cast(void**)p2; | |
746 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
747 | |
748 return o1 == o2 || (o1 && o1.opCmp(o2) == 0); | |
749 } | |
750 | |
751 override int compare(in void* p1, in void* p2) | |
752 { | |
753 Interface* pi = **cast(Interface ***)*cast(void**)p1; | |
754 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset); | |
755 pi = **cast(Interface ***)*cast(void**)p2; | |
756 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset); | |
757 int c = 0; | |
758 | |
759 // Regard null references as always being "less than" | |
760 if (o1 != o2) | |
761 { | |
762 if (o1) | |
763 { | |
764 if (!o2) | |
765 c = 1; | |
766 else | |
767 c = o1.opCmp(o2); | |
768 } | |
769 else | |
770 c = -1; | |
771 } | |
772 return c; | |
773 } | |
774 | |
775 override size_t tsize() | |
776 { | |
777 return Object.sizeof; | |
778 } | |
779 | |
780 override uint flags() { return 1; } | |
781 | |
782 ClassInfo info; | |
783 } | |
784 | |
785 class TypeInfo_Struct : TypeInfo | |
786 { | |
787 override string toString() { return name; } | |
788 | |
789 override equals_t opEquals(Object o) | |
790 { | |
791 TypeInfo_Struct s; | |
792 return this is o || | |
793 ((s = cast(TypeInfo_Struct)o) !is null && | |
794 this.name == s.name && | |
795 this.init.length == s.init.length); | |
796 } | |
797 | |
798 override hash_t getHash(in void* p) | |
799 { | |
800 assert(p); | |
801 if (xtoHash) | |
802 { | |
803 debug(PRINTF) printf("getHash() using xtoHash\n"); | |
804 return (*xtoHash)(p); | |
805 } | |
806 else | |
807 { | |
808 hash_t h; | |
809 debug(PRINTF) printf("getHash() using default hash\n"); | |
810 // A sorry hash algorithm. | |
811 // Should use the one for strings. | |
812 // BUG: relies on the GC not moving objects | |
813 auto q = cast(const(ubyte)*)p; | |
814 for (size_t i = 0; i < init.length; i++) | |
815 { | |
816 h = h * 9 + *q; | |
817 q++; | |
818 } | |
819 return h; | |
820 } | |
821 } | |
822 | |
823 override equals_t equals(in void* p1, in void* p2) | |
824 { | |
825 if (p1 == p2) | |
826 return true; | |
827 else if (!p1 || !p2) | |
828 return false; | |
829 else if (xopEquals) | |
830 return (*xopEquals)(p1, p2); | |
831 else | |
832 // BUG: relies on the GC not moving objects | |
833 return memcmp(p1, p2, init.length) == 0; | |
834 } | |
835 | |
836 override int compare(in void* p1, in void* p2) | |
837 { | |
838 // Regard null references as always being "less than" | |
839 if (p1 != p2) | |
840 { | |
841 if (p1) | |
842 { | |
843 if (!p2) | |
844 return true; | |
845 else if (xopCmp) | |
846 return (*xopCmp)(p2, p1); | |
847 else | |
848 // BUG: relies on the GC not moving objects | |
849 return memcmp(p1, p2, init.length); | |
850 } | |
851 else | |
852 return -1; | |
853 } | |
854 return 0; | |
855 } | |
856 | |
857 override size_t tsize() | |
858 { | |
859 return init.length; | |
860 } | |
861 | |
862 override void[] init() { return m_init; } | |
863 | |
864 override uint flags() { return m_flags; } | |
865 | |
866 override void destroy(void* p) | |
867 { | |
868 if (xdtor) | |
869 (*xdtor)(p); | |
870 } | |
871 | |
872 override void postblit(void* p) | |
873 { | |
874 if (xpostblit) | |
875 (*xpostblit)(p); | |
876 } | |
877 | |
878 string name; | |
879 void[] m_init; // initializer; init.ptr == null if 0 initialize | |
880 | |
881 hash_t function(in void*) xtoHash; | |
882 equals_t function(in void*, in void*) xopEquals; | |
883 int function(in void*, in void*) xopCmp; | |
884 char[] function(in void*) xtoString; | |
885 | |
886 uint m_flags; | |
887 | |
888 const(MemberInfo[]) function(in char[]) xgetMembers; | |
889 void function(void*) xdtor; | |
890 void function(void*) xpostblit; | |
891 } | |
892 | |
893 class TypeInfo_Tuple : TypeInfo | |
894 { | |
895 TypeInfo[] elements; | |
896 | |
897 override string toString() | |
898 { | |
899 string s = "("; | |
900 foreach (i, element; elements) | |
901 { | |
902 if (i) | |
903 s ~= ','; | |
904 s ~= element.toString(); | |
905 } | |
906 s ~= ")"; | |
907 return s; | |
908 } | |
909 | |
910 override equals_t opEquals(Object o) | |
911 { | |
912 if (this is o) | |
913 return true; | |
914 | |
915 auto t = cast(TypeInfo_Tuple)o; | |
916 if (t && elements.length == t.elements.length) | |
917 { | |
918 for (size_t i = 0; i < elements.length; i++) | |
919 { | |
920 if (elements[i] != t.elements[i]) | |
921 return false; | |
922 } | |
923 return true; | |
924 } | |
925 return false; | |
926 } | |
927 | |
928 override hash_t getHash(in void* p) | |
929 { | |
930 assert(0); | |
931 } | |
932 | |
933 override equals_t equals(in void* p1, in void* p2) | |
934 { | |
935 assert(0); | |
936 } | |
937 | |
938 override int compare(in void* p1, in void* p2) | |
939 { | |
940 assert(0); | |
941 } | |
942 | |
943 override size_t tsize() | |
944 { | |
945 assert(0); | |
946 } | |
947 | |
948 override void swap(void* p1, void* p2) | |
949 { | |
950 assert(0); | |
951 } | |
952 | |
953 override void destroy(void* p) | |
954 { | |
955 assert(0); | |
956 } | |
957 | |
958 override void postblit(void* p) | |
959 { | |
960 assert(0); | |
961 } | |
962 } | |
963 | |
964 class TypeInfo_Const : TypeInfo | |
965 { | |
966 override string toString() | |
967 { | |
968 return cast(string) ("const(" ~ base.toString() ~ ")"); | |
969 } | |
970 | |
971 override equals_t opEquals(Object o) { return base.opEquals(o); } | |
972 override hash_t getHash(in void *p) { return base.getHash(p); } | |
973 override equals_t equals(in void *p1, in void *p2) { return base.equals(p1, p2); } | |
974 override int compare(in void *p1, in void *p2) { return base.compare(p1, p2); } | |
975 override size_t tsize() { return base.tsize(); } | |
976 override void swap(void *p1, void *p2) { return base.swap(p1, p2); } | |
977 | |
978 override TypeInfo next() { return base.next(); } | |
979 override uint flags() { return base.flags(); } | |
980 override void[] init() { return base.init(); } | |
981 | |
982 TypeInfo base; | |
983 } | |
984 | |
985 class TypeInfo_Invariant : TypeInfo_Const | |
986 { | |
987 override string toString() | |
988 { | |
989 return cast(string) ("immutable(" ~ base.toString() ~ ")"); | |
990 } | |
991 } | |
992 | |
993 class TypeInfo_Shared : TypeInfo_Const | |
994 { | |
995 override string toString() | |
996 { | |
997 return cast(string) ("shared(" ~ base.toString() ~ ")"); | |
998 } | |
999 } | |
1000 | |
1001 abstract class MemberInfo | |
1002 { | |
1003 string name(); | |
1004 } | |
1005 | |
1006 class MemberInfo_field : MemberInfo | |
1007 { | |
1008 this(string name, TypeInfo ti, size_t offset) | |
1009 { | |
1010 m_name = name; | |
1011 m_typeinfo = ti; | |
1012 m_offset = offset; | |
1013 } | |
1014 | |
1015 override string name() { return m_name; } | |
1016 TypeInfo typeInfo() { return m_typeinfo; } | |
1017 size_t offset() { return m_offset; } | |
1018 | |
1019 string m_name; | |
1020 TypeInfo m_typeinfo; | |
1021 size_t m_offset; | |
1022 } | |
1023 | |
1024 class MemberInfo_function : MemberInfo | |
1025 { | |
1026 this(string name, TypeInfo ti, void* fp, uint flags) | |
1027 { | |
1028 m_name = name; | |
1029 m_typeinfo = ti; | |
1030 m_fp = fp; | |
1031 m_flags = flags; | |
1032 } | |
1033 | |
1034 override string name() { return m_name; } | |
1035 TypeInfo typeInfo() { return m_typeinfo; } | |
1036 void* fp() { return m_fp; } | |
1037 uint flags() { return m_flags; } | |
1038 | |
1039 string m_name; | |
1040 TypeInfo m_typeinfo; | |
1041 void* m_fp; | |
1042 uint m_flags; | |
1043 } | |
1044 | |
1045 | |
1046 /////////////////////////////////////////////////////////////////////////////// | |
1047 // Throwable | |
1048 /////////////////////////////////////////////////////////////////////////////// | |
1049 | |
1050 | |
1051 class Throwable : Object | |
1052 { | |
1053 interface TraceInfo | |
1054 { | |
1055 int opApply(int delegate(inout char[])); | |
1056 } | |
1057 | |
1058 string msg; | |
1059 string file; | |
1060 size_t line; | |
1061 TraceInfo info; | |
1062 Throwable next; | |
1063 | |
1064 this(string msg, Throwable next = null) | |
1065 { | |
1066 this.msg = msg; | |
1067 this.next = next; | |
1068 this.info = traceContext(); | |
1069 } | |
1070 | |
1071 this(string msg, string file, size_t line, Throwable next = null) | |
1072 { | |
1073 this(msg, next); | |
1074 this.file = file; | |
1075 this.line = line; | |
1076 this.info = traceContext(); | |
1077 } | |
1078 | |
1079 override string toString() | |
1080 { | |
1081 char[10] tmp = void; | |
1082 char[] buf; | |
1083 | |
1084 for (Throwable e = this; e !is null; e = e.next) | |
1085 { | |
1086 if (e.file) | |
1087 { | |
1088 buf ~= e.classinfo.name ~ "@" ~ e.file ~ "(" ~ tmp.intToString(e.line) ~ "): " ~ e.msg; | |
1089 } | |
1090 else | |
1091 { | |
1092 buf ~= e.classinfo.name ~ ": " ~ e.msg; | |
1093 } | |
1094 if (e.info) | |
1095 { | |
1096 buf ~= "\n----------------"; | |
1097 foreach (t; e.info) | |
1098 buf ~= "\n" ~ t; | |
1099 } | |
1100 if (e.next) | |
1101 buf ~= "\n"; | |
1102 } | |
1103 return cast(string) buf; | |
1104 } | |
1105 } | |
1106 | |
1107 | |
1108 alias Throwable.TraceInfo function(void* ptr = null) TraceHandler; | |
1109 private __gshared TraceHandler traceHandler = null; | |
1110 | |
1111 | |
1112 /** | |
1113 * Overrides the default trace hander with a user-supplied version. | |
1114 * | |
1115 * Params: | |
1116 * h = The new trace handler. Set to null to use the default handler. | |
1117 */ | |
1118 extern (C) void rt_setTraceHandler(TraceHandler h) | |
1119 { | |
1120 traceHandler = h; | |
1121 } | |
1122 | |
1123 | |
1124 /** | |
1125 * This function will be called when an exception is constructed. The | |
1126 * user-supplied trace handler will be called if one has been supplied, | |
1127 * otherwise no trace will be generated. | |
1128 * | |
1129 * Params: | |
1130 * ptr = A pointer to the location from which to generate the trace, or null | |
1131 * if the trace should be generated from within the trace handler | |
1132 * itself. | |
1133 * | |
1134 * Returns: | |
1135 * An object describing the current calling context or null if no handler is | |
1136 * supplied. | |
1137 */ | |
1138 Throwable.TraceInfo traceContext(void* ptr = null) | |
1139 { | |
1140 if (traceHandler is null) | |
1141 return null; | |
1142 return traceHandler(ptr); | |
1143 } | |
1144 | |
1145 | |
1146 class Exception : Throwable | |
1147 { | |
1148 this(string msg, Throwable next = null) | |
1149 { | |
1150 super(msg, next); | |
1151 } | |
1152 | |
1153 this(string msg, string file, size_t line, Throwable next = null) | |
1154 { | |
1155 super(msg, file, line, next); | |
1156 } | |
1157 } | |
1158 | |
1159 | |
1160 class Error : Throwable | |
1161 { | |
1162 this(string msg, Throwable next = null) | |
1163 { | |
1164 super(msg, next); | |
1165 } | |
1166 | |
1167 this(string msg, string file, size_t line, Throwable next = null) | |
1168 { | |
1169 super(msg, file, line, next); | |
1170 } | |
1171 } | |
1172 | |
1173 | |
1174 /////////////////////////////////////////////////////////////////////////////// | |
1175 // ModuleInfo | |
1176 /////////////////////////////////////////////////////////////////////////////// | |
1177 | |
1178 | |
1179 enum | |
1180 { | |
1181 MIctorstart = 1, // we've started constructing it | |
1182 MIctordone = 2, // finished construction | |
1183 MIstandalone = 4, // module ctor does not depend on other module | |
1184 // ctors being done first | |
1185 MIhasictor = 8, // has ictor member | |
1186 } | |
1187 | |
1188 | |
1189 class ModuleInfo | |
1190 { | |
1191 string name; | |
1192 ModuleInfo[] importedModules; | |
1193 ClassInfo[] localClasses; | |
1194 uint flags; | |
1195 | |
1196 void function() ctor; // module static constructor (order dependent) | |
1197 void function() dtor; // module static destructor | |
1198 void function() unitTest; // module unit tests | |
1199 | |
1200 void* xgetMembers; // module getMembers() function | |
1201 | |
1202 void function() ictor; // module static constructor (order independent) | |
1203 | |
1204 void*[4] reserved; // for future expansion | |
1205 | |
1206 static int opApply(int delegate(inout ModuleInfo) dg) | |
1207 { | |
1208 int ret = 0; | |
1209 | |
1210 foreach (m; _moduleinfo_array) | |
1211 { | |
1212 ret = dg(m); | |
1213 if (ret) | |
1214 break; | |
1215 } | |
1216 return ret; | |
1217 } | |
1218 } | |
1219 | |
1220 | |
1221 // Windows: this gets initialized by minit.asm | |
1222 // Posix: this gets initialized in _moduleCtor() | |
1223 extern (C) __gshared ModuleInfo[] _moduleinfo_array; | |
1224 | |
1225 | |
1226 version (linux) | |
1227 { | |
1228 // This linked list is created by a compiler generated function inserted | |
1229 // into the .ctor list by the compiler. | |
1230 struct ModuleReference | |
1231 { | |
1232 ModuleReference* next; | |
1233 ModuleInfo mod; | |
1234 } | |
1235 | |
1236 extern (C) __gshared ModuleReference* _Dmodule_ref; // start of linked list | |
1237 } | |
1238 | |
1239 version (FreeBSD) | |
1240 { | |
1241 // This linked list is created by a compiler generated function inserted | |
1242 // into the .ctor list by the compiler. | |
1243 struct ModuleReference | |
1244 { | |
1245 ModuleReference* next; | |
1246 ModuleInfo mod; | |
1247 } | |
1248 | |
1249 extern (C) __gshared ModuleReference* _Dmodule_ref; // start of linked list | |
1250 } | |
1251 | |
1252 version (Solaris) | |
1253 { | |
1254 // This linked list is created by a compiler generated function inserted | |
1255 // into the .ctor list by the compiler. | |
1256 struct ModuleReference | |
1257 { | |
1258 ModuleReference* next; | |
1259 ModuleInfo mod; | |
1260 } | |
1261 | |
1262 extern (C) __gshared ModuleReference* _Dmodule_ref; // start of linked list | |
1263 } | |
1264 | |
1265 version (OSX) | |
1266 { | |
1267 extern (C) | |
1268 { | |
1269 extern __gshared void* _minfo_beg; | |
1270 extern __gshared void* _minfo_end; | |
1271 } | |
1272 } | |
1273 | |
1274 __gshared ModuleInfo[] _moduleinfo_dtors; | |
1275 __gshared uint _moduleinfo_dtors_i; | |
1276 | |
1277 // Register termination function pointers | |
1278 extern (C) int _fatexit(void*); | |
1279 | |
1280 /** | |
1281 * Initialize the modules. | |
1282 */ | |
1283 | |
1284 extern (C) void _moduleCtor() | |
1285 { | |
1286 debug(PRINTF) printf("_moduleCtor()\n"); | |
1287 version (linux) | |
1288 { | |
1289 int len = 0; | |
1290 ModuleReference *mr; | |
1291 | |
1292 for (mr = _Dmodule_ref; mr; mr = mr.next) | |
1293 len++; | |
1294 _moduleinfo_array = new ModuleInfo[len]; | |
1295 len = 0; | |
1296 for (mr = _Dmodule_ref; mr; mr = mr.next) | |
1297 { _moduleinfo_array[len] = mr.mod; | |
1298 len++; | |
1299 } | |
1300 } | |
1301 | |
1302 version (FreeBSD) | |
1303 { | |
1304 int len = 0; | |
1305 ModuleReference *mr; | |
1306 | |
1307 for (mr = _Dmodule_ref; mr; mr = mr.next) | |
1308 len++; | |
1309 _moduleinfo_array = new ModuleInfo[len]; | |
1310 len = 0; | |
1311 for (mr = _Dmodule_ref; mr; mr = mr.next) | |
1312 { _moduleinfo_array[len] = mr.mod; | |
1313 len++; | |
1314 } | |
1315 } | |
1316 | |
1317 version (Solaris) | |
1318 { | |
1319 int len = 0; | |
1320 ModuleReference *mr; | |
1321 | |
1322 for (mr = _Dmodule_ref; mr; mr = mr.next) | |
1323 len++; | |
1324 _moduleinfo_array = new ModuleInfo[len]; | |
1325 len = 0; | |
1326 for (mr = _Dmodule_ref; mr; mr = mr.next) | |
1327 { _moduleinfo_array[len] = mr.mod; | |
1328 len++; | |
1329 } | |
1330 } | |
1331 | |
1332 version (OSX) | |
1333 { | |
1334 /* The ModuleInfo references are stored in the special segment | |
1335 * __minfodata, which is bracketed by the segments __minfo_beg | |
1336 * and __minfo_end. The variables _minfo_beg and _minfo_end | |
1337 * are of zero size and are in the two bracketing segments, | |
1338 * respectively. | |
1339 */ | |
1340 size_t length = cast(ModuleInfo*)&_minfo_end - cast(ModuleInfo*)&_minfo_beg; | |
1341 _moduleinfo_array = (cast(ModuleInfo*)&_minfo_beg)[0 .. length]; | |
1342 debug printf("moduleinfo: ptr = %p, length = %d\n", _moduleinfo_array.ptr, _moduleinfo_array.length); | |
1343 | |
1344 debug foreach (m; _moduleinfo_array) | |
1345 { | |
1346 //printf("\t%p\n", m); | |
1347 printf("\t%.*s\n", m.name); | |
1348 } | |
1349 } | |
1350 | |
1351 version (Windows) | |
1352 { | |
1353 // Ensure module destructors also get called on program termination | |
1354 //_fatexit(&_STD_moduleDtor); | |
1355 } | |
1356 | |
1357 _moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length]; | |
1358 debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void*)_moduleinfo_dtors); | |
1359 _moduleIndependentCtors(); | |
1360 _moduleCtor2(_moduleinfo_array, 0); | |
1361 } | |
1362 | |
1363 extern (C) void _moduleIndependentCtors() | |
1364 { | |
1365 debug(PRINTF) printf("_moduleIndependentCtors()\n"); | |
1366 foreach (m; _moduleinfo_array) | |
1367 { | |
1368 if (m && m.flags & MIhasictor && m.ictor) | |
1369 { | |
1370 (*m.ictor)(); | |
1371 } | |
1372 } | |
1373 } | |
1374 | |
1375 void _moduleCtor2(ModuleInfo[] mi, int skip) | |
1376 { | |
1377 debug(PRINTF) printf("_moduleCtor2(): %d modules\n", mi.length); | |
1378 for (uint i = 0; i < mi.length; i++) | |
1379 { | |
1380 ModuleInfo m = mi[i]; | |
1381 | |
1382 debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m); | |
1383 if (!m) | |
1384 continue; | |
1385 debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name); | |
1386 if (m.flags & MIctordone) | |
1387 continue; | |
1388 debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m); | |
1389 | |
1390 if (m.ctor || m.dtor) | |
1391 { | |
1392 if (m.flags & MIctorstart) | |
1393 { if (skip || m.flags & MIstandalone) | |
1394 continue; | |
1395 throw new Exception("Cyclic dependency in module " ~ m.name); | |
1396 } | |
1397 | |
1398 m.flags |= MIctorstart; | |
1399 _moduleCtor2(m.importedModules, 0); | |
1400 if (m.ctor) | |
1401 (*m.ctor)(); | |
1402 m.flags &= ~MIctorstart; | |
1403 m.flags |= MIctordone; | |
1404 | |
1405 // Now that construction is done, register the destructor | |
1406 //printf("\tadding module dtor x%x\n", m); | |
1407 assert(_moduleinfo_dtors_i < _moduleinfo_dtors.length); | |
1408 _moduleinfo_dtors[_moduleinfo_dtors_i++] = m; | |
1409 } | |
1410 else | |
1411 { | |
1412 m.flags |= MIctordone; | |
1413 _moduleCtor2(m.importedModules, 1); | |
1414 } | |
1415 } | |
1416 } | |
1417 | |
1418 /** | |
1419 * Destruct the modules. | |
1420 */ | |
1421 | |
1422 // Starting the name with "_STD" means under Posix a pointer to the | |
1423 // function gets put in the .dtors segment. | |
1424 | |
1425 extern (C) void _moduleDtor() | |
1426 { | |
1427 debug(PRINTF) printf("_moduleDtor(): %d modules\n", _moduleinfo_dtors_i); | |
1428 | |
1429 for (uint i = _moduleinfo_dtors_i; i-- != 0;) | |
1430 { | |
1431 ModuleInfo m = _moduleinfo_dtors[i]; | |
1432 | |
1433 debug(PRINTF) printf("\tmodule[%d] = '%.*s', x%x\n", i, m.name, m); | |
1434 if (m.dtor) | |
1435 { | |
1436 (*m.dtor)(); | |
1437 } | |
1438 } | |
1439 debug(PRINTF) printf("_moduleDtor() done\n"); | |
1440 } | |
1441 | |
1442 /////////////////////////////////////////////////////////////////////////////// | |
1443 // Monitor | |
1444 /////////////////////////////////////////////////////////////////////////////// | |
1445 | |
1446 alias Object.Monitor IMonitor; | |
1447 alias void delegate(Object) DEvent; | |
1448 | |
1449 // NOTE: The dtor callback feature is only supported for monitors that are not | |
1450 // supplied by the user. The assumption is that any object with a user- | |
1451 // supplied monitor may have special storage or lifetime requirements and | |
1452 // that as a result, storing references to local objects within Monitor | |
1453 // may not be safe or desirable. Thus, devt is only valid if impl is | |
1454 // null. | |
1455 struct Monitor | |
1456 { | |
1457 IMonitor impl; | |
1458 /* internal */ | |
1459 DEvent[] devt; | |
1460 /* stuff */ | |
1461 } | |
1462 | |
1463 Monitor* getMonitor(Object h) | |
1464 { | |
1465 return cast(Monitor*) (cast(void**) h)[1]; | |
1466 } | |
1467 | |
1468 void setMonitor(Object h, Monitor* m) | |
1469 { | |
1470 (cast(void**) h)[1] = m; | |
1471 } | |
1472 | |
1473 extern (C) void _d_monitor_create(Object); | |
1474 extern (C) void _d_monitor_destroy(Object); | |
1475 extern (C) void _d_monitor_lock(Object); | |
1476 extern (C) int _d_monitor_unlock(Object); | |
1477 | |
1478 extern (C) void _d_monitordelete(Object h, bool det) | |
1479 { | |
1480 Monitor* m = getMonitor(h); | |
1481 | |
1482 if (m !is null) | |
1483 { | |
1484 IMonitor i = m.impl; | |
1485 if (i is null) | |
1486 { | |
1487 _d_monitor_devt(m, h); | |
1488 _d_monitor_destroy(h); | |
1489 setMonitor(h, null); | |
1490 return; | |
1491 } | |
1492 if (det && (cast(void*) i) !is (cast(void*) h)) | |
1493 delete i; | |
1494 setMonitor(h, null); | |
1495 } | |
1496 } | |
1497 | |
1498 extern (C) void _d_monitorenter(Object h) | |
1499 { | |
1500 Monitor* m = getMonitor(h); | |
1501 | |
1502 if (m is null) | |
1503 { | |
1504 _d_monitor_create(h); | |
1505 m = getMonitor(h); | |
1506 } | |
1507 | |
1508 IMonitor i = m.impl; | |
1509 | |
1510 if (i is null) | |
1511 { | |
1512 _d_monitor_lock(h); | |
1513 return; | |
1514 } | |
1515 i.lock(); | |
1516 } | |
1517 | |
1518 extern (C) void _d_monitorexit(Object h) | |
1519 { | |
1520 Monitor* m = getMonitor(h); | |
1521 IMonitor i = m.impl; | |
1522 | |
1523 if (i is null) | |
1524 { | |
1525 _d_monitor_unlock(h); | |
1526 return; | |
1527 } | |
1528 i.unlock(); | |
1529 } | |
1530 | |
1531 extern (C) void _d_monitor_devt(Monitor* m, Object h) | |
1532 { | |
1533 if (m.devt.length) | |
1534 { | |
1535 DEvent[] devt; | |
1536 | |
1537 synchronized (h) | |
1538 { | |
1539 devt = m.devt; | |
1540 m.devt = null; | |
1541 } | |
1542 foreach (v; devt) | |
1543 { | |
1544 if (v) | |
1545 v(h); | |
1546 } | |
1547 free(devt.ptr); | |
1548 } | |
1549 } | |
1550 | |
1551 extern (C) void rt_attachDisposeEvent(Object h, DEvent e) | |
1552 { | |
1553 synchronized (h) | |
1554 { | |
1555 Monitor* m = getMonitor(h); | |
1556 assert(m.impl is null); | |
1557 | |
1558 foreach (inout v; m.devt) | |
1559 { | |
1560 if (v is null || v == e) | |
1561 { | |
1562 v = e; | |
1563 return; | |
1564 } | |
1565 } | |
1566 | |
1567 auto len = m.devt.length + 4; // grow by 4 elements | |
1568 auto pos = m.devt.length; // insert position | |
1569 auto p = realloc(m.devt.ptr, DEvent.sizeof * len); | |
1570 if (!p) | |
1571 onOutOfMemoryError(); | |
1572 m.devt = (cast(DEvent*)p)[0 .. len]; | |
1573 m.devt[pos+1 .. len] = null; | |
1574 m.devt[pos] = e; | |
1575 } | |
1576 } | |
1577 | |
1578 extern (C) void rt_detachDisposeEvent(Object h, DEvent e) | |
1579 { | |
1580 synchronized (h) | |
1581 { | |
1582 Monitor* m = getMonitor(h); | |
1583 assert(m.impl is null); | |
1584 | |
1585 foreach (p, v; m.devt) | |
1586 { | |
1587 if (v == e) | |
1588 { | |
1589 memmove(&m.devt[p], | |
1590 &m.devt[p+1], | |
1591 (m.devt.length - p - 1) * DEvent.sizeof); | |
1592 m.devt[$ - 1] = null; | |
1593 return; | |
1594 } | |
1595 } | |
1596 } | |
1597 } |