#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) = (new Thread(f)).Start()
let rec forever act : unit = act (); forever act
let take fork =
stm {
let! ref_fork = readTVar (fork)
do! check ref_fork
do! writeTVar (fork) false
}
let adquire left_fork right_fork =
stm {
do! take left_fork
do! take right_fork
} |> atomically
let release left_fork right_fork =
stm {
do! writeTVar left_fork true
do! writeTVar right_fork true
} |> atomically
let rng = new Random()
let n = 7 ;
let thinking = Array.zeroCreate n
let eating = Array.zeroCreate n
let randomDelay () =
let waitTime = rng.Next(1000)
Thread.Sleep waitTime
uint64 waitTime
let eatOrThink i left_fork right_fork =
if (rng.Next(100)) > 50
then
adquire left_fork right_fork
printf "philosopher [%d] is eating.\n" i
eating.[i] <- eating.[i] + randomDelay ()
release left_fork right_fork
else
printf "philosopher [%d] is thinking.\n" i
thinking.[i] <- thinking.[i] + randomDelay ()
let philosofer i leftfork rightfork =
fun () -> forever (fun () -> eatOrThink i leftfork rightfork)
let timer = new System.Diagnostics.Stopwatch()
timer.Start()
let rec main () =
let forks = Array.init n (fun _ -> newTVar(true))
for i in 0..n-1 do
forkIO (philosofer i forks.[i] forks.[(i + 1) % n])
let onInterrupt _ _ =
timer.Stop()
printf "\ndone.\n"
let total = float timer.ElapsedMilliseconds
let p x = ((float x) * 100.0) / (float total)
for i in 0..n-1 do
printf "philosopher [%d] - percents: %.2f eating, %.2f thinking, %.2f obtaining forks\n"
i (p eating.[i]) (p thinking.[i]) (100. - (p eating.[i] + p thinking.[i]))
Console.CancelKeyPress.AddHandler( new ConsoleCancelEventHandler( onInterrupt ))
main()
namespace System
namespace System.Threading
val check: p: bool -> 'a
val p: bool
val forkIO: f: (unit -> unit) -> unit
val f: (unit -> unit)
type unit = Unit
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
val forever: act: (unit -> unit) -> unit
val act: (unit -> unit)
val take: fork: 'a -> 'b
val fork: 'a
val adquire: left_fork: 'a -> right_fork: 'b -> 'c
val left_fork: 'a
val right_fork: 'b
val release: left_fork: 'a -> right_fork: 'b -> 'c
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 n: int
val thinking: uint64 array
type Array =
interface ICollection
interface IEnumerable
interface IList
interface IStructuralComparable
interface IStructuralEquatable
interface ICloneable
member Clone: unit -> obj
member CopyTo: array: Array * index: int -> unit + 1 overload
member GetEnumerator: unit -> IEnumerator
member GetLength: dimension: int -> int
...
<summary>Provides methods for creating, manipulating, searching, and sorting arrays, thereby serving as the base class for all arrays in the common language runtime.</summary>
val zeroCreate: count: int -> 'T array
val eating: uint64 array
val randomDelay: unit -> uint64
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
Multiple items
val uint64: value: 'T -> uint64 (requires member op_Explicit)
--------------------
type uint64 = UInt64
--------------------
type uint64<'Measure> =
uint64
val eatOrThink: i: int -> left_fork: 'a -> right_fork: 'b -> unit
val i: int
val printf: format: Printf.TextWriterFormat<'T> -> 'T
val philosofer: i: int -> leftfork: 'a -> rightfork: 'b -> unit -> unit
val leftfork: 'a
val rightfork: 'b
val timer: Diagnostics.Stopwatch
namespace System.Diagnostics
Multiple items
type Stopwatch =
new: unit -> unit
member Reset: unit -> unit
member Restart: unit -> unit
member Start: unit -> unit
member Stop: unit -> unit
static member GetTimestamp: unit -> int64
static member StartNew: unit -> Stopwatch
static val Frequency: int64
static val IsHighResolution: bool
member Elapsed: TimeSpan
...
<summary>Provides a set of methods and properties that you can use to accurately measure elapsed time.</summary>
--------------------
Diagnostics.Stopwatch() : Diagnostics.Stopwatch
Diagnostics.Stopwatch.Start() : unit
val main: unit -> unit
val forks: obj array
val init: count: int -> initializer: (int -> 'T) -> 'T array
val i: int32
val onInterrupt: 'a -> 'b -> unit
Diagnostics.Stopwatch.Stop() : unit
val total: float
Multiple items
val float: value: 'T -> float (requires member op_Explicit)
--------------------
type float = Double
--------------------
type float<'Measure> =
float
property Diagnostics.Stopwatch.ElapsedMilliseconds: int64 with get
<summary>Gets the total elapsed time measured by the current instance, in milliseconds.</summary>
<returns>A read-only long integer representing the total number of milliseconds measured by the current instance.</returns>
val p: x: uint64 -> float
val x: uint64
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>
event Console.CancelKeyPress: IEvent<ConsoleCancelEventHandler,ConsoleCancelEventArgs>
abstract IDelegateEvent.AddHandler: handler: 'Delegate -> unit
type ConsoleCancelEventHandler =
new: object: obj * method: nativeint -> unit
member BeginInvoke: sender: obj * e: ConsoleCancelEventArgs * callback: AsyncCallback * object: obj -> IAsyncResult
member EndInvoke: result: IAsyncResult -> unit
member Invoke: sender: obj * e: ConsoleCancelEventArgs -> unit
<summary>Represents the method that will handle the <see cref="E:System.Console.CancelKeyPress" /> event of a <see cref="T:System.Console" />.</summary>
<param name="sender">The source of the event.</param>
<param name="e">A <see cref="T:System.ConsoleCancelEventArgs" /> object that contains the event data.</param>