forked from sbozzie/test-intel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIntelAsyncResult.cs
More file actions
233 lines (212 loc) · 9.08 KB
/
Copy pathIntelAsyncResult.cs
File metadata and controls
233 lines (212 loc) · 9.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Threading;
namespace PleaseIgnore.IntelMap {
/// <summary>
/// Implementation of <see cref="IAsyncResult"/>, providing common
/// support for asynchronous function calls in PleaseIgnore.
/// </summary>
/// <typeparam name="TResult">
/// The return <see cref="Type"/> of the <c>End<var>Name</var></c>
/// call.
/// </typeparam>
internal class IntelAsyncResult<TResult> : IAsyncResult {
// The callback to call when execution has completed
private readonly AsyncCallback callback;
// The value of AsyncState
[ContractPublicPropertyName("AsyncState")]
private readonly object state;
// Number of waits made on End*()
private int waitCount;
// Set to true once the asynchronous execution has completed
[ContractPublicPropertyName("IsCompleted")]
private bool completed;
// Set to true if the execution was completed synchronously
[ContractPublicPropertyName("CompletedSynchronously")]
private bool synchronous;
// The return value of a successful asynchronous execution
private TResult result;
// The exception object for an unsuccessful asychronous execution
private Exception exception;
// The WaitHandle instance to use when waiting for completion. Populated
// by AsyncWaitHandle only as needed.
private ManualResetEvent waitHandle;
/// <summary>
/// Initializes a new instance of the <see cref="IntelAsyncResult`2"/>
/// class.
/// </summary>
/// <param name="callback">
/// The <see cref="AsyncCallback"/> to call when the asynchronous
/// operation completes. This can be <see langword="null"/>.
/// </param>
/// <param name="state">
/// The value of <see cref="AsyncState"/>. This can be
/// <see langword="null"/>.
/// </param>
/// <exception cref="ArgumentNullException">
/// <paramref name="owner"/> is <see langword="null"/>.
/// </exception>
protected IntelAsyncResult(AsyncCallback callback, object state) {
Contract.Ensures(this.AsyncState == state);
Contract.Ensures(!this.IsCompleted);
this.callback = callback;
this.state = state;
}
/// <summary>
/// Gets a user-defined object that qualifies or contains information
/// about an asynchronous operation.
/// </summary>
public object AsyncState { get { return this.state; } }
/// <summary>
/// Gets a value that indicates whether the asynchronous operation
/// completed synchronously.
/// </summary>
public bool CompletedSynchronously { get { return this.synchronous; } }
/// <summary>
/// Gets a value that indicates whether the asynchronous operation
/// has completed.
/// </summary>
public bool IsCompleted { get { return this.completed; } }
/// <summary>
/// Gets a <see cref="WaitHandle"/> that is used to wait for an
/// asynchronous operation to complete.
/// </summary>
public WaitHandle AsyncWaitHandle {
get {
Contract.Ensures(Contract.Result<WaitHandle>() != null);
var handle = new ManualResetEvent(false);
var oldhandle = Interlocked.CompareExchange(
ref this.waitHandle,
handle,
null);
// XXX: CodeContracts doesn't seem to realize that CompareExchange
// (above) will leave this.waitHandle as not null.
Contract.Assume(this.waitHandle != null);
if (this.completed) {
this.waitHandle.Set();
}
if (oldhandle != null) {
// XXX: CompareExchange returns the /original/ value. If the
// original value is not null, it was not replaced, so we need
// to delete the new object we created.
handle.Close();
}
return this.waitHandle;
}
}
/// <summary>
/// Signals that the asychronous operation has completed
/// successfully.
/// </summary>
/// <param name="result">
/// The return code for the <c>End*()</c> method.
/// </param>
/// <param name="completeSynchronously">
/// The value to assign to <see cref="CompletedSynchronously"/>.
/// </param>
/// <remarks>
/// If a callback was provided at <see cref="IntelAsyncResult"/>
/// initialization, it will be queued onto the
/// <see cref="ThreadPool"/>.
/// </remarks>
protected void Complete(TResult result, bool completeSynchronously) {
Contract.Requires<InvalidOperationException>(!this.IsCompleted);
Contract.Ensures(this.CompletedSynchronously == completeSynchronously);
Contract.Ensures(this.IsCompleted);
this.completed = true;
this.result = result;
this.synchronous = completeSynchronously;
Thread.MemoryBarrier();
if (this.waitHandle != null) {
this.waitHandle.Set();
}
if (this.callback != null) {
ThreadPool.QueueUserWorkItem(this.UserCallback);
}
}
/// <summary>
/// Signals that the asychronous operation was aborted due to
/// an error.
/// </summary>
/// <param name="exception">
/// The exception to throw from the <c>End*()</c> method.
/// </param>
/// <param name="completeSynchronously">
/// The value to assign to <see cref="CompletedSynchronously"/>.
/// </param>
/// <remarks>
/// If a callback was provided at <see cref="IntelAsyncResult"/>
/// initialization, it will be queued onto the
/// <see cref="ThreadPool"/>.
/// </remarks>
protected void Complete(Exception exception, bool completeSynchronously) {
Contract.Requires(exception != null);
Contract.Requires<InvalidOperationException>(!this.IsCompleted);
Contract.Ensures(this.CompletedSynchronously == completeSynchronously);
Contract.Ensures(this.IsCompleted);
this.completed = true;
this.exception = exception;
this.synchronous = completeSynchronously;
Thread.MemoryBarrier();
if (this.waitHandle != null) {
this.waitHandle.Set();
}
if (callback != null) {
ThreadPool.QueueUserWorkItem(this.UserCallback);
}
}
/// <summary>
/// Waits for the asynchronous call to complete, returning the queued
/// value or throwing an exception as appropriate.
/// </summary>
/// <param name="methodName">
/// The name of the function being used to wait on this
/// <see cref="IntelAsyncResult"/>.
/// </param>
/// <returns>
/// The value provided to <see cref="AsyncComplete(TResult)"/> or
/// <see cref="SyncComplete(TResult)"/>.
/// </returns>
/// <exception cref="ArgumentException">
/// <paramref name="methodName"/> is <see langword="null"/> or
/// <see cref="String.Empty"/>.
/// </exception>
/// <exception cref="InvalidOperationException">
/// A call has already been made to <see cref="Wait"/> on this
/// instance of <see cref="IntelAsyncResult"/>.
/// </exception>
/// <exception cref="Exception">
/// Any exception registered by calling
/// <see cref="Complete(Exception, bool)"/>.
/// </exception>
public TResult Wait(string methodName) {
Contract.Requires<ArgumentException>(!String.IsNullOrEmpty(methodName));
Contract.Ensures(this.completed);
var old = Interlocked.CompareExchange(ref waitCount, 1, 0);
if (old != 0) {
throw new InvalidOperationException(string.Format(
CultureInfo.CurrentCulture,
Properties.Resources.InvalidOperation_MultipleCalls,
methodName));
}
if (!this.completed) {
this.AsyncWaitHandle.WaitOne();
Contract.Assert(this.completed);
}
if (this.exception != null) {
throw this.exception;
} else {
return this.result;
}
}
/// <summary>
/// ThreadPool callback.
/// </summary>
private void UserCallback(object state) {
Contract.Requires(this.callback != null);
this.callback(this);
}
}
}