FSharpx.Extras


#r @"../bin/FSharpx.Extras.dll"

open System
open System.Threading
open FSharpx.Stm

let test l1 l2 num_threads =
    let q1 = ListQueue.ofList l1
    let q2 = ListQueue.ofList l2
    let move_item q1 q2 =
        stm { let! x = ListQueue.dequeue q1
              do! ListQueue.enqueue q2 x 
              return x }
    let stop = newTVar false
    let rnd = new Random()
    let rec worker q1 q2 (fmt : string) =
        let x = 
            stm { let! stop' = readTVar stop
                  return! if not stop' 
                            then liftM Some (move_item q1 q2)
                            else stm.Return(None) } |> atomically
        match x with
        | Some x -> Console.WriteLine(fmt, Thread.CurrentThread.ManagedThreadId, x)
                    Thread.Sleep(rnd.Next(1000))
                    worker q1 q2 fmt
        | None -> ()
    let left_worker () = worker q1 q2 "Thread {0} moved item {1} left."
    let right_worker () = worker q2 q1 "Thread {0} moved item {1} right."
    let spawn (f : unit -> unit) = let t = new Thread(f) in t.Start(); t
    let threads = [ for _ in [1..num_threads] -> [spawn left_worker; spawn right_worker] ]
    let terminate () = 
        writeTVar stop true |> atomically
        threads |> Seq.concat |> Seq.iter (fun t -> t.Join()) 
        Console.WriteLine("Terminated.")
        stm { let! l1 = ListQueue.toList q1
              let! l2 = ListQueue.toList q2
              return l1,l2 } |> atomically
    terminate
    
let runTest () = 
    Console.WriteLine("Started.")
    let t = test [1..50] [51..100] 10 
    Thread.Sleep(3000)
    t () |> ignore
     
namespace System
namespace System.Threading
val test: l1: 'a -> l2: 'b -> num_threads: int -> (unit -> 'c)
val l1: 'a
val l2: 'b
val num_threads: int
val q1: obj
val q2: obj
val move_item: q1: 'd -> q2: 'e -> 'f
val q1: 'd
val q2: 'e
val stop: obj
val rnd: 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 worker: q1: 'd -> q2: 'e -> fmt: string -> unit
val fmt: string
Multiple items
val string: value: 'T -> string

--------------------
type string = String
val x: obj option
union case Option.Some: Value: 'T -> Option<'T>
union case Option.None: Option<'T>
val x: obj
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)
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
property Thread.CurrentThread: Thread with get
<summary>Gets the currently running thread.</summary>
<returns>A <see cref="T:System.Threading.Thread" /> that is the representation of the currently running thread.</returns>
property Thread.ManagedThreadId: int with get
<summary>Gets a unique identifier for the current managed thread.</summary>
<returns>An integer that represents a unique identifier for this managed thread.</returns>
Thread.Sleep(timeout: TimeSpan) : unit
Thread.Sleep(millisecondsTimeout: int) : unit
Random.Next() : int
Random.Next(maxValue: int) : int
Random.Next(minValue: int, maxValue: int) : int
val left_worker: unit -> unit
val right_worker: unit -> unit
val spawn: f: (unit -> unit) -> Thread
val f: (unit -> unit)
type unit = Unit
val t: Thread
Thread.Start() : unit
Thread.Start(parameter: obj) : unit
val threads: Thread list list
val terminate: unit -> 'd
module Seq from Microsoft.FSharp.Collections
val concat: sources: #('T seq) seq -> 'T seq
val iter: action: ('T -> unit) -> source: 'T seq -> unit
Thread.Join() : unit
Thread.Join(timeout: TimeSpan) : bool
Thread.Join(millisecondsTimeout: int) : bool
val runTest: unit -> unit
val t: (unit -> obj)
val ignore: value: 'T -> unit