Added asynchronous result support to SynchronizeFacility.
[castle.git] / Facilities / Synchronize / Castle.Facilities.Synchronize / AbstractAsyncResult.cs
blob4e42f092299046ccc996b5b64332b9241e2b2c23
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Facilities.Synchronize
17 using System;
18 using System.Threading;
20 /// <summary>
21 /// Abstract result for asynchronous operations.
22 /// </summary>
23 public abstract class AbstractAsyncResult : IAsyncResult
25 private int cleanUp;
26 private int completed;
27 private int invokedCallback;
28 private readonly object asyncState;
29 private readonly AsyncCallback _asyncCallback;
30 private bool completedSynchronously;
31 private bool endCalled;
32 private Exception exception;
33 private object result;
34 private object waitEvent;
36 /// <summary>
37 /// Initializes a new <see cref="AbstractAsyncResult"/>
38 /// </summary>
39 /// <param name="callback">The async callback.</param>
40 /// <param name="state">The async state</param>
41 protected AbstractAsyncResult(AsyncCallback callback, object state)
43 asyncState = state;
44 _asyncCallback = callback;
45 invokedCallback = (callback != null) ? 0 : 1;
48 #region IAsyncResult Members
50 /// <summary>
51 /// Gets the asynchournous state.
52 /// </summary>
53 public object AsyncState
55 get { return asyncState; }
58 /// <summary>
59 /// Determines if the result is available.
60 /// </summary>
61 public bool IsCompleted
63 get { return (completed != 0); }
66 /// <summary>
67 /// Determines if the result completed synchronously.
68 /// </summary>
69 public bool CompletedSynchronously
71 get { return completedSynchronously; }
72 protected internal set
74 completedSynchronously = value;
78 /// <summary>
79 /// Gets the asynchronous <see cref="WaitHandle"/>.
80 /// </summary>
81 public WaitHandle AsyncWaitHandle
83 get
85 int isCompleted = completed;
87 if (waitEvent == null)
89 Interlocked.CompareExchange(ref waitEvent,
90 new ManualResetEvent(isCompleted != 0), (object)null);
93 ManualResetEvent ev = (ManualResetEvent)waitEvent;
95 if ((isCompleted == 0) && (completed != 0))
97 ev.Set();
100 return ev;
104 /// <summary>
105 /// Ends the asynchronous request.
106 /// </summary>
107 /// <param name="asyncResult">The asynchronous result.</param>
108 /// <returns>The result.</returns>
109 public static object End(IAsyncResult asyncResult)
111 if (asyncResult == null)
113 throw new ArgumentNullException("asyncResult");
116 AbstractAsyncResult result = asyncResult as AbstractAsyncResult;
118 if (result == null)
120 throw new ArgumentException("Unrecognized IAsyncResult", "result");
123 if (result.endCalled)
125 throw new InvalidOperationException("IAsyncResult has already ended");
128 result.endCalled = true;
130 if (result.completed == 0)
132 result.AsyncWaitHandle.WaitOne();
135 if (result.exception != null)
137 throw result.exception;
140 return result.result;
143 #endregion
145 /// <summary>
146 /// Completes the asynchronous request.
147 /// </summary>
148 /// <param name="synchronously">true if synchronously.</param>
149 protected void Complete(bool synchronously)
151 completedSynchronously = synchronously;
153 Interlocked.Increment(ref completed);
155 if (waitEvent != null)
157 ((ManualResetEvent)waitEvent).Set();
160 if ((_asyncCallback != null) && (Interlocked.Increment(ref invokedCallback) == 1))
162 _asyncCallback(this);
165 InternalCleanup();
168 /// <summary>
169 /// Completes the asynchronous request.
170 /// </summary>
171 /// <param name="synchronously">true if synchronously.</param>
172 /// <param name="result">The result.</param>
173 protected void Complete(bool synchronously, object result)
175 this.result = result;
176 Complete(synchronously);
179 /// <summary>
180 /// Completes the asynchronous request with exception.
181 /// </summary>
182 /// <param name="synchronously">true if synchronously.</param>
183 /// <param name="exception">The exception.</param>
184 protected void Complete(bool synchronously, Exception exception)
186 this.exception = exception;
187 Complete(synchronously);
190 /// <summary>
191 /// Performs any cleanup.
192 /// </summary>
193 protected virtual void Cleanup()
197 private void InternalCleanup()
199 if (Interlocked.Increment(ref cleanUp) == 1)
201 Cleanup();
205 /// <summary>
206 /// Finalizer to ensure cleanup.
207 /// </summary>
208 ~AbstractAsyncResult()
210 InternalCleanup();