MS公开的gchandle.cs源码
1
// ==++==
2
//
3
//
4
// Copyright (c) 2002 Microsoft Corporation. All rights reserved.
5
//
6
// The use and distribution terms for this software are contained in the file
7
// named license.txt, which can be found in the root of this distribution.
8
// By using this software in any fashion, you are agreeing to be bound by the
9
// terms of this license.
10
//
11
// You must not remove this notice, or any other, from this software.
12
//
13
//
14
// ==--==
15
namespace System.Runtime.InteropServices {
16
17
using System;
18
using System.Security.Permissions;
19
using System.Runtime.CompilerServices;
20
21
// These are the types of handles used by the EE. IMPORTANT: These must
22
// match the definitions in ObjectHandle.h in the EE.
23
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType"]/*' />
24
[Serializable]
25
public enum GCHandleType
26
{
27
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.Weak"]/*' />
28
Weak = 0,
29
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.WeakTrackResurrection"]/*' />
30
WeakTrackResurrection = 1,
31
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.Normal"]/*' />
32
Normal = 2,
33
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.Pinned"]/*' />
34
Pinned = 3
35
}
36
37
// This class allows you to create an opaque, GC handle to any
38
// COM+ object. A GC handle is used when an object reference must be
39
// reachable from unmanaged memory. There are 3 kinds of roots:
40
// Normal - keeps the object from being collected.
41
// Weak - allows object to be collected and handle contents will be zeroed.
42
// Weak references are zeroed before the finalizer runs, so if the
43
// object is resurrected in the finalizer the weak reference is
44
// still zeroed.
45
// WeakTrackResurrection - Same as weak, but stays until after object is
46
// really gone.
47
// Pinned - same as normal, but allows the address of the actual object
48
// to be taken.
49
//
50
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle"]/*' />
51
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
52
public struct GCHandle
53
{
54
// Allocate a handle storing the object and the type.
55
internal GCHandle(Object value, GCHandleType type)
56
{
57
m_handle = InternalAlloc(value, type);
58
59
// Record if the handle is pinned.
60
if (type == GCHandleType.Pinned)
61
SetIsPinned();
62
}
63
64
// Used in the conversion functions below.
65
internal GCHandle(IntPtr handle)
66
{
67
InternalCheckDomain(handle);
68
m_handle = handle;
69
}
70
71
// Creates a new GC handle for an object.
72
//
73
// value - The object that the GC handle is created for.
74
// type - The type of GC handle to create.
75
//
76
// returns a new GC handle that protects the object.
77
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Alloc"]/*' />
78
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
79
public static GCHandle Alloc(Object value)
80
{
81
return new GCHandle(value, GCHandleType.Normal);
82
}
83
84
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Alloc1"]/*' />
85
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
86
public static GCHandle Alloc(Object value, GCHandleType type)
87
{
88
return new GCHandle(value, type);
89
}
90
91
// Frees a GC handle. The caller must provide synchronization to
92
// prevent multiple threads from executing this simultaneously for
93
// a given handle. If you modify this method please modify the
94
// __InternalFree also which is the internal without the linktime check.
95
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Free"]/*' />
96
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
97
public void Free()
98
{
99
// Check if the handle was never initialized for was freed.
100
if (m_handle == IntPtr.Zero)
101
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
102
103
// Free the handle.
104
InternalFree(GetHandleValue());
105
m_handle = IntPtr.Zero;
106
}
107
108
internal void __InternalFree()
109
{
110
// Check if the handle was never initialized for was freed.
111
if (m_handle == IntPtr.Zero)
112
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
113
114
// Free the handle.
115
InternalFree(GetHandleValue());
116
m_handle = IntPtr.Zero;
117
}
118
119
// Target property - allows getting / updating of the handle's referent. If you modify this method
120
121
// then modify the __InternalTarget too which is the internal method without the linktime check.
122
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Target"]/*' />
123
public Object Target
124
{
125
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
126
get
127
{
128
// Check if the handle was never initialized or was freed.
129
if (m_handle == IntPtr.Zero)
130
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
131
132
return InternalGet(GetHandleValue());
133
}
134
135
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
136
set
137
{
138
// Check if the handle was never initialized or was freed.
139
if (m_handle == IntPtr.Zero)
140
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
141
142
InternalSet(GetHandleValue(), value, IsPinned());
143
}
144
}
145
146
internal Object __InternalTarget
147
{
148
get
149
{
150
// Check if the handle was never initialized or was freed.
151
if (m_handle == IntPtr.Zero)
152
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
153
154
return InternalGet(GetHandleValue());
155
}
156
}
157
158
// Retrieve the address of an object in a Pinned handle. This throws
159
// an exception if the handle is any type other than Pinned.
160
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.AddrOfPinnedObject"]/*' />
161
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
162
public IntPtr AddrOfPinnedObject()
163
{
164
// Check if the handle was not a pinned handle.
165
if (!IsPinned())
166
{
167
// Check if the handle was never initialized for was freed.
168
if (m_handle == IntPtr.Zero)
169
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
170
171
// You can only get the address of pinned handles.
172
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotPinned"));
173
}
174
175
// Get the address.
176
return InternalAddrOfPinnedObject(GetHandleValue());
177
}
178
179
// Determine whether this handle has been allocated or not.
180
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.IsAllocated"]/*' />
181
public bool IsAllocated
182
{
183
get
184
{
185
return m_handle != IntPtr.Zero;
186
}
187
}
188
189
// Used to create a GCHandle from an int. This is intended to
190
// be used with the reverse conversion.
191
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.operatorGCHandle"]/*' />
192
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
193
public static explicit operator GCHandle(IntPtr value)
194
{
195
return new GCHandle(value);
196
}
197
198
// Used to get the internal integer representation of the handle out.
199
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.operatorIntPtr"]/*' />
200
public static explicit operator IntPtr(GCHandle value)
201
{
202
return value.m_handle;
203
}
204
205
internal IntPtr GetHandleValue()
206
{
207
#if WIN32
208
return new IntPtr(((int)m_handle) & ~1);
209
#else
210
return new IntPtr(((long)m_handle) & ~1L);
211
#endif
212
}
213
214
internal bool IsPinned()
215
{
216
#if WIN32
217
return (((int)m_handle) & 1) != 0;
218
#else
219
return (((long)m_handle) & 1) != 0;
220
#endif
221
}
222
223
internal void SetIsPinned()
224
{
225
#if WIN32
226
m_handle = new IntPtr(((int)m_handle) | 1);
227
#else
228
m_handle = new IntPtr(((long)m_handle) | 1L);
229
#endif
230
}
231
232
// Internal native calls that this implementation uses.
233
[MethodImplAttribute(MethodImplOptions.InternalCall)]
234
internal static extern IntPtr InternalAlloc(Object value, GCHandleType type);
235
[MethodImplAttribute(MethodImplOptions.InternalCall)]
236
internal static extern void InternalFree(IntPtr handle);
237
[MethodImplAttribute(MethodImplOptions.InternalCall)]
238
internal static extern Object InternalGet(IntPtr handle);
239
[MethodImplAttribute(MethodImplOptions.InternalCall)]
240
internal static extern void InternalSet(IntPtr handle, Object value, bool isPinned);
241
[MethodImplAttribute(MethodImplOptions.InternalCall)]
242
internal static extern void InternalCompareExchange(IntPtr handle, Object value, Object oldValue, bool isPinned);
243
[MethodImplAttribute(MethodImplOptions.InternalCall)]
244
internal static extern IntPtr InternalAddrOfPinnedObject(IntPtr handle);
245
[MethodImplAttribute(MethodImplOptions.InternalCall)]
246
internal static extern void InternalCheckDomain(IntPtr handle);
247
248
249
// The actual integer handle value that the EE uses internally.
250
private IntPtr m_handle;
251
}
252
}
253
254
// ==++==2
// 3
// 4
// Copyright (c) 2002 Microsoft Corporation. All rights reserved.5
// 6
// The use and distribution terms for this software are contained in the file7
// named license.txt, which can be found in the root of this distribution.8
// By using this software in any fashion, you are agreeing to be bound by the9
// terms of this license.10
// 11
// You must not remove this notice, or any other, from this software.12
// 13
// 14
// ==--==15
namespace System.Runtime.InteropServices {16
17
using System;18
using System.Security.Permissions;19
using System.Runtime.CompilerServices;20

21
// These are the types of handles used by the EE. IMPORTANT: These must22
// match the definitions in ObjectHandle.h in the EE.23
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType"]/*' />24
[Serializable]25
public enum GCHandleType26
{27
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.Weak"]/*' />28
Weak = 0,29
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.WeakTrackResurrection"]/*' />30
WeakTrackResurrection = 1,31
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.Normal"]/*' />32
Normal = 2,33
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandleType.Pinned"]/*' />34
Pinned = 335
}36

37
// This class allows you to create an opaque, GC handle to any 38
// COM+ object. A GC handle is used when an object reference must be39
// reachable from unmanaged memory. There are 3 kinds of roots:40
// Normal - keeps the object from being collected.41
// Weak - allows object to be collected and handle contents will be zeroed.42
// Weak references are zeroed before the finalizer runs, so if the43
// object is resurrected in the finalizer the weak reference is44
// still zeroed.45
// WeakTrackResurrection - Same as weak, but stays until after object is46
// really gone.47
// Pinned - same as normal, but allows the address of the actual object48
// to be taken.49
//50
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle"]/*' />51
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]52
public struct GCHandle53
{54
// Allocate a handle storing the object and the type.55
internal GCHandle(Object value, GCHandleType type)56
{57
m_handle = InternalAlloc(value, type);58

59
// Record if the handle is pinned.60
if (type == GCHandleType.Pinned)61
SetIsPinned();62
} 63

64
// Used in the conversion functions below.65
internal GCHandle(IntPtr handle)66
{67
InternalCheckDomain(handle);68
m_handle = handle;69
}70

71
// Creates a new GC handle for an object.72
//73
// value - The object that the GC handle is created for.74
// type - The type of GC handle to create.75
// 76
// returns a new GC handle that protects the object.77
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Alloc"]/*' />78
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]79
public static GCHandle Alloc(Object value)80
{81
return new GCHandle(value, GCHandleType.Normal);82
}83

84
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Alloc1"]/*' />85
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]86
public static GCHandle Alloc(Object value, GCHandleType type)87
{88
return new GCHandle(value, type);89
}90

91
// Frees a GC handle. The caller must provide synchronization to92
// prevent multiple threads from executing this simultaneously for93
// a given handle. If you modify this method please modify the 94
// __InternalFree also which is the internal without the linktime check.95
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Free"]/*' />96
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]97
public void Free()98
{99
// Check if the handle was never initialized for was freed.100
if (m_handle == IntPtr.Zero)101
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));102

103
// Free the handle.104
InternalFree(GetHandleValue());105
m_handle = IntPtr.Zero;106
}107
108
internal void __InternalFree()109
{110
// Check if the handle was never initialized for was freed.111
if (m_handle == IntPtr.Zero)112
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));113

114
// Free the handle.115
InternalFree(GetHandleValue());116
m_handle = IntPtr.Zero;117
}118

119
// Target property - allows getting / updating of the handle's referent. If you modify this method120

121
// then modify the __InternalTarget too which is the internal method without the linktime check.122
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.Target"]/*' />123
public Object Target124
{125
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]126
get127
{128
// Check if the handle was never initialized or was freed.129
if (m_handle == IntPtr.Zero)130
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));131

132
return InternalGet(GetHandleValue());133
}134
135
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]136
set137
{138
// Check if the handle was never initialized or was freed.139
if (m_handle == IntPtr.Zero)140
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));141

142
InternalSet(GetHandleValue(), value, IsPinned());143
}144
}145
146
internal Object __InternalTarget147
{148
get149
{150
// Check if the handle was never initialized or was freed.151
if (m_handle == IntPtr.Zero)152
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));153

154
return InternalGet(GetHandleValue());155
}156
}157

158
// Retrieve the address of an object in a Pinned handle. This throws159
// an exception if the handle is any type other than Pinned.160
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.AddrOfPinnedObject"]/*' />161
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]162
public IntPtr AddrOfPinnedObject()163
{164
// Check if the handle was not a pinned handle.165
if (!IsPinned())166
{167
// Check if the handle was never initialized for was freed.168
if (m_handle == IntPtr.Zero)169
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));170

171
// You can only get the address of pinned handles.172
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotPinned"));173
}174

175
// Get the address.176
return InternalAddrOfPinnedObject(GetHandleValue());177
}178

179
// Determine whether this handle has been allocated or not.180
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.IsAllocated"]/*' />181
public bool IsAllocated182
{183
get184
{185
return m_handle != IntPtr.Zero;186
}187
}188

189
// Used to create a GCHandle from an int. This is intended to190
// be used with the reverse conversion.191
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.operatorGCHandle"]/*' />192
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]193
public static explicit operator GCHandle(IntPtr value)194
{195
return new GCHandle(value);196
}197

198
// Used to get the internal integer representation of the handle out.199
/// <include file='doc\GcHandle.uex' path='docs/doc[@for="GCHandle.operatorIntPtr"]/*' />200
public static explicit operator IntPtr(GCHandle value)201
{202
return value.m_handle;203
}204

205
internal IntPtr GetHandleValue()206
{207
#if WIN32208
return new IntPtr(((int)m_handle) & ~1);209
#else210
return new IntPtr(((long)m_handle) & ~1L);211
#endif212
}213

214
internal bool IsPinned()215
{216
#if WIN32217
return (((int)m_handle) & 1) != 0;218
#else219
return (((long)m_handle) & 1) != 0;220
#endif221
}222

223
internal void SetIsPinned()224
{225
#if WIN32226
m_handle = new IntPtr(((int)m_handle) | 1);227
#else228
m_handle = new IntPtr(((long)m_handle) | 1L);229
#endif230
}231

232
// Internal native calls that this implementation uses.233
[MethodImplAttribute(MethodImplOptions.InternalCall)]234
internal static extern IntPtr InternalAlloc(Object value, GCHandleType type);235
[MethodImplAttribute(MethodImplOptions.InternalCall)]236
internal static extern void InternalFree(IntPtr handle);237
[MethodImplAttribute(MethodImplOptions.InternalCall)]238
internal static extern Object InternalGet(IntPtr handle);239
[MethodImplAttribute(MethodImplOptions.InternalCall)]240
internal static extern void InternalSet(IntPtr handle, Object value, bool isPinned);241
[MethodImplAttribute(MethodImplOptions.InternalCall)]242
internal static extern void InternalCompareExchange(IntPtr handle, Object value, Object oldValue, bool isPinned);243
[MethodImplAttribute(MethodImplOptions.InternalCall)]244
internal static extern IntPtr InternalAddrOfPinnedObject(IntPtr handle);245
[MethodImplAttribute(MethodImplOptions.InternalCall)]246
internal static extern void InternalCheckDomain(IntPtr handle);247

248

249
// The actual integer handle value that the EE uses internally.250
private IntPtr m_handle;251
}252
}253

254




浙公网安备 33010602011771号