Vani said:
A, B, C components will all be calling S1 which remains available
commonly available (S1 will be a Singleton - non-instantiable Class
with all methods as static). The web application is not supposed to be
That's not the singleton pattern from the GOF book.
The singleton from GOF would be:
public class S1 {
public static S1 Intance = new S1();
protected S1() {};
public T f(...);
}
Only one static, the "instance" operation.
For the clean up task to remove items from the DataTable, I am
thinking of keeping another thread running, which will, time to time,
look for items (filter via dataview) where (current time -
lastaccessed) = greater than a set timeout value and delete those
items.
Usually caching means keeping N instances around, not just removing
"too-old" ones.
Is there any better way to do this?
Dunno... why don't you keep cache in memory?
ArrayList will not be appropriate I think because moving items around
might be an overhead and because I need to access items by that key
value.
You would can use two data-structures, an IDictionary for the key-based
lookup and a another where the objects are sorted after their
last-accessed property (this is also what a database would do for
multiple-indexed data).
You could also do something like in the attached file, using a bit more
memory (3 refs pr. node) to get a runtime-efficient impl, but if you can
live with having the cache-data in a databse-like thingy you probably
don't need that.
--
Helge Jensen
mailto:
[email protected]
sip:
[email protected]
-=> Sebastian cover-music:
http://ungdomshus.nu <=-
using System;
using System.Collections;
namespace cache
{
public class LinkedValueDictionary: IDictionary
{
protected IDictionary backend;
protected Value first;
protected Value last;
public class Value
{
public readonly object V;
public readonly object K;
public Value Previous;
public Value Next;
public Value(object k, object v, Value prev, Value next)
{
this.K = k;
this.V = v;
this.Previous = prev;
this.Next = next;
}
}
public LinkedValueDictionary(IDictionary backend) { this.backend = backend; }
#region IDictionary Members
public bool IsReadOnly { get { return backend.IsReadOnly; } }
class DictionaryEnumerator: IDictionaryEnumerator
{
IDictionaryEnumerator it;
public DictionaryEnumerator(IDictionaryEnumerator it) { this.it = it; }
#region IDictionaryEnumerator Members
public object Key { get { return it.Key; } }
public object Value { get { return ((Value)it.Value).V; } }
public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } }
#endregion
#region IEnumerator Members
public void Reset() { it.Reset(); }
public object Current { get { return Entry; } }
public bool MoveNext() { return it.MoveNext(); }
#endregion
}
public IDictionaryEnumerator GetEnumerator() { return new DictionaryEnumerator(backend.GetEnumerator()); }
protected void BringToFront(Value v)
{
v.Previous.Next = v.Next;
v.Previous = null;
v.Next = first;
first = v;
}
public virtual object this[object key]
{
get
{
Value v = (Value)backend[key];
if ( v.Previous != null )
BringToFront(v);
return v.V;
}
set
{
if ( Contains(key) )
Remove(key);
Value v = new Value(key, value, null, first);
if ( first == null )
{
first = v;
last = v;
}
else
first.Previous = v;
first = v;
}
}
public void Remove(object key)
{
Value v = (Value)backend[key];
if ( v.Next == null )
last = v.Previous;
else
v.Next.Previous = v.Previous;
if ( v.Previous == null )
first = v.Next;
else
v.Previous.Next = v.Next;
}
public bool Contains(object key) { return backend.Contains(key); }
public void Clear()
{
backend.Clear();
first = null;
last = null;
}
class ValueCollection: ICollection
{
public readonly LinkedValueDictionary LVD;
public ValueCollection(LinkedValueDictionary lvd) { this.LVD = lvd; }
#region ICollection Members
public bool IsSynchronized { get { return LVD.backend.Values.IsSynchronized; } }
public int Count { get { return LVD.backend.Values.Count; } }
public void CopyTo(Array array, int index)
{
foreach ( Value v in LVD.backend.Values )
array.SetValue(v, ++index);
}
public object SyncRoot { get { return LVD.backend.Values.SyncRoot; } }
#endregion
#region IEnumerable Members
class Enumerator: IEnumerator
{
IEnumerator it;
public Enumerator(IEnumerator it) { this.it = it; }
#region IEnumerator Members
public void Reset() { it.Reset(); }
public object Current { get { return ((Value)it.Current).V; } }
public bool MoveNext() { return it.MoveNext(); }
#endregion
}
public IEnumerator GetEnumerator() { return new Enumerator(LVD.Values.GetEnumerator()); }
#endregion
}
public ICollection Values { get { return new ValueCollection(this); } }
public void Add(object key, object value)
{
if ( Contains(key) )
throw new ArgumentException("Already contains key");
else
this[key] = value;
}
public ICollection Keys { get { return backend.Keys; } }
public bool IsFixedSize { get { return backend.IsFixedSize; } }
#endregion
#region ICollection Members
public bool IsSynchronized { get { return backend.IsSynchronized; } }
public int Count { get { return backend.Count; } }
public void CopyTo(Array array, int index)
{
foreach ( DictionaryEntry e in this )
array.SetValue(e, index++);
}
public object SyncRoot { get { return backend.SyncRoot; } }
#endregion
#region IEnumerable Members
IEnumerator System.Collections.IEnumerable.GetEnumerator() { return new DictionaryEnumerator(backend.GetEnumerator()); }
#endregion
public class LinkedCollection: ICollection
{
public readonly LinkedValueDictionary LVD;
public LinkedCollection(LinkedValueDictionary lvd) { this.LVD = lvd; }
#region ICollection Members
public bool IsSynchronized { get { return LVD.IsSynchronized; } }
public int Count { get { return LVD.Count; } }
public void CopyTo(Array array, int index) { LVD.Values.CopyTo(array, index); }
public object SyncRoot { get { return LVD.SyncRoot; } }
#endregion
#region IEnumerable Members
abstract public class Enumerator: IEnumerator
{
public readonly LinkedValueDictionary LVD;
public IEnumerator it; // Used to guarantee exception on mutation
public Value current;
protected Enumerator(LinkedValueDictionary lvd)
{
this.LVD = lvd;
Reset();
}
#region IEnumerator Members
public void Reset()
{
it.Reset();
current = null;
}
public object Current
{
get
{
if ( current == null )
throw new IndexOutOfRangeException();
else
return current;
}
}
protected abstract void Next();
public bool MoveNext()
{
bool hasnext = it.MoveNext();
if ( hasnext )
Next();
return hasnext;
}
#endregion
}
public class Forward: Enumerator
{
public Forward(LinkedValueDictionary lvd): base(lvd) {}
protected override void Next()
{
if ( current == null )
current = LVD.first;
else
current = current.Next;
}
}
public class Backward: Enumerator
{
public Backward(LinkedValueDictionary lvd): base(lvd) {}
protected override void Next()
{
if ( current == null )
current = LVD.last;
else
current = current.Previous;
}
}
public IEnumerator GetEnumerator() { return GetForwardEnumerator(); }
#endregion
public Forward GetForwardEnumerator() { return new Forward(LVD); }
public Backward GetBackwardEnumerator() { return new Backward(LVD); }
}
LinkedCollection Linked { get { return new LinkedCollection(this); } }
}
public class RecentlyReadOrdered: LinkedValueDictionary
{
public RecentlyReadOrdered(IDictionary backend): base(backend) {}
public override object this[object key]
{
get
{
Value v = (Value)backend[key];
if ( v.Previous != null )
BringToFront(v);
return v.V;
}
set { base[key] = value; }
}
}
}