OSDN Git Service

c98e53ae649a32e97bfac1d772afcc4685b8a65e
[wptscs/wpts.git] / HmLib / Utilities / LockObject.cs
1 // ================================================================================================
2 // <summary>
3 //      ロック用のオブジェクトを提供するクラスソース</summary>
4 //
5 // <copyright file="LockObject.cs" company="honeplusのメモ帳">
6 //      Copyright (C) 2012 Honeplus. All rights reserved.</copyright>
7 // <author>
8 //      Honeplus</author>
9 // ================================================================================================
10
11 namespace Honememo.Utilities
12 {
13     using System;
14     using System.Collections.Concurrent;
15     using System.Collections.Generic;
16
17     /// <summary>
18     /// ロック用のオブジェクトを提供するクラスです。
19     /// </summary>
20     /// <remarks>このクラスはスレッドセーフです。</remarks>
21     public class LockObject
22     {
23         #region private変数
24
25         /// <summary>
26         /// ハッシュに対応するロックオブジェクト。
27         /// </summary>
28         private IDictionary<int, object> locks = new ConcurrentDictionary<int, object>();
29
30         #endregion
31
32         #region パラメータ単位のロック用メソッド
33         
34         /// <summary>
35         /// パラメータのハッシュに対応するロックオブジェクトを返す。
36         /// </summary>
37         /// <param name="param">ロックの単位となるパラメータ。</param>
38         /// <returns>対応するロックオブジェクト。</returns>
39         /// <exception cref="ArgumentNullException"><paramref name="param"/>が<c>null</c>。</exception>
40         /// <remarks>
41         /// パラメータのハッシュ取得には<see cref="Object.GetHashCode"/>を使用する。
42         /// </remarks>
43         public object GetObject(object param)
44         {
45             // ロックオブジェクトを取得、この時点では特にロック不要
46             // ※ ConcurrentDictionaryを使用しており、一回の処理で更新しているため
47             int hashcode = Validate.NotNull(param, "param").GetHashCode();
48             object lockObject;
49             if (this.locks.TryGetValue(hashcode, out lockObject))
50             {
51                 return lockObject;
52             }
53
54             // 存在しない場合、ロックを行い念のためキャッシュを再確認
55             lock (this.locks)
56             {
57                 if (this.locks.TryGetValue(hashcode, out lockObject))
58                 {
59                     return lockObject;
60                 }
61
62                 // それでも無ければ、ハッシュに対応するロックオブジェクトを作成して返す
63                 lockObject = new object();
64                 this.locks[hashcode] = lockObject;
65             }
66
67             return lockObject;
68         }
69
70         #endregion
71     }
72 }