2 // System.Runtime.InteropServices/GCHandle.cs
5 // Ajay kumar Dwivedi (adwiv@yahoo.com) ??
6 // Paolo Molaro (lupus@ximian.com)
10 // Copyright (C) 2004, 2009 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Threading;
34 using System.Runtime.CompilerServices;
35 using System.Runtime.InteropServices;
37 namespace System.Runtime.InteropServices
41 [MonoTODO("Struct should be [StructLayout(LayoutKind.Sequential)] but will need to be reordered for that.")]
42 public struct GCHandle
47 private GCHandle(IntPtr h)
53 private GCHandle(object obj)
54 : this(obj, GCHandleType.Normal)
57 internal GCHandle(object value, GCHandleType type)
59 // MS does not crash/throw on (most) invalid GCHandleType values (except -1)
60 if ((type < GCHandleType.Weak) || (type > GCHandleType.Pinned))
61 type = GCHandleType.Normal;
62 handle = GetTargetHandle (value, 0, type);
67 public bool IsAllocated
80 throw new InvalidOperationException (Locale.GetText ("Handle is not allocated"));
81 return GetTarget (handle);
85 handle = GetTargetHandle (value, handle, (GCHandleType)(-1));
90 public IntPtr AddrOfPinnedObject()
92 IntPtr res = GetAddrOfPinnedObject(handle);
93 if (res == (IntPtr)(-1))
94 throw new ArgumentException ("Object contains non-primitive or non-blittable data.");
95 if (res == (IntPtr)(-2))
96 throw new InvalidOperationException("Handle is not pinned.");
100 public static System.Runtime.InteropServices.GCHandle Alloc(object value)
102 return new GCHandle (value);
105 public static System.Runtime.InteropServices.GCHandle Alloc(object value, GCHandleType type)
107 return new GCHandle (value,type);
112 // Copy the handle instance member to a local variable. This is required to prevent
113 // race conditions releasing the handle.
114 int local_handle = handle;
116 // Free the handle if it hasn't already been freed.
117 if (local_handle != 0 && Interlocked.CompareExchange (ref handle, 0, local_handle) == local_handle) {
118 FreeHandle (local_handle);
121 throw new InvalidOperationException ("Handle is not initialized.");
125 public static explicit operator IntPtr (GCHandle value)
127 return (IntPtr) value.handle;
130 public static explicit operator GCHandle(IntPtr value)
132 if (value == IntPtr.Zero)
133 throw new InvalidOperationException ("GCHandle value cannot be zero");
134 if (!CheckCurrentDomain ((int)value))
135 throw new ArgumentException ("GCHandle value belongs to a different domain");
136 return new GCHandle (value);
139 [MethodImplAttribute(MethodImplOptions.InternalCall)]
140 private extern static bool CheckCurrentDomain (int handle);
142 [MethodImplAttribute(MethodImplOptions.InternalCall)]
143 private extern static object GetTarget(int handle);
145 [MethodImplAttribute(MethodImplOptions.InternalCall)]
146 private extern static int GetTargetHandle(object obj, int handle, GCHandleType type);
148 [MethodImplAttribute(MethodImplOptions.InternalCall)]
149 private extern static void FreeHandle(int handle);
151 [MethodImplAttribute(MethodImplOptions.InternalCall)]
152 private extern static IntPtr GetAddrOfPinnedObject(int handle);
154 public static bool operator ==(GCHandle a, GCHandle b)
156 return a.handle == b.handle;
159 public static bool operator !=(GCHandle a, GCHandle b)
164 public override bool Equals(object o)
166 return o is GCHandle ? this == (GCHandle)o : false;
169 public override int GetHashCode()
171 return handle.GetHashCode ();
174 public static GCHandle FromIntPtr (IntPtr value)
176 return (GCHandle)value;
179 public static IntPtr ToIntPtr (GCHandle value)
181 return (IntPtr)value;