/// <summary> /// The thread loops doing this work forever. /// </summary> private static void ThreadLoop() { #if !(REFERENCE_COUNTING_GC || DEFERRED_REFERENCE_COUNTING_GC) while (running) { if (WaitingToRun == 0) { WaitForPendingShouldReturn.Set(); WorkExistsForFinalizerThread.WaitOne(); continue; } // Get some work Object current = GetObjectFromRun(); VTable.Assert(current != null, "No finalizer found, but WaitingToRun != 0"); try { Magic.callFinalizer(current); } catch { // throw it away! } Interlocked.Decrement(ref WaitingToRun); } WaitForPendingShouldReturn.Set(); // now that the finalizer thread has shutdown, we need to prevent // a GC from occuring Interlocked.Increment(ref GC.allocationGCInhibitCount); #endif // REFERENCE_COUNTING_GC }
/// <summary> /// Wait until the finalization queue has been emptied. /// </summary> internal static void WaitForPending() { #if !(REFERENCE_COUNTING_GC || DEFERRED_REFERENCE_COUNTING_GC) if (Thread.CurrentThread == Finalizer.finalizerThread) { return; } WaitForPendingShouldReturn.WaitOne(); #endif // REFERENCE_COUNTING_GC }
/// <summary> /// Finish up after a collection. /// </summary> internal static void ReleaseCollectFinalizers() { #if !(REFERENCE_COUNTING_GC || DEFERRED_REFERENCE_COUNTING_GC) if (madeRunnable) { // Review: For now we will assert against a GC running after the // finalization thread has shut down. However, if this assert // fires and the situation is somewhat reasonable, then we should // allow a GC to occur. VTable.Assert(running, "Attempt to request finalizer while finalization thread is not running."); WaitForPendingShouldReturn.Reset(); WorkExistsForFinalizerThread.Set(); } #endif // REFERENCE_COUNTING_GC }