public class ObjectEnter:IDisposable
{
private string mOwnerID;
static ObjectEnter()
{
Core.Functions.Action(CheckExpires);
}
public ObjectEnter(string id)
{
mOwnerID = Guid.NewGuid().ToString("N");
mID = id;
Enter(mOwnerID, id, 60000);
}
public ObjectEnter(string id, int milliseconds)
{
mOwnerID = Guid.NewGuid().ToString("N");
mID = id;
Enter(mOwnerID, id, milliseconds);
}
private string mID = null;
private static Dictionary<string, LockItem> mObjectTable = new Dictionary<string, LockItem>(100);
public static void TryEnter(string id, Smark.Core.AsyncDelegate<string,bool> lockhandler)
{
TryEnter(id, 60000, 30000, lockhandler);
}
public static void TryEnter(string id, int milliseconds, int timeout, Smark.Core.AsyncDelegate<string,bool> lockhandler)
{
string owner = Guid.NewGuid().ToString("N");
if(lockhandler!=null)
lockhandler(owner,TryEnter(owner, id, milliseconds, timeout));
}
public static bool TryEnter(string owner, string id, int milliseconds, int timeout)
{
QueueState state = new QueueState();
state.EntrerMilliseconds = milliseconds;
state.TimeOut = timeout;
if (!GetLockItem(id).Enter(owner, milliseconds, state))
{
state.Handler.Reset();
state.Handler.WaitOne(state.TimeOut);
return GetLockItem(id).Enter(owner, milliseconds, null);
}
else
{
return true;
}
}
public static void Enter(string owner,string id, int milliseconds)
{
QueueState state = new QueueState();
state.EntrerMilliseconds = milliseconds;
if (!GetLockItem(id).Enter(owner, milliseconds, state))
{
state.Handler.Reset();
state.Handler.WaitOne();
}
}
public static void Exit(string owner,string id)
{
if (mObjectTable.ContainsKey(id))
mObjectTable[id].Exit(owner);
}
private static LockItem GetLockItem(string id)
{
lock (mObjectTable)
{
LockItem item = null;
if (!mObjectTable.ContainsKey(id))
{
item = new LockItem();
item.ID = id;
mObjectTable.Add(id, item);
}
else
{
item = mObjectTable[id];
}
return item;
}
}
private static void CheckExpires()
{
while (true)
{
lock (mObjectTable)
{
foreach (System.Collections.Generic.KeyValuePair<string, LockItem> item in mObjectTable)
{
item.Value.Expires();
}
}
System.Threading.Thread.Sleep(5000);
}
}
class LockItem
{
const string SYSTEM_ID = "SYSTEM_4EB49CA1-7470-44af-94DE-B2128B9B5BA9";
public LockItem()
{
}
public bool Enter(string owner, int milliseconds, QueueState handler)
{
lock (this)
{
if (Count>0 && owner != Owner)
{
if (handler != null)
EnterWait(handler);
return false;
}
Count++;
EntrerMilliseconds = milliseconds;
EnterTime = DateTime.Now;
return true;
}
}
private void EnterWait(QueueState handler)
{
lock (mWaitHandle)
{
mWaitHandle.Enqueue(handler);
}
}
private Queue<QueueState> mWaitHandle = new Queue<QueueState>();
public void Exit(string owner)
{
lock (this)
{
if (owner == SYSTEM_ID)
{
Owner = null;
Count = 0;
}
else
{
if (owner == Owner)
{
Count--;
}
}
if (Count == 0)
{
lock (mWaitHandle)
{
if (mWaitHandle.Count > 0)
{
QueueState state = mWaitHandle.Dequeue();
state.Handler.Set();
}
}
}
}
}
public int EntrerMilliseconds
{
get;
set;
}
public DateTime EnterTime
{
get;
set;
}
public string ID
{
get;
set;
}
public string Owner
{
get;
set;
}
public int Count
{
get;
set;
}
public void Expires()
{
lock (this)
{
TimeSpan ts = DateTime.Now - EnterTime;
if (ts.TotalMilliseconds > EntrerMilliseconds)
Exit(SYSTEM_ID);
}
}
}
#region IDisposable 成员
private bool mDisposed = false;
public void Dispose()
{
lock (this)
{
if (!mDisposed)
{
Exit(mID,mOwnerID);
mDisposed = true;
}
}
}
#endregion
}
class QueueState
{
public QueueState()
{
EntrerMilliseconds = 60000;
}
public bool Idle
{
get;
set;
}
public int EntrerMilliseconds
{
get;
set;
}
public int TimeOut
{
get;
set;
}
private System.Threading.EventWaitHandle mHandler = new EventWaitHandle(false, EventResetMode.ManualReset);
public System.Threading.EventWaitHandle Handler
{
get
{
return mHandler;
}
}
}