Merge pull request #3240 from alexanderkyte/aot_compiler_leaks
[mono.git] / mcs / class / Facades / System.Threading.Overlapped / ClrThreadPoolBoundHandleOverlapped.cs
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.
4
5 namespace System.Threading
6 {
7     /// <summary>
8     /// Overlapped subclass adding data needed by ThreadPoolBoundHandle.
9     /// </summary>
10     internal sealed class ThreadPoolBoundHandleOverlapped : Overlapped
11     {
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;
18
19         public unsafe ThreadPoolBoundHandleOverlapped(IOCompletionCallback callback, object state, object pinData, PreAllocatedOverlapped preAllocated)
20         {
21             _userCallback = callback;
22             _userState = state;
23             _preAllocated = preAllocated;
24
25             _nativeOverlapped = Pack(CompletionCallback, pinData);
26             _nativeOverlapped->OffsetLow = 0;        // CLR reuses NativeOverlapped instances and does not reset these
27             _nativeOverlapped->OffsetHigh = 0;
28         }
29
30         private unsafe static void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped)
31         {
32             ThreadPoolBoundHandleOverlapped overlapped = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(nativeOverlapped);
33
34             //
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.
38             //
39             if (overlapped._completed)
40                 throw new InvalidOperationException(SR.InvalidOperation_NativeOverlappedReused);
41
42             overlapped._completed = true;
43
44             if (overlapped._boundHandle == null)
45                 throw new InvalidOperationException(SR.Argument_NativeOverlappedAlreadyFree);
46
47             overlapped._userCallback(errorCode, numBytes, nativeOverlapped);
48         }
49     }
50 }