ANN: WeakObjectReference - class to hold weak references

Robert Fraser fraserofthenight at gmail.com
Sun Jun 24 12:17:55 PDT 2007


Awesome! If you have the time, do you think you could do a Tango version too? I think Tango doesn't have object.notifyRegister() though...

Thanks,
Best of wishes,
Fraser

Myron Alexander Wrote:

> Hello.
> 
> I recently had a need for weak references and, with the help of Bill 
> Baxter, who pointed me in the right direction, I created the attached class.
> 
> Its using the apache license so have fun. If you want to add it to 
> Tango, or Phobos and need the license changed, just drop me a note.
> 
> Best regards,
> 
> Myron.
> dprogramming...myron...alexander...com
> replace the first ... with @, remove the second, and replace the third 
> with ".".
> 
> /+
> Create a WeakReference to an Object such that the GC will not be prevented
> from collecting the referenced object.
> 
> Copyright 2007 Myron Alexander
> 
> Licensed under the Apache License, Version 2.0 (the "License");
> you may not use this file except in compliance with the License.
> You may obtain a copy of the License at
> 
>    http://www.apache.org/licenses/LICENSE-2.0
> 
> Unless required by applicable law or agreed to in writing, software
> distributed under the License is distributed on an "AS IS" BASIS,
> WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> See the License for the specific language governing permissions and
> limitations under the License.
> +/
> 
> import std.stdio;
> import std.string : str = toString;
> 
> import stdlib = std.c.stdlib;
> 
> class WeakObjectReference(T : Object) {
> 
>    this (T obj) {
>       /* Get a pointer to the object referenced. The pointer is necessary as
>        * I do not what type to declare a pointer to a reference (ie T*->T).
>        * I tried T*T but that doesn't work. The T** implementation works but
>        * out of curiosity, it would be nice to know if something like T*T could
>        * be done.
>        */
>       T* p = cast(T*)obj;
> 
>       /* Allocate a non-gc region of memory to store the pointer to the object.
>        * The type is T** as it is: memptr -> T* -> obj.
>        */
>       weakObjRef = cast(T**)stdlib.malloc (p.sizeof);
> 
>       debug {
>          writefln ("%s", weakObjRef);
>          writefln ("%s", p);
>          writefln ("%s", &obj);
>       }
> 
>       /* Set memptr->T* = address of obj reference.
>        */
>       *weakObjRef = p;
> 
>       /* Request that the GC call the unhook delegate when the referenced object
>        * is collected. The unhook delegate removes the pointer to the object.
>        * This is very important otherwise we would maintain a pointer to a
>        * non-existant object.
>        */
>       obj.notifyRegister (&unhook);
>    }
> 
>    ~this () {
>       debug {
>          writefln ("Destructing weak reference ...");
>       }
>       /* Remove the object destruction notification delegate as we will no
>        * longer maintain a link to that object.
>        */
>       if (*weakObjRef != null) {
>          debug {
>             writefln ("... Unhooked ...");
>          }
>          (cast(T)(*weakObjRef)).notifyUnRegister(&unhook);
>          *weakObjRef = null;
>       }
> 
>       /* Free the non-gc memory allocated in the constructor.
>        */
>       stdlib.free (weakObjRef);
> 
>       debug {
>          writefln ("... Done");
>       }
>    }
> 
>    T get () {
>       debug {
>          writefln ("Getting pointer: %s", /*weakObjRef == null ? "NULL" :*/ *weakObjRef);
>       }
>       return cast(T)(*weakObjRef);
>    }
> 
>    private void unhook (Object obj) {
>       debug {
>          writefln ("Unhook object");
>       }
>       *weakObjRef = null;
>    }
> 
>    private T** weakObjRef;
> }
> 
> class AnException : Exception {
>    this (string msg) {
>       super (msg);
>    }
> }
> 
> void main () {
> 
>    AnException x = new AnException ("Boom");
>    writefln ("%s", &x);
>    writefln ("%s", cast (AnException*)x);
>    AnException *xp = cast (AnException*)(x);
>    writefln ("EX0: %s", (cast(AnException)xp).toString);
> 
>    auto w = new WeakObjectReference!(AnException) (x);
>    //xp = w.get ();
>    AnException y = w.get ();
>    if (y !is null) {
>       //AnException xx = cast(AnException)xp;
>       writefln ("EX1: %s", y.toString());
>    }
>    delete x;
>    y = w.get ();
>    if (y !is null) {
>       writefln ("EX2: %s", y.toString());
>    } else {
>       writefln ("EX2: y is null");
>    }
> }
> 




More information about the Digitalmars-d-announce mailing list