アットウィキロゴ

キャッシュ

#contents

Generic Type Caching

generic & static なクラスをキャッシュとして使うことである。
型引数が key、static メンバが value に相当する。
静的コンストラクタは、クラスの呼び出し時に1回だけ実行され、スレッドセーフである。
そして、型引数はコンパイル時に解決されるため、Dictionary などの動的な key ルックアップと比べて、圧倒的に早い。 new { 変数名 }.GetType().GetProperties()[0].Nameで変数名を文字列で取得できる。

 private static class GenericCache<T>
   {
       public static string GetName<T>(this T source) where T : class
       {
           return GenericCache<T>.Name;
       }
       static GenericCache()
       {
           var properties = typeof(T).GetProperties();
           Name = properties[0].Name;
       }
       public static readonly string Name;
       
   }

MyCacheを作ってみる。

  • Dictionaryでkeyにオブジェクトなんかを入れている場合、そのkeyがGC対象になったときにvalueもGC対象にする
  • 変数(フィールドやらローカル変数やら)に格納されている参照のことを「強い参照」と言う。
    「アクセス可能なオブジェクト」とは、強い参照が存在するオブジェクトのことを言う。
    ただし、その強い参照を所持しているオブジェクトもアクセス可能なオブジェクトである必要がある。
    つまり、強い参照を所持しているオブジェクトを辿って行くとアクセス不可能なオブジェクトに辿り着く場合、
    それらは全てアクセス不可能なオブジェクトである。
    また、実際にアクセスされている最中(コンストラクタ実行中だったりメソッド実行中だったり)のオブジェクトも、~アクセス可能なオブジェクトである。~
  • 「オブジェクトを使いたいんだけども、GC 的には参照していることにしないでほしい」、
    「自分以外が全員参照を手放したらその時点で削除対象にしてほしい」というような要件がまれにあります。
    こういう、GC の参照探索上は除外してほしい参照を、弱参照(weak reference)といいます。
 public class MyCache<K,T>
   {
       private Dictionary<K, WeakReference> cache = new Dictionary<K, WeakReference>();
       private object locker = new object();
       public T GetItem(K key)
       {
           lock (locker)
           {
               WeakReference v;
               if (!cache.TryGetValue(key, out v)) return default(T);
               T val = (T)v.Target;
               if (val != null) return val;
               cache.Remove(key);
               return default(T);
           }
       }
       public void Add(K key, T val)
       {
           lock (locker)
           {
               cache[key] = new WeakReference(val);
           }
       }
   }
最終更新:2015年08月23日 21:40