I have created an open source memory cache called cachew and can be found here: cachew. I would like your help to make it better.
Regarding the class Cache
or its dependencies:
- I am thinking of removing
timeoutStyle
and timeout from theCache
constructor and providing default values that can be changed via public properties. How do you like that? - How do you like my abstraction
LockManager
forReaderWriterLockSlim
? - Do you think my timer in
Cache
should be configurable? Through a property in cache, change internal to public or by another method? - Do you think it is a bad practice to start a timer in a constructor? If so, what would you do?
- Would you consider the Cache threadsafe? Could it be better implemented?
public enum TimeoutStyle
{
FixedTimeout,
RenewTimoutOnQuery
}
public class Cache : ICache
{
private readonly ITimer expirationTimer;
private readonly IInternalCache internalCache;
private readonly LockManager lockManager = new LockManager();
public Cache(TimeoutStyle timeoutStyle, TimeSpan timeout) :
this(new InternalCache(timeoutStyle, timeout), new SystemTimer(5000))
{
}
internal Cache(IInternalCache iternalCache, ITimer expirationTimer)
{
if (iternalCache == null) throw new ArgumentNullException("iternalCache");
if (expirationTimer == null) throw new ArgumentNullException("expirationTimer");
this.internalCache = iternalCache;
this.expirationTimer = expirationTimer;
this.expirationTimer.Elapsed += ExpirationTimerElapsed;
this.expirationTimer.Start();
}
public object Get<T>(CacheKey key, Func<T> func)
{
using (lockManager.EnterRead())
{
object existingValue;
if (internalCache.TryGetValue(key, out existingValue))
return existingValue;
}
using (lockManager.EnterWrite())
{
object existingValue;
if (internalCache.TryGetValue(key, out existingValue))
return existingValue;
var newValue = func();
internalCache.Add(key, newValue);
return newValue;
}
}
private void ExpirationTimerElapsed(object sender, EventArgs e)
{
using (lockManager.EnterWrite())
{
internalCache.RemoveExpiredItems();
}
}
}
.Start()
is the last line of the constructor, but the compiler or JIT may reorder things. \$\endgroup\$