2
2
// The .NET Foundation licenses this file to you under the MIT license.
3
3
// See the LICENSE file in the project root for more information.
4
4
5
- using Microsoft . Win32 . SafeHandles ;
6
-
7
5
using System . Diagnostics ;
8
- using System . Runtime . CompilerServices ;
9
6
using System . Runtime . InteropServices ;
10
7
using System . Threading ;
11
8
12
9
namespace System . Net . Sockets
13
10
{
14
- internal class SafeNativeOverlapped : SafeHandle
11
+ internal sealed class SafeNativeOverlapped : SafeHandle
15
12
{
16
- private static readonly SafeNativeOverlapped s_zero = new SafeNativeOverlapped ( ) ;
17
- private SafeCloseSocket _safeCloseSocket ;
18
-
19
- internal static SafeNativeOverlapped Zero { get { return s_zero ; } }
13
+ internal static SafeNativeOverlapped Zero { get ; } = new SafeNativeOverlapped ( ) ;
20
14
21
- protected SafeNativeOverlapped ( )
15
+ private SafeNativeOverlapped ( )
22
16
: this ( IntPtr . Zero )
23
17
{
24
18
if ( GlobalLog . IsEnabled )
@@ -27,7 +21,7 @@ protected SafeNativeOverlapped()
27
21
}
28
22
}
29
23
30
- protected SafeNativeOverlapped ( IntPtr handle )
24
+ private SafeNativeOverlapped ( IntPtr handle )
31
25
: base ( IntPtr . Zero , true )
32
26
{
33
27
SetHandle ( handle ) ;
@@ -36,32 +30,26 @@ protected SafeNativeOverlapped(IntPtr handle)
36
30
public unsafe SafeNativeOverlapped ( SafeCloseSocket socketHandle , NativeOverlapped * handle )
37
31
: this ( ( IntPtr ) handle )
38
32
{
39
- _safeCloseSocket = socketHandle ;
33
+ SocketHandle = socketHandle ;
40
34
41
35
if ( GlobalLog . IsEnabled )
42
36
{
43
37
GlobalLog . Print ( "SafeNativeOverlapped#" + LoggingHash . HashString ( this ) + "::ctor(socket#" + LoggingHash . HashString ( socketHandle ) + ")" ) ;
44
38
}
45
39
46
40
#if DEBUG
47
- _safeCloseSocket . AddRef ( ) ;
41
+ SocketHandle . AddRef ( ) ;
48
42
#endif
49
43
}
50
44
51
- protected override void Dispose ( bool disposing )
45
+ internal unsafe void ReplaceHandle ( NativeOverlapped * overlapped )
52
46
{
53
- if ( disposing )
54
- {
55
- // It is important that the boundHandle is released immediately to allow new overlapped operations.
56
- if ( GlobalLog . IsEnabled )
57
- {
58
- GlobalLog . Print ( "SafeNativeOverlapped#" + LoggingHash . HashString ( this ) + "::Dispose(true)" ) ;
59
- }
60
-
61
- FreeNativeOverlapped ( ) ;
62
- }
47
+ Debug . Assert ( handle == IntPtr . Zero , "We should only be replacing the handle when it's already been freed." ) ;
48
+ SetHandle ( ( IntPtr ) overlapped ) ;
63
49
}
64
50
51
+ internal SafeCloseSocket SocketHandle { get ; }
52
+
65
53
public override bool IsInvalid
66
54
{
67
55
get { return handle == IntPtr . Zero ; }
@@ -75,37 +63,31 @@ protected override bool ReleaseHandle()
75
63
}
76
64
77
65
FreeNativeOverlapped ( ) ;
66
+
67
+ #if DEBUG
68
+ SocketHandle . Release ( ) ;
69
+ #endif
78
70
return true ;
79
71
}
80
72
81
- private void FreeNativeOverlapped ( )
73
+ internal void FreeNativeOverlapped ( )
82
74
{
83
- IntPtr oldHandle = Interlocked . Exchange ( ref handle , IntPtr . Zero ) ;
84
-
85
75
// Do not call free during AppDomain shutdown, there may be an outstanding operation.
86
76
// Overlapped will take care calling free when the native callback completes.
77
+ IntPtr oldHandle = Interlocked . Exchange ( ref handle , IntPtr . Zero ) ;
87
78
if ( oldHandle != IntPtr . Zero && ! Environment . HasShutdownStarted )
88
79
{
89
80
unsafe
90
81
{
91
- Debug . Assert ( _safeCloseSocket != null , "m_SafeCloseSocket is null." ) ;
92
-
93
- ThreadPoolBoundHandle boundHandle = _safeCloseSocket . IOCPBoundHandle ;
94
- Debug . Assert ( boundHandle != null , "SafeNativeOverlapped::ImmediatelyFreeNativeOverlapped - boundHandle is null" ) ;
82
+ Debug . Assert ( SocketHandle != null , "SocketHandle is null." ) ;
95
83
96
- if ( boundHandle != null )
97
- {
98
- // FreeNativeOverlapped will be called even if boundHandle was previously disposed.
99
- boundHandle . FreeNativeOverlapped ( ( NativeOverlapped * ) oldHandle ) ;
100
- }
84
+ ThreadPoolBoundHandle boundHandle = SocketHandle . IOCPBoundHandle ;
85
+ Debug . Assert ( boundHandle != null , "SafeNativeOverlapped::FreeNativeOverlapped - boundHandle is null" ) ;
101
86
102
- #if DEBUG
103
- _safeCloseSocket . Release ( ) ;
104
- #endif
105
- _safeCloseSocket = null ;
87
+ // FreeNativeOverlapped will be called even if boundHandle was previously disposed.
88
+ boundHandle ? . FreeNativeOverlapped ( ( NativeOverlapped * ) oldHandle ) ;
106
89
}
107
90
}
108
- return ;
109
91
}
110
92
}
111
93
}
0 commit comments