// 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.
namespace System.Threading
{
///
/// Represents pre-allocated state for native overlapped I/O operations.
///
///
public sealed class PreAllocatedOverlapped : IDisposable, IDeferredDisposable
{
internal readonly ThreadPoolBoundHandleOverlapped _overlapped;
private DeferredDisposableLifetime _lifetime;
///
/// Initializes a new instance of the class, specifying
/// a delegate that is invoked when each asynchronous I/O operation is complete, a user-provided
/// object providing context, and managed objects that serve as buffers.
///
///
/// An delegate that represents the callback method
/// invoked when each asynchronous I/O operation completes.
///
///
/// A user-provided object that distinguishes instance produced from this
/// object from other instances. Can be .
///
///
/// An object or array of objects representing the input or output buffer for the operations. Each
/// object represents a buffer, for example an array of bytes. Can be .
///
///
/// The new instance can be passed to
/// , to produce
/// a instance that can be passed to the operating system in overlapped
/// I/O operations. A single instance can only be used for
/// a single native I/O operation at a time. However, the state stored in the
/// instance can be reused for subsequent native operations.
///
/// The buffers specified in are pinned until is called.
///
///
///
/// is .
///
///
/// This method was called after the was disposed.
///
public unsafe PreAllocatedOverlapped(IOCompletionCallback callback, object state, object pinData)
{
if (callback == null)
throw new ArgumentNullException(nameof(callback));
_overlapped = new ThreadPoolBoundHandleOverlapped(callback, state, pinData, this);
}
internal bool AddRef()
{
return _lifetime.AddRef(this);
}
internal void Release()
{
_lifetime.Release(this);
}
///
/// Frees the resources associated with this instance.
///
public unsafe void Dispose()
{
_lifetime.Dispose(this);
GC.SuppressFinalize(this);
}
~PreAllocatedOverlapped()
{
//
// During shutdown, don't automatically clean up, because this instance may still be
// reachable/usable by other code.
//
if (!Environment.HasShutdownStarted)
Dispose();
}
unsafe void IDeferredDisposable.OnFinalRelease(bool disposed)
{
if (_overlapped != null)
{
if (disposed)
{
Overlapped.Free(_overlapped._nativeOverlapped);
}
else
{
_overlapped._boundHandle = null;
_overlapped._completed = false;
*_overlapped._nativeOverlapped = default(NativeOverlapped);
}
}
}
}
}