D doesn't have weak references. So how can I make a associative array of objects without preventing their destruction?

Liam McGillivray yoshi.pit.link.mario at gmail.com
Thu May 9 00:39:49 UTC 2024


A "weak reference" (in the sense that I'm referring to) is a 
feature in some programming languages for a reference to an 
object that doesn't prevent the GC from destroying that object.

My current understanding is that D doesn't have weak references, 
though I've found some posts in this forum from many years back 
that mention something called "weakref". So is weakref a real 
thing, or just a concept that never got implemented?

The functionality that I'm going to describe would be easy with 
weak references, but I don't know how I would implement it 
without it. If there is a way to implement it without it, I would 
like to know how. I am going to describe my specific example, but 
it may apply to any class that's initialized using contents of a 
file without any of that data being modified after.

In my particular case, the class I've created is a wrapper for 
the `Texture2D` struct in Raylib. This class holds an image that 
was loaded from a file.

```
Sprite[string] spritesByPath;

Sprite getSprite(string path) {
     path = path.asAbsolutePath;

     if (path !in spritesByPath) {
         spritesByPath[path] = new Sprite(path);
     }

     return spritesByPath[path];
}

class Sprite
{
     Texture2D texture;
     alias this = texture;
     string path;

     this(string path) {
         texture = LoadTexture(path.toStringz);
         this.path = path;
     }

     ~this() {
         if (IsWindowReady) UnloadTexture(texture);
         if (path in spritesByPath) spritesByName.remove(path);
     }
}
```

Alternatively, `spritesByPath` and `getSprite` may be static 
members of `Sprite`.

If D had weak references, than `spritesByPath` would be made of 
weak references so that they don't prevent the destruction of 
`Sprite` objects, which should be destroyed whenever they don't 
have any references elsewhere.

I've considered making `Sprite` reference-counted, but I couldn't 
manage to figure out how to do it properly. I tried doing 
`SafeRefCounted!Sprite` but the compiler said it doesn't work on 
`Object` types. I then tried making my own struct for reference 
counting that would be placed in place of a direct reference to 
the `Sprite` object, but there was some bug in which sometimes it 
didn't increment the reference count, so it didn't work.

What's a good way I can achieve what I'm trying to do, using 
either reference counting or a garbage-collected object?


More information about the Digitalmars-d-learn mailing list