Thread overview
weak pointers for Objects and delegates pointing to Objects
Oct 25, 2006
Thomas Kuehne
Oct 26, 2006
Bill Baxter
Oct 26, 2006
Thomas Kuehne
October 25, 2006
Who said D didn't support weak pointers?

# private import internal.gc.gcbits;
# private import internal.gc.gclinux;
# private import internal.gc.gcx;
# private import std.utf;
# private import std.gc;
#
# class WeakPointerException : Exception{
#    this(char[] msg){
#    	super(msg);
#    }
# }
#
# class WeakPointer(T){
#    private size_t[] hidden;
#
#    this(T data){
#    	Object o;
#    	static if(is(T == delegate)){
#    		o = getObject(data.ptr);
#    	}else static if(is(T : Object)){
#    		o = data;
#    	}else{
#    		static assert(0, "only delegates and Objects are supported");
#    	}
#
#    	if(!o){
#    		throw new WeakPointerException("destination not an Object");
#    	}
#
#    	synchronized(o){
#    		hidden = new size_t[T.sizeof];
#    		ubyte[] raw = (cast(ubyte*)&data)[0 .. T.sizeof];
#    		foreach(size_t i, ubyte element; raw){
#    				hidden[i] = element;
#    		}
#
#    		o.notifyRegister(&dead);
#    	}
#    }
#
#    void dead(Object o){
#    	if(hidden.length && !o){
#    		static if(is(T == delegate)){
#    			(cast(Object)get().ptr).notifyUnRegister(&dead);
#    		}else{
#    			get().notifyUnRegister(&dead);
#    		}
#    	}
#    	hidden.length = 0;
#    }
#
#    private static Object getObject(void* ptr){
#    	gc_t handle = cast(gc_t) getGCHandle();
#    	Gcx* engine = handle.gcx;
#
#    	Pool* pool = engine.findPool(ptr);
#    	if(!pool){
#    		return null;
#    	}
#
#    	Object o = cast(Object) ptr;
#    	if(!o){
#    		return null;
#    	}
#
#    	ClassInfo ci = o.classinfo;
#    	if(!ci){
#    		return null;
#    	}
#
#    	if(ci.name.length > (1 << 12)){
#    		return null;
#    	}
#
#    	try{
#    		std.utf.validate(ci.name);
#    	}catch{
#    		return null;
#    	}
#
#    	return o;
#    }
#
#    T get(){
#    	if(hidden.length < T.sizeof){
#    		throw new WeakPointerException("delegate isn't valid anymore");
#    	}
#    	T result;
#    	ubyte[] raw = (cast(ubyte*)&result)[0 .. T.sizeof];
#    	foreach(size_t i, size_t element; hidden){
#    		raw[i] = cast(ubyte)element;
#    	}
#    	return result;
#    }
#
#    ~this(){
#    	dead(null);
#    }
# }

Usage sample:

# import std.stdio;
#
# int main(){
#    WeakPointer!(Object) weak;
#
#    {
#    	auto Object o = new Object();
#    	weak = new WeakPointer!(typeof(o))(o);
#
#    	try{
#    		weak.get();
#    		writefln("WEAK: is valid");
#    	}catch{
#    		writefln("WEAK: isn't valid");
#    	}
#    }
#
#    try{
#    	weak.get();
#    	writefln("WEAK: is valid");
#    }catch{
#    	writefln("WEAK: isn't valid");
#    }
#
#    return 0;
# }

Don't be irritated by additional output. http://d.puremagic.com/issues/show_bug.cgi?id=457

Thomas


October 26, 2006
Thomas Kuehne wrote:

> Who said D didn't support weak pointers?

So is this "problem solved?"  Are there any issues or limitations with the weak pointer code you posted?  If not, Great!

Weak refs were one of the last pieces of the puzzle for implementing rock-solid signals/slots from what I understood.

--bb

October 26, 2006
Bill Baxter schrieb am 2006-10-26:
> Thomas Kuehne wrote:
>
>> Who said D didn't support weak pointers?
>
> So is this "problem solved?"  Are there any issues or limitations with the weak pointer code you posted?  If not, Great!

Limitation:
Only objects and delegates pointing to object member functions are
supported.

I haven't yet looked through the GC code, but adding support
for all GC allocated types ought to be possible without major changes
there. Weak pointers to array elements though will most likely be impossible
without major changes.

Using GCC/GDC's "-finstrument-functions" should allow weak pointers for
all types stored on the stack as a pure library implementation. For
DMD that would require "-profile" as well as hijacking internal/trace.d.

Thomas