1 /* Copyright (C) 2009 Versant Inc.   http://www.db4o.com */
2 
3 using System;
4 using System.Threading;
5 
6 namespace Db4objects.Db4o.Foundation
7 {
8 #if CF
9     public class Lock4
10     {
11         private volatile Thread lockedByThread;
12 
13         private volatile Thread waitReleased;
14         private volatile Thread closureReleased;
15 
16     	readonly AutoResetEvent waitEvent = new AutoResetEvent(false);
17     	readonly AutoResetEvent closureEvent = new AutoResetEvent(false);
18 
Awake()19 		public void Awake()
20 		{
21 			AwakeWait();
22 		}
23 
Run(IClosure4 closure4)24 		public Object Run(IClosure4 closure4)
25         {
26 			EnterClosure();
27             try
28             {
29                 return closure4.Run();
30             }
31             finally
32             {
33                 AwakeClosure();
34             }
35         }
36 
Snooze(long timeout)37 		public void Snooze(long timeout)
38 		{
39 			AwakeClosure();
40 			WaitWait(timeout);
41 			EnterClosure();
42 		}
43 
EnterClosure()44 		private void EnterClosure()
45 		{
46 			while (lockedByThread != Thread.CurrentThread)
47 			{
48 				while (!SetLock())
49 				{
50 					WaitClosure();
51 				}
52 			}
53 		}
54 
AwakeClosure()55 		private void AwakeClosure()
56         {
57             lock (this)
58             {
59                 RemoveLock();
60                 closureReleased = Thread.CurrentThread;
61                 closureEvent.Set();
62                 Thread.Sleep(0);
63                 if (closureReleased == Thread.CurrentThread)
64                 {
65                     closureEvent.Reset();
66                 }
67             }
68         }
69 
AwakeWait()70 		private void AwakeWait()
71 		{
72 			lock (this)
73 			{
74 				waitReleased = Thread.CurrentThread;
75 				waitEvent.Set();
76 				Thread.Sleep(0);
77 				if (waitReleased == Thread.CurrentThread)
78 				{
79 					waitEvent.Reset();
80 				}
81 			}
82 		}
83 
WaitWait(long timeout)84 		private void WaitWait(long timeout)
85         {
86         	waitEvent.WaitOne((int) timeout, false);
87             waitReleased = Thread.CurrentThread;
88         }
89 
WaitClosure()90         private void WaitClosure()
91         {
92             closureEvent.WaitOne();
93             closureReleased = Thread.CurrentThread;
94         }
95 
SetLock()96         private bool SetLock()
97         {
98             lock (this)
99             {
100                 if (lockedByThread == null)
101                 {
102                     lockedByThread = Thread.CurrentThread;
103                     return true;
104                 }
105                 return false;
106             }
107         }
108 
RemoveLock()109         private void RemoveLock()
110         {
111             lock (this)
112             {
113                 if (lockedByThread == Thread.CurrentThread)
114                 {
115                     lockedByThread = null;
116                 }
117             }
118         }
119     }
120 #endif
121 }