X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FSystem.Runtime.InteropServices%2FGCHandle.cs;h=ec83a3e0756b6f79737d2acb38b87f4ea11ba02b;hb=2eb33cebf5d9669671d3023535456e9c9cf084f7;hp=67218468375d7caea990078900c470a6bdc7d22a;hpb=987f8c63e214937c50dcb308149f7558a2cbba41;p=mono.git diff --git a/mcs/class/corlib/System.Runtime.InteropServices/GCHandle.cs b/mcs/class/corlib/System.Runtime.InteropServices/GCHandle.cs index 67218468375..ec83a3e0756 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/GCHandle.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/GCHandle.cs @@ -7,7 +7,7 @@ // // -// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// Copyright (C) 2004, 2009 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -30,15 +30,14 @@ // using System; +using System.Threading; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace System.Runtime.InteropServices { -#if NET_2_0 [ComVisible(true)] -#endif [MonoTODO("Struct should be [StructLayout(LayoutKind.Sequential)] but will need to be reordered for that.")] public struct GCHandle { @@ -55,8 +54,11 @@ namespace System.Runtime.InteropServices : this(obj, GCHandleType.Normal) {} - private GCHandle(object value, GCHandleType type) + internal GCHandle(object value, GCHandleType type) { + // MS does not crash/throw on (most) invalid GCHandleType values (except -1) + if ((type < GCHandleType.Weak) || (type > GCHandleType.Pinned)) + type = GCHandleType.Normal; handle = GetTargetHandle (value, 0, type); } @@ -74,6 +76,8 @@ namespace System.Runtime.InteropServices { get { + if (!IsAllocated) + throw new InvalidOperationException (Locale.GetText ("Handle is not allocated")); return GetTarget (handle); } set @@ -86,10 +90,10 @@ namespace System.Runtime.InteropServices public IntPtr AddrOfPinnedObject() { IntPtr res = GetAddrOfPinnedObject(handle); - if (res == IntPtr.Zero) - throw new InvalidOperationException("The handle is not of Pinned type"); if (res == (IntPtr)(-1)) throw new ArgumentException ("Object contains non-primitive or non-blittable data."); + if (res == (IntPtr)(-2)) + throw new InvalidOperationException("Handle is not pinned."); return res; } @@ -105,8 +109,17 @@ namespace System.Runtime.InteropServices public void Free() { - FreeHandle(handle); - handle = 0; + // Copy the handle instance member to a local variable. This is required to prevent + // race conditions releasing the handle. + int local_handle = handle; + + // Free the handle if it hasn't already been freed. + if (local_handle != 0 && Interlocked.CompareExchange (ref handle, 0, local_handle) == local_handle) { + FreeHandle (local_handle); + } + else { + throw new InvalidOperationException ("Handle is not initialized."); + } } public static explicit operator IntPtr (GCHandle value) @@ -117,7 +130,7 @@ namespace System.Runtime.InteropServices public static explicit operator GCHandle(IntPtr value) { if (value == IntPtr.Zero) - throw new ArgumentException ("GCHandle value cannot be zero"); + throw new InvalidOperationException ("GCHandle value cannot be zero"); if (!CheckCurrentDomain ((int)value)) throw new ArgumentException ("GCHandle value belongs to a different domain"); return new GCHandle (value); @@ -138,23 +151,19 @@ namespace System.Runtime.InteropServices [MethodImplAttribute(MethodImplOptions.InternalCall)] private extern static IntPtr GetAddrOfPinnedObject(int handle); -#if NET_2_0 public static bool operator ==(GCHandle a, GCHandle b) { - return a.Equals(b); + return a.handle == b.handle; } public static bool operator !=(GCHandle a, GCHandle b) { - return (!(a.Equals(b))); + return !(a == b); } public override bool Equals(object o) { - if (o == null || !(o is GCHandle)) - return false; - - return (handle == ((GCHandle)o).handle); + return o is GCHandle ? this == (GCHandle)o : false; } public override int GetHashCode() @@ -171,7 +180,6 @@ namespace System.Runtime.InteropServices { return (IntPtr)value; } -#endif } }