










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
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。