Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs')
-rw-r--r--src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs b/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs
new file mode 100644
index 000000000..225268122
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Gen2GcCallback.cs
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ /// <summary>
+ /// Schedules a callback roughly every gen 2 GC (you may see a Gen 0 an Gen 1 but only once)
+ /// (We can fix this by capturing the Gen 2 count at startup and testing, but I mostly don't care)
+ /// </summary>
+ internal sealed class Gen2GcCallback : CriticalFinalizerObject
+ {
+ private Gen2GcCallback()
+ : base()
+ {
+ }
+
+ /// <summary>
+ /// Schedule 'callback' to be called in the next GC. If the callback returns true it is
+ /// rescheduled for the next Gen 2 GC. Otherwise the callbacks stop.
+ ///
+ /// NOTE: This callback will be kept alive until either the callback function returns false,
+ /// or the target object dies.
+ /// </summary>
+ public static void Register(Func<object, bool> callback, object targetObj)
+ {
+ // Create a unreachable object that remembers the callback function and target object.
+ Gen2GcCallback gcCallback = new Gen2GcCallback();
+ gcCallback.Setup(callback, targetObj);
+ }
+
+ private Func<object, bool> _callback;
+ private GCHandle _weakTargetObj;
+
+ private void Setup(Func<object, bool> callback, object targetObj)
+ {
+ _callback = callback;
+ _weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak);
+ }
+
+ ~Gen2GcCallback()
+ {
+ // Check to see if the target object is still alive.
+ object targetObj = _weakTargetObj.Target;
+ if (targetObj == null)
+ {
+ // The target object is dead, so this callback object is no longer needed.
+ _weakTargetObj.Free();
+ return;
+ }
+
+ // Execute the callback method.
+ try
+ {
+ if (!_callback(targetObj))
+ {
+ // If the callback returns false, this callback object is no longer needed.
+ return;
+ }
+ }
+ catch
+ {
+ // Ensure that we still get a chance to resurrect this object, even if the callback throws an exception.
+ }
+
+ // Resurrect ourselves by re-registering for finalization.
+ if (!Environment.HasShutdownStarted)
+ {
+ GC.ReRegisterForFinalize(this);
+ }
+ }
+ }
+}