#r @"../bin/FSharpx.Extras.dll"
open System
open System.Threading
open FSharpx.Stm
let check p =
match p with
| true -> stm.Return(())
| false -> retry ()
let forkIO (f : unit -> unit) =
let t = new Thread(f)
t.Start()
t
//----------------
//forever :: IO () -> IO ()
// Repeatedly perform the action
let rec forever act : unit = act (); forever act
//randomDelay :: IO ()
// Delay for a random time between 1 and 1000,000 microseconds
let rng = new Random()
let randomDelay () =
let waitTime = rng.Next(1000)
Thread.Sleep(waitTime)
//choose :: [(STM a, a -> IO ())] -> IO ()
let choose choices : unit =
//stmActions :: [STM (IO ())]
let stmActions = [ for (guard, rhs) in choices -> stm { let! v = guard in return (rhs v) } ]
stmActions |> List.reduceBack orElse |> atomically
//---------------
type Gate = MkGate of int * TVar<int>
//newGate :: Int -> STM Gate
let newGate n =
stm { let tv = newTVar 0 in return MkGate (n, tv) }
//passGate :: Gate -> IO ()
let passGate (MkGate (n,tv)) =
stm { let! n_left = readTVar tv
do! check (n_left > 0)
do! writeTVar tv (n_left-1)
return () } |> atomically
//operateGate :: Gate -> IO ()
let operateGate (MkGate (n,tv)) =
stm { return! writeTVar tv n } |> atomically
stm { let! n_left = readTVar tv
return! check (n_left = 0) } |> atomically
//---------------
type Group = MkGroup of int * TVar<int * Gate * Gate>
//newGroup :: Int -> IO Group
let newGroup n =
stm { let! g1 = newGate n
let! g2 = newGate n
let tv = newTVar (n, g1, g2)
return MkGroup (n, tv) } |> atomically
//joinGroup :: Group -> IO (Gate,Gate)
let joinGroup (MkGroup (n,tv)) =
stm { let! n_left, g1, g2 = readTVar tv
do! check (n_left > 0)
do! writeTVar tv (n_left-1, g1, g2)
return (g1,g2) } |> atomically
//awaitGroup :: Group -> STM (Gate,Gate)
let awaitGroup (MkGroup (n,tv)) =
stm { let! n_left, g1, g2 = readTVar tv
do! check (n_left = 0)
let! new_g1 = newGate n
let! new_g2 = newGate n
do! writeTVar tv (n,new_g1,new_g2)
return (g1,g2) }
//---------------
let rec main () =
let elf_gp = newGroup 3
List.iter (fun n -> elf elf_gp n |> ignore) [1..10]
let rein_gp = newGroup 9
List.iter (fun n -> reindeer rein_gp n |> ignore) [1..9]
forever (fun () -> santa elf_gp rein_gp)
and elf gp id = forkIO (fun () -> forever (fun () -> elf1 gp id; randomDelay ()))
and reindeer gp id = forkIO (fun () -> forever (fun () -> reindeer1 gp id; randomDelay ()))
//santa :: Group -> Group -> IO ()
and santa elf_group rein_group =
Console.WriteLine("----------")
choose [awaitGroup rein_group, run "deliver toys";
awaitGroup elf_group, run "meet in my study"]
//run :: String -> (Gate,Gate) -> IO ()
and run task (in_gate,out_gate) =
Console.WriteLine("Ho! Ho! Ho! let's {0}", task)
operateGate in_gate
operateGate out_gate
//helper1 :: Group -> IO () -> IO ()
and helper1 group do_task =
let in_gate, out_gate = joinGroup group
passGate in_gate
do_task ()
passGate out_gate
//elf1, reindeer1 :: Group -> Int -> IO ()
and elf1 group id = helper1 group (fun () -> meetInStudy id)
and reindeer1 group id = helper1 group (fun () -> deliverToys id)
and meetInStudy id = Console.WriteLine("Elf {0} meeting in the study", id)
and deliverToys id = Console.WriteLine("Reindeer {0} delivering toys", id)
#if INTERACTIVE
main()
#else
[<EntryPoint>]
let entryPoint args = main(); 0
#endif
namespace System
namespace System.Threading
val check: p: bool -> 'a
val p: bool
val forkIO: f: (unit -> unit) -> Thread
val f: (unit -> unit)
type unit = Unit
val t: Thread
Multiple items
type Thread =
inherit CriticalFinalizerObject
new: start: ParameterizedThreadStart -> unit + 3 overloads
member Abort: unit -> unit + 1 overload
member DisableComObjectEagerCleanup: unit -> unit
member GetApartmentState: unit -> ApartmentState
member GetCompressedStack: unit -> CompressedStack
member GetHashCode: unit -> int
member Interrupt: unit -> unit
member Join: unit -> unit + 2 overloads
member Resume: unit -> unit
...
<summary>Creates and controls a thread, sets its priority, and gets its status.</summary>
--------------------
Thread(start: ParameterizedThreadStart) : Thread
Thread(start: ThreadStart) : Thread
Thread(start: ParameterizedThreadStart, maxStackSize: int) : Thread
Thread(start: ThreadStart, maxStackSize: int) : Thread
Thread.Start() : unit
Thread.Start(parameter: obj) : unit
val forever: act: (unit -> unit) -> unit
val act: (unit -> unit)
val rng: Random
Multiple items
type Random =
new: unit -> unit + 1 overload
member Next: unit -> int + 2 overloads
member NextBytes: buffer: byte array -> unit + 1 overload
member NextDouble: unit -> float
member NextInt64: unit -> int64 + 2 overloads
member NextSingle: unit -> float32
static member Shared: Random
<summary>Represents a pseudo-random number generator, which is an algorithm that produces a sequence of numbers that meet certain statistical requirements for randomness.</summary>
--------------------
Random() : Random
Random(Seed: int) : Random
val randomDelay: unit -> unit
val waitTime: int
Random.Next() : int
Random.Next(maxValue: int) : int
Random.Next(minValue: int, maxValue: int) : int
Thread.Sleep(timeout: TimeSpan) : unit
Thread.Sleep(millisecondsTimeout: int) : unit
val choose: choices: ('a * 'b) seq -> unit
val choices: ('a * 'b) seq
val stmActions: obj list
val guard: 'a
val rhs: 'b
Multiple items
module List
from Microsoft.FSharp.Collections
--------------------
type List<'T> =
| op_Nil
| op_ColonColon of Head: 'T * Tail: 'T list
interface IReadOnlyList<'T>
interface IReadOnlyCollection<'T>
interface IEnumerable
interface IEnumerable<'T>
member GetReverseIndex: rank: int * offset: int -> int
member GetSlice: startIndex: int option * endIndex: int option -> 'T list
static member Cons: head: 'T * tail: 'T list -> 'T list
member Head: 'T
member IsEmpty: bool
member Item: index: int -> 'T with get
...
val reduceBack: reduction: ('T -> 'T -> 'T) -> list: 'T list -> 'T
type Gate = | MkGate of int * obj
union case Gate.MkGate: int * obj -> Gate
Multiple items
val int: value: 'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> =
int
val newGate: n: 'a -> 'b
val n: 'a
val passGate: Gate -> 'a
val n: int
val tv: obj
val operateGate: Gate -> 'a
type Group = | MkGroup of int * obj
union case Group.MkGroup: int * obj -> Group
val newGroup: n: 'a -> 'b
val joinGroup: Group -> 'a
val awaitGroup: Group -> 'a
val main: unit -> unit
val elf_gp: Group
val iter: action: ('T -> unit) -> list: 'T list -> unit
val elf: gp: Group -> id: int -> Thread
val ignore: value: 'T -> unit
val rein_gp: Group
val reindeer: gp: Group -> id: int -> Thread
val santa: elf_group: Group -> rein_group: Group -> unit
val gp: Group
val id: int
val elf1: group: Group -> id: int -> unit
val reindeer1: group: Group -> id: int -> unit
val elf_group: Group
val rein_group: Group
type Console =
static member Beep: unit -> unit + 1 overload
static member Clear: unit -> unit
static member GetCursorPosition: unit -> struct (int * int)
static member MoveBufferArea: sourceLeft: int * sourceTop: int * sourceWidth: int * sourceHeight: int * targetLeft: int * targetTop: int -> unit + 1 overload
static member OpenStandardError: unit -> Stream + 1 overload
static member OpenStandardInput: unit -> Stream + 1 overload
static member OpenStandardOutput: unit -> Stream + 1 overload
static member Read: unit -> int
static member ReadKey: unit -> ConsoleKeyInfo + 1 overload
static member ReadLine: unit -> string
...
<summary>Represents the standard input, output, and error streams for console applications. This class cannot be inherited.</summary>
Console.WriteLine() : unit
(+0 other overloads)
Console.WriteLine(value: uint64) : unit
(+0 other overloads)
Console.WriteLine(value: uint32) : unit
(+0 other overloads)
Console.WriteLine(value: string) : unit
(+0 other overloads)
Console.WriteLine(value: float32) : unit
(+0 other overloads)
Console.WriteLine(value: obj) : unit
(+0 other overloads)
Console.WriteLine(value: int64) : unit
(+0 other overloads)
Console.WriteLine(value: int) : unit
(+0 other overloads)
Console.WriteLine(value: float) : unit
(+0 other overloads)
Console.WriteLine(value: decimal) : unit
(+0 other overloads)
val run: task: string -> in_gate: Gate * out_gate: Gate -> 'a
val task: string
val in_gate: Gate
val out_gate: Gate
val helper1: group: Group -> do_task: (unit -> unit) -> 'b
val group: Group
val do_task: (unit -> unit)
val meetInStudy: id: int -> unit
val deliverToys: id: int -> unit
Multiple items
type EntryPointAttribute =
inherit Attribute
new: unit -> EntryPointAttribute
--------------------
new: unit -> EntryPointAttribute