58587eb15a479f07b7fd6144f8adc2f65289362d
[platform/upstream/dotnet/runtime.git] /
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3
4 using System;
5 using System.Diagnostics;
6 using System.Runtime.InteropServices;
7 using System.Threading;
8 using Microsoft.Win32.SafeHandles;
9
10 namespace System.Runtime.InteropServices.JavaScript
11 {
12     public abstract class AnyRef : SafeHandleMinusOneIsInvalid
13     {
14         private GCHandle? InFlight;
15         private int InFlightCounter;
16         private GCHandle AnyRefHandle;
17         public int JSHandle => (int)handle;
18
19         internal AnyRef(int jsHandle, bool ownsHandle) : this((IntPtr)jsHandle, ownsHandle)
20         { }
21
22         internal AnyRef(IntPtr jsHandle, bool ownsHandle) : base(ownsHandle)
23         {
24             SetHandle(jsHandle);
25             AnyRefHandle = GCHandle.Alloc(this, ownsHandle ? GCHandleType.Weak : GCHandleType.Normal);
26             InFlight = null;
27             InFlightCounter = 0;
28         }
29         internal int Int32Handle => (int)(IntPtr)AnyRefHandle;
30
31         internal void AddInFlight()
32         {
33             lock (this)
34             {
35                 InFlightCounter++;
36                 if (InFlightCounter == 1)
37                 {
38                     Debug.Assert(InFlight == null);
39                     InFlight = GCHandle.Alloc(this, GCHandleType.Normal);
40                 }
41             }
42         }
43
44         internal void ReleaseInFlight()
45         {
46             lock (this)
47             {
48                 Debug.Assert(InFlightCounter != 0);
49
50                 InFlightCounter--;
51                 if (InFlightCounter == 0)
52                 {
53                     Debug.Assert(InFlight.HasValue);
54                     InFlight.Value.Free();
55                     InFlight = null;
56                 }
57             }
58         }
59
60
61         protected void FreeGCHandle()
62         {
63             AnyRefHandle.Free();
64         }
65 #if DEBUG_HANDLE
66         private int _refCount;
67
68         internal void AddRef()
69         {
70             Interlocked.Increment(ref _refCount);
71         }
72
73         internal void Release()
74         {
75             Debug.Assert(_refCount > 0, "AnyRefSafeHandle: Release() called more times than AddRef");
76             Interlocked.Decrement(ref _refCount);
77         }
78
79         internal int RefCount => _refCount;
80 #endif
81     }
82 }