Thanks to visit codestin.com
Credit goes to github.com

Skip to content

System.Lazy<T> F# snippets #7775

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions snippets/fsharp/System/LazyT/.ctor/example.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
module example

//<SnippetAll>
open System
open System.Threading

type LargeObject() =
let initBy = Thread.CurrentThread.ManagedThreadId
do
printfn $"LargeObject was created on thread id {initBy}."

member val Data = Array.zeroCreate<int64> 100000000 with get
member _.InitializedBy = initBy

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
//<SnippetNewLazy>
let lazyLargeObject = Lazy<LargeObject>()

// The following lines show how to use other constructors to achieve exactly the
// same result as the previous line:
// let lazyLargeObject = Lazy<LargeObject>(true)
// let lazyLargeObject = Lazy<LargeObject>(LazyThreadSafetyMode.ExecutionAndPublication)
//</SnippetNewLazy>

let threadProc (state: obj) =
// Wait for the signal.
let waitForStart = state :?> ManualResetEvent
waitForStart.WaitOne() |> ignore

//<SnippetValueProp>
let large = lazyLargeObject.Value
//</SnippetValueProp>

// The following line introduces an artificial delay to exaggerate the race condition.
Thread.Sleep 5

// IMPORTANT: Lazy initialization is thread-safe, but it doesn't protect the
// object after creation. You must lock the object before accessing it,
// unless the type is thread safe. (LargeObject is not thread safe.)
lock large (fun () ->
large.Data[0] <- Thread.CurrentThread.ManagedThreadId
printfn $"Initialized by thread {large.InitializedBy} last used by thread {large.Data[0]}." )

printfn """
LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject."""
stdin.ReadLine() |> ignore

// Create and start 3 threads, passing the same blocking event to all of them.
let startingGate = new ManualResetEvent false
let threads = [| Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc) |]
for t in threads do
t.Start startingGate

// Give all 3 threads time to start and wait, then release them all at once.
Thread.Sleep 100
startingGate.Set() |> ignore

// Wait for all 3 threads to finish. (The order doesn't matter.)
for t in threads do
t.Join()

printfn "\nPress Enter to end the program"
stdin.ReadLine() |> ignore

// This example produces output similar to the following:
// LargeObject is not created until you access the Value property of the lazy
// initializer. Press Enter to create LargeObject.
//
// LargeObject was created on thread id 4.
// Initialized by thread 4 last used by thread 3.
// Initialized by thread 4 last used by thread 4.
// Initialized by thread 4 last used by thread 5.
//
// Press Enter to end the program
//</SnippetAll>
44 changes: 44 additions & 0 deletions snippets/fsharp/System/LazyT/.ctor/example1.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
module example1

//<SnippetAll>
open System
open System.Threading

type LargeObject () =
do
printfn $"LargeObject was created on thread id {Thread.CurrentThread.ManagedThreadId}."

member val Data = Array.zeroCreate<int64> 100000000 with get

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
//<SnippetNewLazy>
let lazyLargeObject = Lazy<LargeObject> false
// The following lines show how to use other constructors to achieve exactly the
// same result as the previous line:
// let lazyLargeObject = Lazy<LargeObject>(LazyThreadSafetyMode.None)
//</SnippetNewLazy>

printfn """
LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject."""
stdin.ReadLine() |> ignore

//<SnippetValueProp>
let large = lazyLargeObject.Value
//</SnippetValueProp>

large.Data[11] <- 89

printfn "\nPress Enter to end the program"
stdin.ReadLine() |> ignore


// This example produces output similar to the following:
// LargeObject is not created until you access the Value property of the lazy
// initializer. Press Enter to create LargeObject.
//
// LargeObject was created on thread id 1.
//
// Press Enter to end the program
//</SnippetAll>
77 changes: 77 additions & 0 deletions snippets/fsharp/System/LazyT/.ctor/example2.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
module example2

//<SnippetAll>
open System
open System.Threading

//<SnippetLargeCtor>
type LargeObject() =
static let mutable instanceCount = 0
let initBy = Thread.CurrentThread.ManagedThreadId
do
if 1 = Interlocked.Increment &instanceCount then
raise (ApplicationException "Throw only ONCE.")
printfn $"LargeObject was created on thread id {initBy}."
//</SnippetLargeCtor>
member _.InitializedBy = initBy
member val Data = Array.zeroCreate<int64> 100000000

//<SnippetFactoryFunc>
let initLargeObject () =
LargeObject()
//</SnippetFactoryFunc>

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
//<SnippetNewLazy>
let lazyLargeObject = Lazy<LargeObject> initLargeObject

// The following lines show how to use other constructors to achieve exactly the
// same result as the previous line:
// let lazyLargeObject = Lazy<LargeObject>(initLargeObject, true)
// let lazyLargeObject = Lazy<LargeObject>(initLargeObject, LazyThreadSafetyMode.ExecutionAndPublication)
//</SnippetNewLazy>

let threadProc _ =
//<SnippetValueProp>
try
let large = lazyLargeObject.Value

// IMPORTANT: Lazy initialization is thread-safe, but it doesn't protect the
// object after creation. You must lock the object before accessing it,
// unless the type is thread safe. (LargeObject is not thread safe.)
lock large (fun () ->
large.Data[0] <- Thread.CurrentThread.ManagedThreadId
printfn $"Initialized by thread {large.InitializedBy} last used by thread {large.Data[0]}.")
with :? ApplicationException as aex ->
printfn $"Exception: {aex.Message}"
//</SnippetValueProp>

printfn """
LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject."""
stdin.ReadLine () |> ignore

// Create and start 3 threads, each of which tries to use LargeObject.
let threads =
[| Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc) |]
for t in threads do
t.Start()

// Wait for all 3 threads to finish. (The order doesn't matter.)
for t in threads do
t.Join()

printfn "\nPress Enter to end the program"
stdin.ReadLine() |> ignore

// This example produces output similar to the following:
// LargeObject is not created until you access the Value property of the lazy
// initializer. Press Enter to create LargeObject.
//
// Exception: Throw only ONCE.
// Exception: Throw only ONCE.
// Exception: Throw only ONCE.
//
// Press Enter to end the program
//</SnippetAll>
59 changes: 59 additions & 0 deletions snippets/fsharp/System/LazyT/.ctor/example3.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module example3

//<SnippetAll>
open System
open System.Threading

//<SnippetLargeCtor>
type LargeObject() =
static let mutable pleaseThrow = true
do
if pleaseThrow then
pleaseThrow <- false
raise (ApplicationException "Throw only ONCE.")
printfn $"LargeObject was created on thread id {Thread.CurrentThread.ManagedThreadId}."
//</SnippetLargeCtor>
member val Data = Array.zeroCreate<int64> 100000000

//<SnippetFactoryFunc>
let initLargeObject () =
LargeObject()
//</SnippetFactoryFunc>

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
//<SnippetNewLazy>
let lazyLargeObject = Lazy<LargeObject>(initLargeObject, false)

// The following lines show how to use other constructors to achieve exactly the
// same result as the previous line:
// let lazyLargeObject = Lazy<LargeObject>(initLargeObject, LazyThreadSafetyMode.None)
//</SnippetNewLazy>

printfn """
LargeObject is not created until you access the Value property of the lazy
initializer. Press Enter to create LargeObject (three tries)."""
stdin.ReadLine() |> ignore

//<SnippetValueProp>
for _ = 0 to 2 do
try
let large = lazyLargeObject.Value
large.Data[11] <- 89
with :? ApplicationException as aex ->
printfn $"Exception: {aex.Message}"
//</SnippetValueProp>

printfn "\nPress Enter to end the program"
stdin.ReadLine() |> ignore

// This example produces output similar to the following:
// LargeObject is not created until you access the Value property of the lazy
// initializer. Press Enter to create LargeObject (three tries).
//
// Exception: Throw only ONCE.
// Exception: Throw only ONCE.
// Exception: Throw only ONCE.
//
// Press Enter to end the program
//</SnippetAll>
93 changes: 93 additions & 0 deletions snippets/fsharp/System/LazyT/.ctor/example4.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//<SnippetAll>
open System
open System.Threading

//<SnippetCtorFinalizer>
type LargeObject(initBy) =
do
printfn $"Constructor: Instance initializing on thread {initBy}"

override _.Finalize() =
printfn $"Finalizer: Instance was initialized on {initBy}"
//</SnippetCtorFinalizer>
member _.InitializedBy = initBy
member val Data = Array.zeroCreate<int64> 100000000 with get

// Factory function for lazy initialization.
//<SnippetFactoryFunc>
let mutable instanceCount = 0
let initLargeObject () =
if 1 = Interlocked.Increment &instanceCount then
raise (ApplicationException $"Lazy initialization function failed on thread {Thread.CurrentThread.ManagedThreadId}.")
LargeObject Thread.CurrentThread.ManagedThreadId
//</SnippetFactoryFunc>

// The lazy initializer is created here. LargeObject is not created until the
// ThreadProc method executes.
//<SnippetNewLazy>
let lazyLargeObject = Lazy<LargeObject>(initLargeObject, LazyThreadSafetyMode.PublicationOnly)
//</SnippetNewLazy>

let threadProc (state: obj) =
// Wait for the signal.
let waitForStart = state :?> ManualResetEvent
waitForStart.WaitOne() |> ignore

//<SnippetValueProp>
try
let large = lazyLargeObject.Value

// The following line introduces an artificial delay to exaggerate the race condition.
Thread.Sleep 5

// IMPORTANT: Lazy initialization is thread-safe, but it doesn't protect the
// object after creation. You must lock the object before accessing it,
// unless the type is thread safe. (LargeObject is not thread safe.)
lock large (fun () ->
large.Data[0] <- Thread.CurrentThread.ManagedThreadId
printfn $"LargeObject was initialized by thread {large.InitializedBy} last used by thread {large.Data[0]}.")
with :? ApplicationException as ex ->
printfn $"ApplicationException: {ex.Message}"
//</SnippetValueProp>

// Create and start 3 threads, passing the same blocking event to all of them.
let startingGate = new ManualResetEvent false
let threads =
[| Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc); Thread(ParameterizedThreadStart threadProc) |]
for t in threads do
t.Start startingGate

// Give all 3 threads time to start and wait, then release them all at once.
Thread.Sleep 50
startingGate.Set() |> ignore

// Wait for all 3 threads to finish. (The order doesn't matter.)
for t in threads do
t.Join()

printfn "\nThreads are complete. Running GC.Collect() to reclaim extra instances."

GC.Collect()

// Allow time for garbage collection, which happens asynchronously.
Thread.Sleep 100

printfn "\nNote that only one instance of LargeObject was used."
printfn "Press Enter to end the program"
stdin.ReadLine() |> ignore

// This example produces output similar to the following:
// Constructor: Instance initializing on thread 5
// Constructor: Instance initializing on thread 4
// ApplicationException: Lazy initialization function failed on thread 3.
// LargeObject was initialized by thread 5 last used by thread 5.
// LargeObject was initialized by thread 5 last used by thread 4.
//
// Threads are complete. Running GC.Collect() to reclaim extra instances.
// Finalizer: Instance was initialized on 4
//
// Note that only one instance of LargeObject was used.
// Press Enter to end the program
//
// Finalizer: Instance was initialized on 5
//</SnippetAll>
Loading