I am trying to write a caching class similar to the one in
System.Web.Caching. The class will be a generic class but I am writing it
with the the following application in mind:-

I have written an LDAP library for Active Directory that allows fast
searching and creation of C# classes to represent the AD objects.

1) If searchA returns 200 objects and searchB returns 10 objects which have
already been retrieved by searchA, then I want to ensure that the same
object instance is used.

2) In certain cases, I want to be able to provide a read-ahead cache. An
example of this is a speed-up of calculating nested memberships. (In a
previous VB app, instead of recursing each nested membership down to its
deepest level and then moving onto the next which involves thousands of
small searches returning 1 or 2 objects, I made a list of all of the 'next-
level' memberships and searched for them en-masse before continuing with
the normal recursion - this way the objects I am looking for are already in
the cache and no further access to the AD is required. The size of the
searches increases (I have had a search expression of 500K before now!) but
the number of searches is then limited to the deepest nesting level -
typically 3 or 4)

I thought that I could achieve this by storing the cached items in a
wrapper that, as well as expiration date/access count/priority info etc.,
stores the object reference in a WeakReference object. This way, if the
unused pre-cached items had been garbage collected to free memory, I could
write the Cache classes retrieval code to silently remove the wrapper and
inform the app that they are not in the cache and subsequent searches would
look in the AD in the normal way.

However, I found that even for relatively small searches of a couple of
thousand items, when I inspected the cache I found that a large number had
been collected by the GC if a strong reference was not present elsewhere.
(I thought that a GC only occurred when memory was scarce - on a
workstation at least - I know that server works differently).

I am trying to think of a good solution to this and this is all I could
come up with is this:
- In the CachedItem wrapper, initially store the object to be cached
directly in an object variable.
- Have a System.Timers.Timer object in the cache instance that starts a
maintenance event periodically.
- The maintenance event goes through each of the wrappers and checks the
stored reference. If it is not a WeakReference and sufficient time has
passed since the object was first stored, then put the object reference
into a WeakReference and store that instead.
- Change the retrieval code to extract the real reference from the
WeakReference if one is present.

This way I can guarantee that a pre-cached item, regardless of whether a
strong reference exists elsewhere in the application, will remain in the
cache for at least a specified period of time.

Can anyone offer a better way of doing this?

Cheers
Simon

You can read messages from the Advanced DOTNET archive, unsubscribe from Advanced 
DOTNET, or
subscribe to other DevelopMentor lists at http://discuss.develop.com.

Reply via email to