3

I want to use an object-pool in my C# application, and I know that there isn't any reference count in C#. If the same object can be passed to several threads, how can I know when there are no more references to the object so that I can return it to the object pool?

I thought of doing it in the dispose method, but that is too late, and it can't be returned to the pool since it is disposed.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
gerstla
  • 587
  • 1
  • 5
  • 20

3 Answers3

7

Implementing object-pool in .Net can be done using a Finalizer.

Actually, most of the pools implemented in .Net are doing this also (for example - DB connection pool).

Using a finalizer allows you to know that the object isn't referenced anymore, as the finalizer is being called after the GC determine that there are not possible routes to the object.

The technique is not to do any destructive methods in your Dispose (i'll be getting this next) and finalize method.

Let's say that you have an PooledObject type, and an ObjectPool type that manages the pool.

In the ObjectPool, add an internal methods called ReturnToPool(PooledObject obj) that will get the object and make it available for other callers.

In the PooledObject type, you should add an internal method called ReleaseResources - which will only be called by the ObjectPool when the entire pool should be removed from memory - in this method you will implement your dispose logic (closing handles, releasing un-managed memory, etc..). In the PooledObject Dispose and Finalize methods you should call the ReturnToPool methods in the ObjectPool (static, or internally stored in the pooled object) - this is called - resurrection. When calling the ReturnToPool method in the finalizer you are actually resurrecting the object and making it available again.

Make sure you are re-registering PooledObject for finalization in the ReturnToPool method in ObjectPool - GC.ReRegisterForFinalize method.

Both of those types should be in the same assembly, of course. (to make sure they can call each other internal methods)

You should however implement the Dispose pattern either way. It will save time when object is not being used anymore (after leaving Using scope for example) and will return the object to the pool.

Hope this helps. Ofir.

Ofir Makmal
  • 501
  • 2
  • 3
  • 7
    This answer is pretty much correct but **be very, very careful** if you implement pooled objects using finalizers. It is very, very easy to make a mistake. Remember, in a finalizer, *none of your usual assumptions are true*. The object might not have been fully constructed. The current thread is not any of your threads. The object is considered dead by the GC. Anything the object refers to might also be dead. And so on. Be *extremely cautious* if you go down this road. I recommend that people return objects to pools explicitly, rather than pursuing a finalization strategy. – Eric Lippert Dec 30 '12 at 18:53
  • You are correct. The finalize is there for cases when the developer is not using Dispose. When using dispose It's an implicit return to the pool and perfectly safe. Wouldn't you agree? – Ofir Makmal Dec 30 '12 at 23:02
1

how can I know when there are no more references to the object so that I can return it to the object pool.

Hm. You implement reference counting.

What also works is a proxy around it that has a Disposable method. WHen done with the Proxy, the dispose implementation puts the inner object to the pool (the outer object tuhs is VERY small).

But at the end you have to know when to release. This is called programming. This only makes sense for "fat" objets with significant initialization overhead, and then you really have to make sure you acutally know when to put them back by logic (i.e. custom counting etc.).

TomTom
  • 61,059
  • 10
  • 88
  • 148
0

It should be in the Close/Release method. Responsibility of creating and disposing the instance lies with the ObjectPool itself.

To request/release an object from/to ObjectPool, use Open/Close or Acquire/Release.

A The Code Project article, C# Object Pooling, presents a nice lightweight custom object pool implementation.

You can also look at Connection Pooling Mechanism of ADO.NET to get hint of an object pooling example.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tilak
  • 30,108
  • 19
  • 83
  • 131