summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
diff options
context:
space:
mode:
authorJiyoung Yun <jy910.yun@samsung.com>2017-02-10 20:35:12 +0900
committerJiyoung Yun <jy910.yun@samsung.com>2017-02-10 20:35:12 +0900
commit4b11dc566a5bbfa1378d6266525c281b028abcc8 (patch)
treeb48831a898906734f8884d08b6e18f1144ee2b82 /src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
parentdb20f3f1bb8595633a7e16c8900fd401a453a6b5 (diff)
downloadcoreclr-4b11dc566a5bbfa1378d6266525c281b028abcc8.tar.gz
coreclr-4b11dc566a5bbfa1378d6266525c281b028abcc8.tar.bz2
coreclr-4b11dc566a5bbfa1378d6266525c281b028abcc8.zip
Imported Upstream version 1.0.0.9910upstream/1.0.0.9910
Diffstat (limited to 'src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs')
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs157
1 files changed, 0 insertions, 157 deletions
diff --git a/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs b/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
deleted file mode 100644
index 71eb787c5e..0000000000
--- a/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
+++ /dev/null
@@ -1,157 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Security;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace System.Threading.Tasks {
-
-/// <summary>
-/// Provides an adapter to make Begin/End pairs awaitable.
-/// In general, Task.Factory.FromAsync should be used for this purpose.
-/// However, for cases where absolute minimal overhead is required, this type
-/// may be used to making APM pairs awaitable while minimizing overhead.
-/// (APM = Asynchronous Programming Model or the Begin/End pattern.)
-/// </summary>
-/// <remarks>
-/// This instance may be reused repeatedly. However, it must only be used
-/// by a single APM invocation at a time. It's state will automatically be reset
-/// when the await completes.
-/// </remarks>
-/// <example>
-/// Usage sample:
-/// <code>
-/// static async Task CopyStreamAsync(Stream source, Stream dest) {
-///
-/// BeginEndAwaitableAdapter adapter = new BeginEndAwaitableAdapter();
-/// Byte[] buffer = new Byte[0x1000];
-///
-/// while (true) {
-///
-/// source.BeginRead(buffer, 0, buffer.Length, BeginEndAwaitableAdapter.Callback, adapter);
-/// Int32 numRead = source.EndRead(await adapter);
-/// if (numRead == 0)
-/// break;
-///
-/// dest.BeginWrite(buffer, 0, numRead, BeginEndAwaitableAdapter.Callback, adapter);
-/// dest.EndWrite(await adapter);
-/// }
-/// }
-/// </code>
-/// </example>
-internal sealed class BeginEndAwaitableAdapter : ICriticalNotifyCompletion {
-
- /// <summary>A sentinel marker used to communicate between OnCompleted and the APM callback
- /// that the callback has already run, and thus OnCompleted needs to execute the callback.</summary>
- private readonly static Action CALLBACK_RAN = () => { };
-
- /// <summary>The IAsyncResult for the APM operation.</summary>
- private IAsyncResult _asyncResult;
-
- /// <summary>The continuation delegate provided to the awaiter.</summary>
- private Action _continuation;
-
-
- /// <summary>A callback to be passed as the AsyncCallback to an APM pair.
- /// It expects that an BeginEndAwaitableAdapter instance was supplied to the APM Begin method as the object state.</summary>
- public readonly static AsyncCallback Callback = (asyncResult) => {
-
- Debug.Assert(asyncResult != null);
- Debug.Assert(asyncResult.IsCompleted);
- Debug.Assert(asyncResult.AsyncState is BeginEndAwaitableAdapter);
-
- // Get the adapter object supplied as the "object state" to the Begin method
- BeginEndAwaitableAdapter adapter = (BeginEndAwaitableAdapter) asyncResult.AsyncState;
-
- // Store the IAsyncResult into it so that it's available to the awaiter
- adapter._asyncResult = asyncResult;
-
- // If the _continuation has already been set to the actual continuation by OnCompleted, then invoke the continuation.
- // Set _continuation to the CALLBACK_RAN sentinel so that IsCompleted returns true and OnCompleted sees the sentinel
- // and knows to invoke the callback.
- // Due to some known incorrect implementations of IAsyncResult in the Framework where CompletedSynchronously is lazily
- // set to true if it is first invoked after IsCompleted is true, we cannot rely here on CompletedSynchronously for
- // synchronization between the caller and the callback, and thus do not use CompletedSynchronously at all.
- Action continuation = Interlocked.Exchange(ref adapter._continuation, CALLBACK_RAN);
- if (continuation != null) {
-
- Debug.Assert(continuation != CALLBACK_RAN);
- continuation();
- }
- };
-
-
- /// <summary>Gets an awaiter.</summary>
- /// <returns>Returns itself as the awaiter.</returns>
- public BeginEndAwaitableAdapter GetAwaiter() {
-
- return this;
- }
-
-
- /// <summary>Gets whether the awaited APM operation completed.</summary>
- public bool IsCompleted {
- get {
-
- // We are completed if the callback was called and it set the continuation to the CALLBACK_RAN sentinel.
- // If the operation completes asynchronously, there's still a chance we'll see CALLBACK_RAN here, in which
- // case we're still good to keep running synchronously.
- return (_continuation == CALLBACK_RAN);
- }
- }
-
- /// <summary>Schedules the continuation to run when the operation completes.</summary>
- /// <param name="continuation">The continuation.</param>
- public void UnsafeOnCompleted(Action continuation) {
-
- Debug.Assert(continuation != null);
- OnCompleted(continuation);
- }
-
-
- /// <summary>Schedules the continuation to run when the operation completes.</summary>
- /// <param name="continuation">The continuation.</param>
- public void OnCompleted(Action continuation) {
-
- Debug.Assert(continuation != null);
-
- // If the continuation field is null, then set it to be the target continuation
- // so that when the operation completes, it'll invoke the continuation. If it's non-null,
- // it was already set to the CALLBACK_RAN-sentinel by the Callback, in which case we hit a very rare race condition
- // where the operation didn't complete synchronously but completed asynchronously between our
- // calls to IsCompleted and OnCompleted... in that case, just schedule a task to run the continuation.
- if (_continuation == CALLBACK_RAN
- || Interlocked.CompareExchange(ref _continuation, continuation, null) == CALLBACK_RAN) {
-
- Task.Run(continuation); // must run async at this point, or else we'd risk stack diving
- }
- }
-
-
- /// <summary>Gets the IAsyncResult for the APM operation after the operation completes, and then resets the adapter.</summary>
- /// <returns>The IAsyncResult for the operation.</returns>
- public IAsyncResult GetResult() {
-
- Debug.Assert(_asyncResult != null && _asyncResult.IsCompleted);
-
- // Get the IAsyncResult
- IAsyncResult result = _asyncResult;
-
- // Reset the adapter
- _asyncResult = null;
- _continuation = null;
-
- // Return the result
- return result;
- }
-
-} // class BeginEndAwaitableAdapter
-
-} // namespace