views:

190

answers:

5

I want to implement some reusable object pool. Also I don't want to have API that puts the object back to pool when it is not needed.

I want to use garbage collector to inform me that it is going to remove the object because it has no references, so that I could stop the object from being garbage collected and put it back to the pool.

A: 

Why not just keep a reference to the object, so that it doesn't get marked for gc?

In response to your question on how the GC knows it isn't in use anymore:

One way of garbage collecting is keeping a reference count. When the reference count reaches 0, the object isn't referred to anymore, and can be Garbage Collected. This is not how .NET implements it however (see Garbage Collection) but it might help to understand the principle a bit better.

Edit: How I understand it, you need a pool of objects that have once been instantiated, and that you can just distribute and collect. Basically you want to implement memory management on top of the GC.

The only reason I can see for wanting to do this is that creating a new instance of the object and making it usable (initializing) takes too much time.

In any case, you could try the traditional unmanaged approach:

Stack pool = new Stack();

// Initialize a few MyObjects
pool.Push( new MyObject() );


// Get an instance of the object from the pool
MyObject obj = (MyObject)pool.Pop();

// Use the object
obj.Foo();

// When you are finished clean up
pool.Push(obj);
obj = null;
Yannick M.
But then how does the pool know if an object is in use or not?
Stephen C
The object is referred to, not 'in use'. If it isn't referred to anymore it can be pickup for gc
Yannick M.
You miss my point. An object pool is a mechanism for keeping track of objects that are not in use by the application, and then handing them out on request. If the pool has no way of telling that the application is no longer using a given object, it cannot safely hand it out again.
Stephen C
A: 

If your Pool class is simply a list of objects you want to have in it, they will never get garbage collected since you always have a reference to the objects in your pool.

Gerrie Schenck
But then how does the pool know if an object is in use or not?
Stephen C
A: 

You're going to find that this is relatively unrealistic. There's no way to have the GC notify you of objects its about to destroy. It sounds like you're trying to manage your own memory space, which is not a task C# is geared towards.

Admittedly, you could do it by using a pool system and a reference count so you would know when your objects were not referred to by anyone. Seems very risky, though.

JustLoren
I don't think there is a realistic way of keeping a reference count yourself.
Yannick M.
A: 

I think that it is theoretically possible to implement a recycling scheme using C# weak references.

The idea is to construct proxies for your managed objects, and issue those proxies when a client requests an object from the pool. The pool holds a hard reference to the real object and a weak reference to the proxy object. (And the proxy has a hard reference to the real object.)

When the application drops a reference to a proxy object it will (eventually) be garbage collected, and (even later) the weak reference in the pool will be broken. Later again, the pool notices that the weak reference holds a null, and can then safely issue a new proxy, create a new weak reference to it and issue it to the application.

In practice, this is really bad idea. For a start, weak references are likely to be expensive for the GC to deal with, and it may take multiple GC cycles for the weak references to be broken. And add the space used by the pool and proxies, and the performance cost of doing operations via proxies. Most likely, the sum of these costs will greatly outweigh any benefits of recycling objects using an object pool.

Stephen C
+1  A: 

I don't think you'll get a satisfactory answer for a pool that will magically return unused objects, or else everyone would be doing it. Java has a ReferenceQueue on which garbage collected objects are placed, but even there I wouldn't recommend depending on GC behaviour.

If you want to avoid having to explicitly release the object from the pool, have you thought of using a callback/delegate function? The API would accept a delegate that would provide the object, and the app can use the object within the delegate. When it finishes, cleanup is guaranteed. (EDIT: I mean it is guaranteed to return to the pool).

class Pool
{
  public delegate void UseResource(Object object);
  public void GetObject(UseResource del)
  {
    Object o = null;
    try {
      o = getFromPool();
      del(o)
    } finally {
      if (o != null) returnToPool(o);
    }
  }
}
Nick
I don't really understand what you mean with cleanup is guaranteed. If you mean the object is returned to the pool, then sure, however there is no reason why the object wouldn't still be referred to externally.
Yannick M.
Yes, I did mean it was returned to the pool. I finished off that sentence a bit quickly without thinking. The contract of the API would have to be that you should only use the provided object within the delegate - if you kept hold of it then behaviour would be undefined, so it might not be appropriate for some uses. That is probably why most APIs have explicitly releasing :)
Nick