Merge pull request #3389 from lambdageek/bug-43099
[mono.git] / mcs / class / referencesource / System.Web / Util / GCUtil.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="GCUtil.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 namespace System.Web.Util {
8     using System;
9     using System.Runtime.InteropServices;
10     using System.Security.Permissions;
11
12     // Provides helper methods for wrapping managed objects so that they can be passed to and from unmanaged code.
13     // Unmanaged code can't actually inspect these objects at all since they're just GCHandles. And these handles
14     // cannot be reused (they're single-shot).
15
16     [SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
17     internal static class GCUtil {
18
19         public static IntPtr RootObject(object obj) {
20             return (obj != null)
21                 ? (IntPtr)GCHandle.Alloc(obj)
22                 : IntPtr.Zero;
23         }
24
25         public static object UnrootObject(IntPtr pointer) {
26             if (pointer != IntPtr.Zero) {
27                 GCHandle gcHandle = (GCHandle)pointer;
28                 if (gcHandle.IsAllocated) {
29                     object target = gcHandle.Target;
30                     gcHandle.Free();
31                     return target;
32                 }
33             }
34
35             return null;
36         }
37
38     }
39
40     // This wrapper around a managed object is opaque to SizedReference GC handle
41     // and therefore helps with calculating size of only relevant graph of objects
42     internal class DisposableGCHandleRef<T> : IDisposable
43     where T : class, IDisposable {
44         GCHandle _handle;
45         [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
46         public DisposableGCHandleRef(T t) {
47             Debug.Assert(t != null);
48             _handle = GCHandle.Alloc(t);
49         }
50
51         public T Target {
52             [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
53             get {
54                 Debug.Assert(_handle.IsAllocated);
55                 return (T)_handle.Target;
56             }
57         }
58
59         [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
60         public void Dispose() {
61             Target.Dispose();
62             Debug.Assert(_handle.IsAllocated);
63             if (_handle.IsAllocated) {
64                 _handle.Free();
65             }
66         }
67     }
68 }