1 /*==========================================================================
2  * weakref.d
3  *    Written in the D Programming Language (http://www.digitalmars.com/d)
4  */
5 /***************************************************************************
6  * Creates a weak reference to a class instance.
7  *
8  * A weak reference lets you hold onto a pointer to an object without
9  * preventing the garbage collector from collecting it.
10  * If the garbage collector collects the object then the weak pointer will
11  * become 'null'.  Thus one should always check a weak pointer for null
12  * before doing anything that depends upon it having a value.
13  *
14  * Tested with:
15  *    DMD 1.025 / Phobos 1.025
16  *    DMD 1.025 / Tango 0.99.4
17  *
18  * Usage example:
19 ---
20  class Something {}
21 
22  auto a = new Something();
23  auto wa = new WeakRef!(Something)(a);
24  std.gc.fullCollect();
25 
26  // Reference 'a' prevents collection so wa.ptr is non-null
27  assert(wa.ptr is a);
28 
29  delete a;
30 
31  // 'a' is gone now, so wa.ptr magically becomes null
32  assert(wa.ptr is null);
33 ---
34  *
35  *
36  * Author:  William V. Baxter III
37  * Contributors:
38  * Date: 21 Jan 2008
39  * Copyright: (C) 2008  William Baxter
40  * License: Public Domain where allowed by law, ZLIB/PNG otherwise.
41  */
42 //===========================================================================
43 
44 module java.nonstandard.WeakRef;
45 
46 private {
47     alias void delegate(Object) DisposeEvt;
48     extern (C) void  rt_attachDisposeEvent( Object obj, DisposeEvt evt );
49     extern (C) void  rt_detachDisposeEvent( Object obj, DisposeEvt evt );
50 }
51 
52 class WeakRef(T : Object) {
53 private:
54     size_t cast_ptr_;
55     void unhook(Object o) {
56         if (cast(size_t)cast(void*)o == cast_ptr_) {
57             rt_detachDisposeEvent(o, &unhook);
58             cast_ptr_ = 0;
59         }
60     }
61 public:
62 
63     this(T tptr) {
64         cast_ptr_ = cast(size_t)cast(void*)tptr;
65         rt_attachDisposeEvent(tptr, &unhook);
66     }
67     ~this() {
68         T p = ptr();
69         if (p) {
70             rt_detachDisposeEvent(p, &unhook);
71         }
72     }
73     T ptr() {
74         return cast(T)cast(void*)cast_ptr_;
75     }
76     WeakRef dup() {
77         return new WeakRef(ptr());
78     }
79     equals_t opEquals( Object o ){
80         if( auto other = cast( WeakRef!(T) )o ){
81             return other.cast_ptr_ is cast_ptr_;
82         }
83         return false;
84     }
85     hash_t toHash(){
86         return cast_ptr_;
87     }
88 }