1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 namespace System.Threading
8 /// Overlapped subclass adding data needed by ThreadPoolBoundHandle.
10 internal sealed class ThreadPoolBoundHandleOverlapped : Overlapped
12 private readonly IOCompletionCallback _userCallback;
13 internal readonly object _userState;
14 internal PreAllocatedOverlapped _preAllocated;
15 internal unsafe NativeOverlapped* _nativeOverlapped;
16 internal ThreadPoolBoundHandle _boundHandle;
17 internal bool _completed;
19 public unsafe ThreadPoolBoundHandleOverlapped(IOCompletionCallback callback, object state, object pinData, PreAllocatedOverlapped preAllocated)
21 _userCallback = callback;
23 _preAllocated = preAllocated;
25 _nativeOverlapped = Pack(CompletionCallback, pinData);
26 _nativeOverlapped->OffsetLow = 0; // CLR reuses NativeOverlapped instances and does not reset these
27 _nativeOverlapped->OffsetHigh = 0;
30 private unsafe static void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
32 ThreadPoolBoundHandleOverlapped overlapped = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(nativeOverlapped);
35 // The Win32 thread pool implementation of ThreadPoolBoundHandle does not permit reuse of NativeOverlapped
36 // pointers without freeing them and allocating new a new one. We need to ensure that code using the CLR
37 // ThreadPool implementation follows those rules.
39 if (overlapped._completed)
40 throw new InvalidOperationException(SR.InvalidOperation_NativeOverlappedReused);
42 overlapped._completed = true;
44 if (overlapped._boundHandle == null)
45 throw new InvalidOperationException(SR.Argument_NativeOverlappedAlreadyFree);
47 overlapped._userCallback(errorCode, numBytes, nativeOverlapped);