diff options
Diffstat (limited to 'OpenSim/Framework/Communications/GenericAsyncResult.cs')
-rw-r--r-- | OpenSim/Framework/Communications/GenericAsyncResult.cs | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/OpenSim/Framework/Communications/GenericAsyncResult.cs b/OpenSim/Framework/Communications/GenericAsyncResult.cs new file mode 100644 index 0000000..ed41614 --- /dev/null +++ b/OpenSim/Framework/Communications/GenericAsyncResult.cs | |||
@@ -0,0 +1,156 @@ | |||
1 | using System; | ||
2 | using System.Threading; | ||
3 | |||
4 | namespace OpenSim.Framework.Communications | ||
5 | { | ||
6 | internal class SimpleAsyncResult : IAsyncResult | ||
7 | { | ||
8 | private readonly AsyncCallback m_callback; | ||
9 | |||
10 | /// <summary> | ||
11 | /// Is process completed? | ||
12 | /// </summary> | ||
13 | /// <remarks>Should really be boolean, but VolatileRead has no boolean method</remarks> | ||
14 | private byte m_completed; | ||
15 | |||
16 | /// <summary> | ||
17 | /// Did process complete synchroneously? | ||
18 | /// </summary> | ||
19 | /// <remarks>I have a hard time imagining a scenario where this is the case, again, same issue about | ||
20 | /// booleans and VolatileRead as m_completed | ||
21 | /// </remarks> | ||
22 | private byte m_completedSynchronously; | ||
23 | |||
24 | private readonly object m_asyncState; | ||
25 | private ManualResetEvent m_waitHandle; | ||
26 | private Exception m_exception; | ||
27 | |||
28 | internal SimpleAsyncResult(AsyncCallback cb, object state) | ||
29 | { | ||
30 | m_callback = cb; | ||
31 | m_asyncState = state; | ||
32 | m_completed = 0; | ||
33 | m_completedSynchronously = 1; | ||
34 | } | ||
35 | |||
36 | #region IAsyncResult Members | ||
37 | |||
38 | public object AsyncState | ||
39 | { | ||
40 | get { return m_asyncState; } | ||
41 | } | ||
42 | |||
43 | public WaitHandle AsyncWaitHandle | ||
44 | { | ||
45 | get | ||
46 | { | ||
47 | if (m_waitHandle == null) | ||
48 | { | ||
49 | bool done = IsCompleted; | ||
50 | ManualResetEvent mre = new ManualResetEvent(done); | ||
51 | if (Interlocked.CompareExchange(ref m_waitHandle, mre, null) != null) | ||
52 | { | ||
53 | mre.Close(); | ||
54 | } | ||
55 | else | ||
56 | { | ||
57 | if (!done && IsCompleted) | ||
58 | { | ||
59 | m_waitHandle.Set(); | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | return m_waitHandle; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | |||
68 | public bool CompletedSynchronously | ||
69 | { | ||
70 | get { return Thread.VolatileRead(ref m_completedSynchronously) == 1; } | ||
71 | } | ||
72 | |||
73 | |||
74 | public bool IsCompleted | ||
75 | { | ||
76 | get { return Thread.VolatileRead(ref m_completed) == 1; } | ||
77 | } | ||
78 | |||
79 | #endregion | ||
80 | |||
81 | #region class Methods | ||
82 | |||
83 | internal void SetAsCompleted(bool completedSynchronously) | ||
84 | { | ||
85 | m_completed = 1; | ||
86 | if (completedSynchronously) | ||
87 | m_completedSynchronously = 1; | ||
88 | else | ||
89 | m_completedSynchronously = 0; | ||
90 | |||
91 | SignalCompletion(); | ||
92 | } | ||
93 | |||
94 | internal void HandleException(Exception e, bool completedSynchronously) | ||
95 | { | ||
96 | m_completed = 1; | ||
97 | if (completedSynchronously) | ||
98 | m_completedSynchronously = 1; | ||
99 | else | ||
100 | m_completedSynchronously = 0; | ||
101 | m_exception = e; | ||
102 | |||
103 | SignalCompletion(); | ||
104 | } | ||
105 | |||
106 | private void SignalCompletion() | ||
107 | { | ||
108 | if (m_waitHandle != null) m_waitHandle.Set(); | ||
109 | |||
110 | if (m_callback != null) m_callback(this); | ||
111 | } | ||
112 | |||
113 | public void EndInvoke() | ||
114 | { | ||
115 | // This method assumes that only 1 thread calls EndInvoke | ||
116 | if (!IsCompleted) | ||
117 | { | ||
118 | // If the operation isn't done, wait for it | ||
119 | AsyncWaitHandle.WaitOne(); | ||
120 | AsyncWaitHandle.Close(); | ||
121 | m_waitHandle = null; // Allow early GC | ||
122 | } | ||
123 | |||
124 | // Operation is done: if an exception occured, throw it | ||
125 | if (m_exception != null) throw m_exception; | ||
126 | } | ||
127 | |||
128 | #endregion | ||
129 | } | ||
130 | |||
131 | internal class AsyncResult<T> : SimpleAsyncResult | ||
132 | { | ||
133 | private T m_result = default(T); | ||
134 | |||
135 | public AsyncResult(AsyncCallback asyncCallback, Object state) : | ||
136 | base(asyncCallback, state) | ||
137 | { | ||
138 | } | ||
139 | |||
140 | public void SetAsCompleted(T result, bool completedSynchronously) | ||
141 | { | ||
142 | // Save the asynchronous operation's result | ||
143 | m_result = result; | ||
144 | |||
145 | // Tell the base class that the operation completed | ||
146 | // sucessfully (no exception) | ||
147 | base.SetAsCompleted(completedSynchronously); | ||
148 | } | ||
149 | |||
150 | public new T EndInvoke() | ||
151 | { | ||
152 | base.EndInvoke(); | ||
153 | return m_result; | ||
154 | } | ||
155 | } | ||
156 | } \ No newline at end of file | ||