From d09ee5ed7e54d2acf6bfdb675f03a8a4ad389e50 Mon Sep 17 00:00:00 2001
From: albert-du <52804499+albert-du@users.noreply.github.com>
Date: Sat, 22 Jan 2022 20:36:15 -0800
Subject: [PATCH 1/2] GC F# snippets
---
.../GC/CancelFullGCNotification/Program.fs | 168 ++++++++++++++++++
.../GC/CancelFullGCNotification/fs.fsproj | 9 +
.../fsharp/System/GC/Collect/Program.fs | 7 +
.../fsharp/System/GC/Collect/class1.fs | 24 +++
.../fsharp/System/GC/Collect/collect4.fs | 19 ++
.../fsharp/System/GC/Collect/fs.fsproj | 12 ++
.../System/GC/Collect/lohcompactionmode1.fs | 9 +
.../System/GC/EndNoGCRegion/endnogcregion1.fs | 7 +
.../fsharp/System/GC/EndNoGCRegion/fs.fsproj | 9 +
.../fsharp/System/GC/GetGeneration/fs.fsproj | 9 +
.../systemgcgetgenerationweak.fs | 52 ++++++
.../fsharp/System/GC/KeepAlive/fs.fsproj | 9 +
.../fsharp/System/GC/KeepAlive/gckeepalive.fs | 76 ++++++++
.../fsharp/System/GC/Overview/class1.fs | 45 +++++
.../fsharp/System/GC/Overview/fs.fsproj | 9 +
.../System/GC/ReRegisterForFinalize/class1.fs | 41 +++++
.../System/GC/ReRegisterForFinalize/fs.fsproj | 9 +
.../System/GC/SuppressFinalize/fs.fsproj | 9 +
.../GC/SuppressFinalize/suppressfinalize1.fs | 112 ++++++++++++
.../GC/WaitForPendingFinalizers/class1.fs | 50 ++++++
.../GC/WaitForPendingFinalizers/fs.fsproj | 9 +
xml/System/GC.xml | 19 ++
22 files changed, 713 insertions(+)
create mode 100644 samples/snippets/fsharp/System/GC/CancelFullGCNotification/Program.fs
create mode 100644 samples/snippets/fsharp/System/GC/CancelFullGCNotification/fs.fsproj
create mode 100644 samples/snippets/fsharp/System/GC/Collect/Program.fs
create mode 100644 samples/snippets/fsharp/System/GC/Collect/class1.fs
create mode 100644 samples/snippets/fsharp/System/GC/Collect/collect4.fs
create mode 100644 samples/snippets/fsharp/System/GC/Collect/fs.fsproj
create mode 100644 samples/snippets/fsharp/System/GC/Collect/lohcompactionmode1.fs
create mode 100644 samples/snippets/fsharp/System/GC/EndNoGCRegion/endnogcregion1.fs
create mode 100644 samples/snippets/fsharp/System/GC/EndNoGCRegion/fs.fsproj
create mode 100644 samples/snippets/fsharp/System/GC/GetGeneration/fs.fsproj
create mode 100644 samples/snippets/fsharp/System/GC/GetGeneration/systemgcgetgenerationweak.fs
create mode 100644 samples/snippets/fsharp/System/GC/KeepAlive/fs.fsproj
create mode 100644 samples/snippets/fsharp/System/GC/KeepAlive/gckeepalive.fs
create mode 100644 samples/snippets/fsharp/System/GC/Overview/class1.fs
create mode 100644 samples/snippets/fsharp/System/GC/Overview/fs.fsproj
create mode 100644 samples/snippets/fsharp/System/GC/ReRegisterForFinalize/class1.fs
create mode 100644 samples/snippets/fsharp/System/GC/ReRegisterForFinalize/fs.fsproj
create mode 100644 samples/snippets/fsharp/System/GC/SuppressFinalize/fs.fsproj
create mode 100644 samples/snippets/fsharp/System/GC/SuppressFinalize/suppressfinalize1.fs
create mode 100644 samples/snippets/fsharp/System/GC/WaitForPendingFinalizers/class1.fs
create mode 100644 samples/snippets/fsharp/System/GC/WaitForPendingFinalizers/fs.fsproj
diff --git a/samples/snippets/fsharp/System/GC/CancelFullGCNotification/Program.fs b/samples/snippets/fsharp/System/GC/CancelFullGCNotification/Program.fs
new file mode 100644
index 00000000000..f98c997d409
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/CancelFullGCNotification/Program.fs
@@ -0,0 +1,168 @@
+//
+//
+open System
+open System.Threading
+
+// Variable for continual checking in the
+// While loop in the WaitForFullGCProc method.
+let mutable checkForNotify = false
+
+// Variable for suspending work
+// (such servicing allocated server requests)
+// after a notification is received and then
+// resuming allocation after inducing a garbage collection.
+let mutable bAllocate = false
+
+// Variable for ending the example.
+let mutable finalExit = false
+
+// Collection for objects that simulate the server request workload.
+let load = ResizeArray()
+
+
+//
+let redirectRequests () =
+ // Code that sends requests
+ // to other servers.
+
+ // Suspend work.
+ bAllocate <- false
+
+let finishExistingRequests () =
+ // Code that waits a period of time
+ // for pending requests to finish.
+
+ // Clear the simulated workload.
+ load.Clear()
+
+let acceptRequests () =
+ // Code that resumes processing
+ // requests on this server.
+
+ // Resume work.
+ bAllocate <- true
+//
+
+//
+let onFullGCApproachNotify () =
+ printfn "Redirecting requests."
+
+ // Method that tells the request queuing
+ // server to not direct requests to this server.
+ redirectRequests ()
+
+ // Method that provides time to
+ // finish processing pending requests.
+ finishExistingRequests ()
+
+ // This is a good time to induce a GC collection
+ // because the runtime will induce a full GC soon.
+ // To be very careful, you can check precede with a
+ // check of the GC.GCCollectionCount to make sure
+ // a full GC did not already occur since last notified.
+ GC.Collect()
+ printfn "Induced a collection."
+//
+
+
+//
+let onFullGCCompleteEndNotify () =
+ // Method that informs the request queuing server
+ // that this server is ready to accept requests again.
+ acceptRequests ()
+ printfn "Accepting requests again."
+//
+
+//
+let waitForFullGCProc () =
+ let mutable broken = false
+
+ while not broken do
+ let mutable broken = false
+ // CheckForNotify is set to true and false in Main.
+ while checkForNotify && not broken do
+ //
+ // Check for a notification of an approaching collection.
+ match GC.WaitForFullGCApproach() with
+ | GCNotificationStatus.Succeeded ->
+ printfn "GC Notification raised."
+ onFullGCApproachNotify ()
+ //
+ // Check for a notification of a completed collection.
+ match GC.WaitForFullGCComplete() with
+ | GCNotificationStatus.Succeeded ->
+ printfn "GC Notification raised."
+ onFullGCCompleteEndNotify ()
+ | GCNotificationStatus.Canceled ->
+ printfn "GC Notification cancelled."
+ broken <- true
+ | _ ->
+ // Could be a time out.
+ printfn "GC Notification not applicable."
+ broken <- true
+ //
+ | GCNotificationStatus.Canceled ->
+ printfn "GC Notification cancelled."
+ broken <- true
+ | _ ->
+ // This can occur if a timeout period
+ // is specified for WaitForFullGCApproach(Timeout)
+ // or WaitForFullGCComplete(Timeout)
+ // and the time out period has elapsed.
+ printfn "GC Notification not applicable."
+ broken <- true
+ //
+
+ Thread.Sleep 500
+ // FinalExit is set to true right before
+ // the main thread cancelled notification.
+ if finalExit then broken <- true
+//
+
+
+
+try
+ // Register for a notification.
+ GC.RegisterForFullGCNotification(10, 10)
+ printfn "Registered for GC notification."
+
+ checkForNotify <- true
+ bAllocate <- true
+
+ // Start a thread using WaitForFullGCProc.
+ let thWaitForFullGC = Thread(ThreadStart waitForFullGCProc)
+ thWaitForFullGC.Start()
+
+ // While the thread is checking for notifications in
+ // WaitForFullGCProc, create objects to simulate a server workload.
+ try
+ let mutable lastCollCount = 0
+ let mutable newCollCount = 0
+
+ let mutable broken = false
+
+ while not broken do
+ if bAllocate then
+ load.Add(Array.zeroCreate 1000)
+ newCollCount <- GC.CollectionCount 2
+
+ if newCollCount <> lastCollCount then
+ // Show collection count when it increases:
+ printfn $"Gen 2 collection count: {GC.CollectionCount(2)}"
+ lastCollCount <- newCollCount
+ // For ending the example (arbitrary).
+ if newCollCount = 500 then
+ finalExit <- true
+ checkForNotify <- false
+ broken <- true
+ with :? OutOfMemoryException -> printfn "Out of memory."
+
+ //
+ finalExit <- true
+ checkForNotify <- false
+ GC.CancelFullGCNotification()
+//
+with :? InvalidOperationException as invalidOp ->
+ printfn $"GC Notifications are not supported while concurrent GC is enabled.\n{invalidOp.Message}"
+//
+//
diff --git a/samples/snippets/fsharp/System/GC/CancelFullGCNotification/fs.fsproj b/samples/snippets/fsharp/System/GC/CancelFullGCNotification/fs.fsproj
new file mode 100644
index 00000000000..8b95ffbfe3d
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/CancelFullGCNotification/fs.fsproj
@@ -0,0 +1,9 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/Collect/Program.fs b/samples/snippets/fsharp/System/GC/Collect/Program.fs
new file mode 100644
index 00000000000..3f357f2f886
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/Collect/Program.fs
@@ -0,0 +1,7 @@
+module Program
+
+//
+open System
+
+GC.Collect(2, GCCollectionMode.Optimized)
+//
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/Collect/class1.fs b/samples/snippets/fsharp/System/GC/Collect/class1.fs
new file mode 100644
index 00000000000..1dc207e7a75
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/Collect/class1.fs
@@ -0,0 +1,24 @@
+module class1
+
+//
+open System
+
+let maxGarbage = 1000
+
+let makeSomeGarbage () =
+ // Create objects and release them to fill up memory with unused objects.
+ for _ = 1 to maxGarbage do
+ Version() |> ignore
+
+// Put some objects in memory.
+makeSomeGarbage()
+printfn $"Memory used before collection: {GC.GetTotalMemory false:N0}"
+
+// Collect all generations of memory.
+GC.Collect()
+printfn $"Memory used after full collection: {GC.GetTotalMemory true:N0}"
+
+// The output from the example resembles the following:
+// Memory used before collection: 79,392
+// Memory used after full collection: 52,640
+//
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/Collect/collect4.fs b/samples/snippets/fsharp/System/GC/Collect/collect4.fs
new file mode 100644
index 00000000000..d780f9df1dd
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/Collect/collect4.fs
@@ -0,0 +1,19 @@
+module collect4
+
+open System
+open System.Runtime
+
+let createObjects () =
+ Array.init 10000 (fun i ->
+ let s1= "word1"
+ let s2 = "word2"
+ s1 + " " + s2 )
+ |> ignore
+
+createObjects ()
+printfn $"Memory allocated before GC: {GC.GetTotalMemory false:N0}"
+//
+GCSettings.LargeObjectHeapCompactionMode <- GCLargeObjectHeapCompactionMode.CompactOnce
+GC.Collect(2, GCCollectionMode.Forced, true, true)
+//
+printfn $"Memory allocated after GC: {GC.GetTotalMemory false:N0}"
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/Collect/fs.fsproj b/samples/snippets/fsharp/System/GC/Collect/fs.fsproj
new file mode 100644
index 00000000000..7b9839f1202
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/Collect/fs.fsproj
@@ -0,0 +1,12 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/Collect/lohcompactionmode1.fs b/samples/snippets/fsharp/System/GC/Collect/lohcompactionmode1.fs
new file mode 100644
index 00000000000..76f37cc0e0e
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/Collect/lohcompactionmode1.fs
@@ -0,0 +1,9 @@
+module lohcompactionmode1
+
+open System
+open System.Runtime
+
+//
+GCSettings.LargeObjectHeapCompactionMode <- GCLargeObjectHeapCompactionMode.CompactOnce
+GC.Collect()
+//
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/EndNoGCRegion/endnogcregion1.fs b/samples/snippets/fsharp/System/GC/EndNoGCRegion/endnogcregion1.fs
new file mode 100644
index 00000000000..88750f23ae0
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/EndNoGCRegion/endnogcregion1.fs
@@ -0,0 +1,7 @@
+open System
+open System.Runtime
+
+//
+if GCSettings.LatencyMode = GCLatencyMode.NoGCRegion then
+ GC.EndNoGCRegion()
+//
diff --git a/samples/snippets/fsharp/System/GC/EndNoGCRegion/fs.fsproj b/samples/snippets/fsharp/System/GC/EndNoGCRegion/fs.fsproj
new file mode 100644
index 00000000000..63c0860488e
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/EndNoGCRegion/fs.fsproj
@@ -0,0 +1,9 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/GetGeneration/fs.fsproj b/samples/snippets/fsharp/System/GC/GetGeneration/fs.fsproj
new file mode 100644
index 00000000000..374c9619b9c
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/GetGeneration/fs.fsproj
@@ -0,0 +1,9 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/GetGeneration/systemgcgetgenerationweak.fs b/samples/snippets/fsharp/System/GC/GetGeneration/systemgcgetgenerationweak.fs
new file mode 100644
index 00000000000..d78518cb097
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/GetGeneration/systemgcgetgenerationweak.fs
@@ -0,0 +1,52 @@
+//
+open System
+
+let maxGarbage = 1000
+
+[]
+type MyGCCollectClass() =
+ member _.MakeSomeGarbage() =
+ for i = 1 to maxGarbage do
+ // Create objects and release them to fill up memory
+ // with unused objects.
+ Version() |> ignore
+
+// Create a strong reference to an object.
+let mutable myGCCol = MyGCCollectClass()
+
+// Put some objects in memory.
+myGCCol.MakeSomeGarbage()
+
+// Get the generation of managed memory where myGCCol is stored.
+printfn $"The object is in generation: {GC.GetGeneration myGCCol}"
+
+// Perform a full garbage collection.
+// Because there is a strong reference to myGCCol, it will
+// not be garbage collected.
+GC.Collect()
+
+// Get the generation of managed memory where myGCCol is stored.
+printfn $"The object is in generation: {GC.GetGeneration myGCCol}"
+
+// Create a WeakReference to myGCCol.
+let wkref = WeakReference myGCCol
+// Remove the strong reference to myGCCol.
+myGCCol <- null
+
+// Get the generation of managed memory where wkref is stored.
+printfn $"The WeakReference to the object is in generation: {GC.GetGeneration wkref}"
+
+// Perform another full garbage collection.
+// A WeakReference will not survive a garbage collection.
+GC.Collect()
+
+// Try to get the generation of managed memory where wkref is stored.
+// Because it has been collected, an exception will be thrown.
+try
+ printfn $"The WeakReference to the object is in generation: {GC.GetGeneration wkref}"
+ stdin.Read() |> ignore
+with e ->
+ printfn $"The WeakReference to the object has been garbage collected: '{e}'"
+ stdin.Read() |> ignore
+
+//
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/KeepAlive/fs.fsproj b/samples/snippets/fsharp/System/GC/KeepAlive/fs.fsproj
new file mode 100644
index 00000000000..b546c98d087
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/KeepAlive/fs.fsproj
@@ -0,0 +1,9 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/KeepAlive/gckeepalive.fs b/samples/snippets/fsharp/System/GC/KeepAlive/gckeepalive.fs
new file mode 100644
index 00000000000..ebae7e7f69f
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/KeepAlive/gckeepalive.fs
@@ -0,0 +1,76 @@
+//
+open System
+open System.Threading
+open System.Runtime.InteropServices
+
+// A simple module that exposes two static Win32 functions.
+// One is a delegate type and the other is an enumerated type.
+module MyWin32 =
+ // An enumerated type for the control messages
+ // sent to the handler routine.
+ type CtrlTypes =
+ | CTRL_C_EVENT = 0
+ | CTRL_BREAK_EVENT = 1
+ | CTRL_CLOSE_EVENT = 2
+ | CTRL_LOGOFF_EVENT = 5
+ | CTRL_SHUTDOWN_EVENT = 6
+
+ // A delegate type to be used as the handler routine for SetConsoleCtrlHandler.
+ type HandlerRoutine = delegate of CtrlTypes -> bool
+
+ // Declare the SetConsoleCtrlHandler function
+ // as external and receiving a delegate.
+ []
+ extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add)
+
+// A private static handler function in the MyApp class.
+let handler (ctrlType: MyWin32.CtrlTypes) =
+ let message =
+ // Pattern match to handle the event type.
+ match ctrlType with
+ | MyWin32.CtrlTypes.CTRL_C_EVENT ->
+ "A CTRL_C_EVENT was raised by the user."
+ | MyWin32.CtrlTypes.CTRL_BREAK_EVENT ->
+ "A CTRL_BREAK_EVENT was raised by the user."
+ | MyWin32.CtrlTypes.CTRL_CLOSE_EVENT ->
+ "A CTRL_CLOSE_EVENT was raised by the user."
+ | MyWin32.CtrlTypes.CTRL_LOGOFF_EVENT ->
+ "A CTRL_LOGOFF_EVENT was raised by the user."
+ | MyWin32.CtrlTypes.CTRL_SHUTDOWN_EVENT ->
+ "A CTRL_SHUTDOWN_EVENT was raised by the user."
+ | _ -> "This message should never be seen!"
+
+ // Use interop to display a message for the type of event.
+ printfn $"{message}"
+ true
+
+// Use interop to set a console control handler.
+let hr = MyWin32.HandlerRoutine handler
+MyWin32.SetConsoleCtrlHandler(hr, true) |> ignore
+
+// Give the user some time to raise a few events.
+printfn "Waiting 30 seconds for console ctrl events..."
+
+// The object hr is not referred to again.
+// The garbage collector can detect that the object has no
+// more managed references and might clean it up here while
+// the unmanaged SetConsoleCtrlHandler method is still using it.
+
+// Force a garbage collection to demonstrate how the hr
+// object will be handled.
+GC.Collect()
+GC.WaitForPendingFinalizers()
+GC.Collect()
+
+Thread.Sleep 30000
+
+// Display a message to the console when the unmanaged method
+// has finished its work.
+printfn "Finished!"
+
+// Call GC.KeepAlive(hr) at this point to maintain a reference to hr.
+// This will prevent the garbage collector from collecting the
+// object during the execution of the SetConsoleCtrlHandler method.
+GC.KeepAlive hr
+Console.Read() |> ignore
+//
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/Overview/class1.fs b/samples/snippets/fsharp/System/GC/Overview/class1.fs
new file mode 100644
index 00000000000..481de49eac1
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/Overview/class1.fs
@@ -0,0 +1,45 @@
+//
+open System
+
+let maxGarbage = 1000
+
+type MyGCCollectClass() =
+ member _.MakeSomeGarbage() =
+ for _ = 1 to maxGarbage do
+ // Create objects and release them to fill up memory with unused objects.
+ Version() |> ignore
+
+[]
+let main _ =
+ let myGCCol = MyGCCollectClass()
+
+ // Determine the maximum number of generations the system
+ // garbage collector currently supports.
+ printfn $"The highest generation is {GC.MaxGeneration}"
+
+ myGCCol.MakeSomeGarbage()
+
+ // Determine which generation myGCCol object is stored in.
+ printfn $"Generation: {GC.GetGeneration myGCCol}"
+
+ // Determine the best available approximation of the number
+ // of bytes currently allocated in managed memory.
+ printfn $"Total Memory: {GC.GetTotalMemory false}"
+
+ // Perform a collection of generation 0 only.
+ GC.Collect 0
+
+ // Determine which generation myGCCol object is stored in.
+ printfn $"Generation: {GC.GetGeneration myGCCol}"
+
+ printfn $"Total Memory: {GC.GetTotalMemory false}"
+
+ // Perform a collection of all generations up to and including 2.
+ GC.Collect 2
+
+ // Determine which generation myGCCol object is stored in.
+ printfn $"Generation: {GC.GetGeneration myGCCol}"
+ printfn $"Total Memory: {GC.GetTotalMemory false}"
+
+ 0
+//
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/Overview/fs.fsproj b/samples/snippets/fsharp/System/GC/Overview/fs.fsproj
new file mode 100644
index 00000000000..0d4b6596c65
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/Overview/fs.fsproj
@@ -0,0 +1,9 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/ReRegisterForFinalize/class1.fs b/samples/snippets/fsharp/System/GC/ReRegisterForFinalize/class1.fs
new file mode 100644
index 00000000000..db0112c4309
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/ReRegisterForFinalize/class1.fs
@@ -0,0 +1,41 @@
+//
+open System
+
+[]
+type MyFinalizeObject() =
+ let mutable hasFinalized = false
+
+ static member val CurrentInstance = null with get, set
+
+ override this.Finalize() =
+ if hasFinalized then
+ printfn "First finalization"
+
+ // Put this object back into a root by creating a reference to it.
+ MyFinalizeObject.CurrentInstance <- this
+
+ // Indicate that this instance has finalized once.
+ hasFinalized <- true
+
+ // Place a reference to this object back in the finalization queue.
+ GC.ReRegisterForFinalize this
+ else
+ printfn "Second finalization"
+
+// Create a MyFinalizeObject.
+let mutable mfo = MyFinalizeObject()
+
+// Release the reference to mfo.
+mfo <- null
+
+// Force a garbage collection.
+GC.Collect()
+
+// At this point mfo will have gone through the first Finalize.
+// There should now be a reference to mfo in the static
+// MyFinalizeObject.CurrentInstance property. Setting this value
+// to null and forcing another garbage collection will now
+// cause the object to Finalize permanently.
+MyFinalizeObject.CurrentInstance <- null
+GC.Collect()
+//
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/ReRegisterForFinalize/fs.fsproj b/samples/snippets/fsharp/System/GC/ReRegisterForFinalize/fs.fsproj
new file mode 100644
index 00000000000..0d4b6596c65
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/ReRegisterForFinalize/fs.fsproj
@@ -0,0 +1,9 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/SuppressFinalize/fs.fsproj b/samples/snippets/fsharp/System/GC/SuppressFinalize/fs.fsproj
new file mode 100644
index 00000000000..443db6f4104
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/SuppressFinalize/fs.fsproj
@@ -0,0 +1,9 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/SuppressFinalize/suppressfinalize1.fs b/samples/snippets/fsharp/System/GC/SuppressFinalize/suppressfinalize1.fs
new file mode 100644
index 00000000000..f154a6ddc5d
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/SuppressFinalize/suppressfinalize1.fs
@@ -0,0 +1,112 @@
+//
+open System
+open System.ComponentModel
+open System.Runtime.InteropServices
+
+[]
+extern IntPtr GetStdHandle(int nStdHandle)
+
+[]
+extern bool WriteConsole(IntPtr hConsoleOutput, string lpBuffer, uint nNumberOfCharsToWrite, uint& lpNumberOfCharsWritten, IntPtr lpReserved)
+
+[]
+extern bool CloseHandle(IntPtr handle)
+
+type ConsoleMonitor() =
+ let STD_INPUT_HANDLE = -10
+ let STD_OUTPUT_HANDLE = -11
+ let STD_ERROR_HANDLE = -12
+
+ let handle =
+ let h = GetStdHandle STD_OUTPUT_HANDLE
+ if h = IntPtr.Zero then
+ raise (InvalidOperationException "A console handle is not available.")
+ else
+ h
+
+ let comp = new Component()
+ let output = "The ConsoleMonitor class constructor.\n"
+ let mutable disposed = false
+ let mutable written = 0u
+ do
+ WriteConsole(handle, output, uint output.Length, &written, IntPtr.Zero)
+ |> ignore
+
+ // The finalizer represents Object.Finalize override.
+ override this.Finalize() =
+ if handle <> IntPtr.Zero then
+ let output = "The ConsoleMonitor finalizer.\n"
+ let mutable written = 0u
+ WriteConsole(handle, output, uint output.Length, &written, IntPtr.Zero)
+ |> ignore
+ else
+ eprintfn "Object finalization."
+ this.Dispose false
+
+ member _.Write() =
+ let output = "The Write method.\n"
+ let mutable written = 0u
+
+ WriteConsole(handle, output, uint output.Length, &written, IntPtr.Zero)
+ |> ignore
+
+ member _.Dispose(disposing: bool) =
+ let output = $"The Dispose({disposing}) method.\n"
+ let mutable written = 0u
+
+ WriteConsole(handle, output, uint output.Length, &written, IntPtr.Zero)
+ |> ignore
+
+ // Execute if resources have not already been disposed.
+ if not disposed then
+ // If the call is from Dispose, free managed resources.
+ if disposing then
+ eprintfn "Disposing of managed resources."
+ if comp <> null then comp.Dispose()
+ // Free unmanaged resources.
+ let output = "Disposing of unmanaged resources."
+
+ WriteConsole(handle, output, uint output.Length, &written, IntPtr.Zero)
+ |> ignore
+
+ if handle <> IntPtr.Zero then
+ if not (CloseHandle handle) then
+ eprintfn "Handle cannot be closed."
+
+ disposed <- true
+
+ member this.Dispose() =
+ let output = "The Dispose method.\n"
+ let mutable written = 0u
+
+ WriteConsole(handle, output, uint output.Length, &written, IntPtr.Zero)
+ |> ignore
+
+ this.Dispose true
+ GC.SuppressFinalize this
+
+ interface IDisposable with
+ member this.Dispose() = this.Dispose()
+
+printfn "ConsoleMonitor instance...."
+let monitor = new ConsoleMonitor()
+monitor.Write()
+monitor.Dispose()
+
+// If the monitor.Dispose method is not called, the example displays the following output:
+// ConsoleMonitor instance....
+// The ConsoleMonitor class constructor.
+// The Write method.
+// The ConsoleMonitor finalizer.
+// The Dispose(False) method.
+// Disposing of unmanaged resources.
+//
+// If the monitor.Dispose method is called, the example displays the following output:
+// ConsoleMonitor instance....
+// The ConsoleMonitor class constructor.
+// The Write method.
+// The Dispose method.
+// The Dispose(True) method.
+// Disposing of managed resources.
+// Disposing of unmanaged resources.
+//
diff --git a/samples/snippets/fsharp/System/GC/WaitForPendingFinalizers/class1.fs b/samples/snippets/fsharp/System/GC/WaitForPendingFinalizers/class1.fs
new file mode 100644
index 00000000000..92534d8be85
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/WaitForPendingFinalizers/class1.fs
@@ -0,0 +1,50 @@
+//
+open System
+
+// You can increase this number to fill up more memory.
+let numMfos = 1000
+
+// You can increase this number to cause more
+// post-finalization work to be done.
+let maxIterations = 100
+
+[]
+type MyFinalizeObject() =
+ // Make this number very large to cause the finalizer todo more work.
+ let maxIterations = 10000
+
+ override _.Finalize() =
+ printfn "Finalizing a MyFinalizeObject"
+
+ // Do some work.
+ for i = 1 to maxIterations do
+ // This method performs no operation on i, but prevents
+ // the JIT compiler from optimizing away the code inside
+ // the loop.
+ GC.KeepAlive i
+
+let mutable mfo = null
+
+// Create and release a large number of objects
+// that require finalization.
+for j = 1 to numMfos do
+ mfo <- MyFinalizeObject()
+
+//Release the last object created in the loop.
+mfo <- null
+
+//Force garbage collection.
+GC.Collect()
+
+// Wait for all finalizers to complete before continuing.
+// Without this call to GC.WaitForPendingFinalizers,
+// the worker loop below might execute at the same time
+// as the finalizers.
+// With this call, the worker loop executes only after
+// all finalizers have been called.
+GC.WaitForPendingFinalizers()
+
+// Worker loop to perform post-finalization code.
+for _ = 1 to maxIterations do
+ printfn "Doing some post-finalize work"
+//
\ No newline at end of file
diff --git a/samples/snippets/fsharp/System/GC/WaitForPendingFinalizers/fs.fsproj b/samples/snippets/fsharp/System/GC/WaitForPendingFinalizers/fs.fsproj
new file mode 100644
index 00000000000..0d4b6596c65
--- /dev/null
+++ b/samples/snippets/fsharp/System/GC/WaitForPendingFinalizers/fs.fsproj
@@ -0,0 +1,9 @@
+
+
+ Exe
+ net6.0
+
+
+
+
+
\ No newline at end of file
diff --git a/xml/System/GC.xml b/xml/System/GC.xml
index 54b3f6eaaf8..3ded4fbf8dd 100644
--- a/xml/System/GC.xml
+++ b/xml/System/GC.xml
@@ -99,6 +99,7 @@
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.gc.collect int example/CPP/class1.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Overview/class1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Overview/class1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.gc.collect int example/VB/class1.vb" id="Snippet1":::
]]>
@@ -321,6 +322,7 @@ If pinned is set to `true`, `T` must not be a reference type or a type that cont
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR/GCNotification/cpp/program.cpp" id="Snippet7":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/CancelFullGCNotification/Program.cs" id="Snippet7":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/CancelFullGCNotification/Program.fs" id="Snippet7":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR/GCNotification/vb/program.vb" id="Snippet7":::
]]>
@@ -397,6 +399,7 @@ If pinned is set to `true`, `T` must not be a reference type or a type that cont
Starting with the .NET Framework 4.5.1, you can compact the large object heap (LOH) by setting the property to before calling the method, as the following example illustrates.
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Collect/lohcompactionmode1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Collect/lohcompactionmode1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.runtime.gcsettings/vb/lohcompactionmode1.vb" id="Snippet1":::
@@ -406,6 +409,7 @@ If pinned is set to `true`, `T` must not be a reference type or a type that cont
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.GC.Collect Example/CPP/class1.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Collect/class1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Collect/class1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.GC.Collect Example/VB/class1.vb" id="Snippet1":::
]]>
@@ -473,6 +477,7 @@ If pinned is set to `true`, `T` must not be a reference type or a type that cont
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.gc.collect int example/CPP/class1.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Overview/class1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Overview/class1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.gc.collect int example/VB/class1.vb" id="Snippet1":::
]]>
@@ -550,6 +555,7 @@ If pinned is set to `true`, `T` must not be a reference type or a type that cont
The following example forces a garbage collection for generation 2 objects with the setting.
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Collect/Program.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Collect/Program.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.GC.GCCollectionMode/vb/program.vb" id="Snippet1":::
]]>
@@ -696,6 +702,7 @@ If pinned is set to `true`, `T` must not be a reference type or a type that cont
You can call the method to reduce the managed heap to the smallest size possible, as the following code fragment illustrates.
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Collect/collect4.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Collect/collect4.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.gc.collect/vb/collect4.vb" id="Snippet1":::
Specifying `true` for the `compacting` argument guarantees a compacting, full blocking garbage collection. Setting the property to ensures that both the LOH and SOH are compacted.
@@ -820,6 +827,7 @@ If pinned is set to `true`, `T` must not be a reference type or a type that cont
You can prevent an exception for any of these reasons by using code such as the following:
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/EndNoGCRegion/endnogcregion1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/EndNoGCRegion/endnogcregion1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.gc.endnogcregion/vb/endnogcregion1.vb" id="Snippet1":::
]]>
@@ -1021,6 +1029,7 @@ This method is most useful in monitoring scenarios for measuring the difference
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.gc.collect int example/CPP/class1.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Overview/class1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Overview/class1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.gc.collect int example/VB/class1.vb" id="Snippet1":::
]]>
@@ -1080,6 +1089,7 @@ This method is most useful in monitoring scenarios for measuring the difference
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.GC.GetGenerationWeak Example/CPP/systemgcgetgenerationweak.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/GetGeneration/systemgcgetgenerationweak.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/GetGeneration/systemgcgetgenerationweak.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.GC.GetGenerationWeak Example/VB/systemgcgetgenerationweak.vb" id="Snippet1":::
]]>
@@ -1183,6 +1193,7 @@ This method is most useful in monitoring scenarios for measuring the difference
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.gc.collect int example/CPP/class1.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Overview/class1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Overview/class1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.gc.collect int example/VB/class1.vb" id="Snippet1":::
]]>
@@ -1258,6 +1269,7 @@ This method is most useful in monitoring scenarios for measuring the difference
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.GC.KeepAlive Example2/CPP/gckeepalive.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/KeepAlive/gckeepalive.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/KeepAlive/gckeepalive.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.GC.KeepAlive Example2/VB/gckeepalive.vb" id="Snippet1":::
]]>
@@ -1328,6 +1340,7 @@ This method is most useful in monitoring scenarios for measuring the difference
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.gc.collect int example/CPP/class1.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Overview/class1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Overview/class1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.gc.collect int example/VB/class1.vb" id="Snippet1":::
]]>
@@ -1414,6 +1427,7 @@ This method is most useful in monitoring scenarios for measuring the difference
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR/GCNotification/cpp/program.cpp" id="Snippet2":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/CancelFullGCNotification/Program.cs" id="Snippet2":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/CancelFullGCNotification/Program.fs" id="Snippet2":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR/GCNotification/vb/program.vb" id="Snippet2":::
]]>
@@ -1561,6 +1575,7 @@ This method is most useful in monitoring scenarios for measuring the difference
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.GC.ReRegisterForFinalize Example/CPP/class1.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/ReRegisterForFinalize/class1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/ReRegisterForFinalize/class1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.GC.ReRegisterForFinalize Example/VB/class1.vb" id="Snippet1":::
]]>
@@ -1641,6 +1656,7 @@ If `obj` does not have a finalizer or the GC has already signaled the finalizer
The following example demonstrates how to use the method in a resource class to prevent a redundant garbage collection from being called. The example uses the [dispose pattern](/dotnet/standard/garbage-collection/implementing-dispose) to free both managed resources (that is, objects that implement ) and unmanaged resources.
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/SuppressFinalize/suppressfinalize1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/SuppressFinalize/suppressfinalize1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.gc.suppressfinalize/vb/suppressfinalize1.vb" id="Snippet1":::
]]>
@@ -2020,6 +2036,7 @@ If `obj` does not have a finalizer or the GC has already signaled the finalizer
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR/GCNotification/cpp/program.cpp" id="Snippet3":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/CancelFullGCNotification/Program.cs" id="Snippet3":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/CancelFullGCNotification/Program.fs" id="Snippet3":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR/GCNotification/vb/program.vb" id="Snippet3":::
]]>
@@ -2160,6 +2177,7 @@ If `obj` does not have a finalizer or the GC has already signaled the finalizer
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR/GCNotification/cpp/program.cpp" id="Snippet4":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/CancelFullGCNotification/Program.cs" id="Snippet4":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/CancelFullGCNotification/Program.fs" id="Snippet4":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR/GCNotification/vb/program.vb" id="Snippet4":::
]]>
@@ -2290,6 +2308,7 @@ If `obj` does not have a finalizer or the GC has already signaled the finalizer
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR_System/system.GC.WaitForPendingFinalizers Example/CPP/class1.cpp" id="Snippet1":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/WaitForPendingFinalizers/class1.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/WaitForPendingFinalizers/class1.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.GC.WaitForPendingFinalizers Example/VB/class1.vb" id="Snippet1":::
]]>
From ff32ae3990d62ffa4882f86782568ec6d185fef6 Mon Sep 17 00:00:00 2001
From: albert-du <52804499+albert-du@users.noreply.github.com>
Date: Sat, 22 Jan 2022 20:43:09 -0800
Subject: [PATCH 2/2] related type snippet refs
---
xml/System/GCCollectionMode.xml | 1 +
xml/System/GCNotificationStatus.xml | 1 +
2 files changed, 2 insertions(+)
diff --git a/xml/System/GCCollectionMode.xml b/xml/System/GCCollectionMode.xml
index 13e815cde6a..4739d626e2a 100644
--- a/xml/System/GCCollectionMode.xml
+++ b/xml/System/GCCollectionMode.xml
@@ -57,6 +57,7 @@
The following example forces a garbage collection for generation 2 objects with the Optimized setting.
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/Collect/Program.cs" id="Snippet1":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/Collect/Program.fs" id="Snippet1":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR_System/system.GC.GCCollectionMode/vb/program.vb" id="Snippet1":::
]]>
diff --git a/xml/System/GCNotificationStatus.xml b/xml/System/GCNotificationStatus.xml
index 88891804c96..48d1d067e6a 100644
--- a/xml/System/GCNotificationStatus.xml
+++ b/xml/System/GCNotificationStatus.xml
@@ -53,6 +53,7 @@
:::code language="cpp" source="~/samples/snippets/cpp/VS_Snippets_CLR/GCNotification/cpp/program.cpp" id="Snippet8":::
:::code language="csharp" source="~/samples/snippets/csharp/System/GC/CancelFullGCNotification/Program.cs" id="Snippet8":::
+ :::code language="fsharp" source="~/samples/snippets/fsharp/System/GC/CancelFullGCNotification/Program.fs" id="Snippet8":::
:::code language="vb" source="~/samples/snippets/visualbasic/VS_Snippets_CLR/GCNotification/vb/program.vb" id="Snippet8":::
]]>