www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - ANN: WeakObjectReference - class to hold weak references

reply Myron Alexander <someone somewhere.com> writes:
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 ".".
Jun 23 2007
next sibling parent reply Myron Alexander <someone somewhere.com> writes:
Hello.

There is a bug in the version. I just noticed it now. When I rewrote the 
test code into a class, I accidentally left out the check on the malloc 
return. I have to go somewhere now so I'll fix it later.

After:
    weakObjRef = cast(T**)stdlib.malloc (p.sizeof);

just add:
    if (null == weakObjRef) {
      _d_OutOfMemory ();
    }

and then import std.outofmemory.

Sorry,

Myron.
Jun 23 2007
parent Myron Alexander <someone somewhere.com> writes:
Myron Alexander wrote:
 There is a bug in the version. I just noticed it now. When I rewrote the 
 test code into a class, I accidentally left out the check on the malloc 
 return. I have to go somewhere now so I'll fix it later.
I have attached the fixed version. Regards, Myron.
Jun 23 2007
prev sibling next sibling parent Extrawurst <spam extrawurst.org> writes:
i would attach the fixed version for the lazy guys who dont recognize 
the post with the fix ;)


Myron Alexander schrieb:
 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 ".".
Jun 23 2007
prev sibling parent Robert Fraser <fraserofthenight gmail.com> writes:
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");
    }
 }
 
Jun 24 2007