Reputation: 191
I've got a question regarding WeakReferences.
I'm right now in the process of writing a "Resource Manager" who hast to keep references to created texture objects. I have a Dictionary like:
Dictionary<uint, WeakReference>
Where the first is, as you allready may guessed, the Resource Id and the second param is a WeakReference to the Resource itself.
Right now my Resources do have a method to free themselfes from their Owner (i.e. Resource Manager). They do so in calling a method at the Resource Manger while passing a this reference to it. The ResMgr does lookup if it is a resource he keeps bookmark of and if so, does something like this:
WeakReference result;
if (m_Resources.TryGetValue(ResourceId, out result))
{
if (result.IsAlive)
return;
(result.Target as Resource).free(); // free for good
m_Resources.Remove(ResourceId);
}
The Problem I'm having is that the part after:
if (result.IsAlive)
is never reached because there are still leftover references to the Resource.
The thing is, I do only have one Reference of the Resource in question and it releases itself like:
resource.free(); // calls internally its owner (i.e. ResMgr)
resource = null;
I guess the left over reference would be the "resource" variable, but I cannot set it to null, because I do have to call free first. Quite a dilema...
Well what I wanted to achive with this is a Resource Manager who keeps references to its owning Resources and release them ONLY if there is no reference left to not screw up something.
Any idea how I may solve this in a clean fashion?
PS: Is there a way to actually get the reference count in some way ?
Thanks in advance!
Mfg Imp
Upvotes: 2
Views: 277
Reputation: 532455
I would handle this differently. I might, internally, keep a WeakReference to the object, but I would return a hard reference to it. Consumers shouldn't remove the item from the resource manager unless they know they have the only reference to it and it's not needed. Otherwise, they should simply allow the system to determine when to remove the referenced object. That way, as a long as there is a (hard) reference to the object, it will remain in memory. You might remove it from the dictionary, but you'd only be removing that entry -- i.e., any new requests for it would have to create a new object, even if other consumers had a reference to the old object. The retrieval process should recreate the object if the weak reference isn't live.
public ResourceManager<T>
{
private Dictionary<uint,WeakReference> Cache = new Dictionary<uint,WeakReference>();
public T this[uint key]
{
var obj = (T)this.Cache[key].Target;
if (obj == null)
{
obj = ...recreate resource...
this.Cache[key] = obj;
}
return obj;
}
public void Remove( uint key )
{
this.Cache.Remove(key);
}
}
Upvotes: 2
Reputation: 456487
I recommend you look into caching or a reference count. Weak references were never inteded to be used as a caching system.
There is no "reference count" in .NET; objects are either referenced or they are not. If you need an actual reference count, then I'd recommend building on RefCountDisposable
from the Rx library, which is a reference-counted IDisposable
.
Upvotes: 2
Reputation: 16744
If result.IsAlive is false, then result.Target will be null.
You might want to look at finalizers and/or ConditionalWeakTable, they might help you with a solution.
Upvotes: 1