#light

open System
open System.Diagnostics
open System.Threading

type Node(next, m, eventwait : AutoResetEvent) =
    let mailbox =
        MailboxProcessor.Start(fun inbox ->
            let rec loop l =
                async {
                    let! (nodes : Node[]) = inbox.Receive()
                    nodes.[next].Post(nodes)
                    if l < m then
                        return! loop (l + 1)
                    else
                        eventwait.Set() |> ignore
                        return ()
                }
            loop 0
        )
    member this.Post(msg) = mailbox.Post(msg)

let benchmark n m =
    let eventwait = new AutoResetEvent(false)
    let nodes = [|for i in 1..n -> new Node(i % n, m, eventwait)|]
    let stopwatch = Stopwatch.StartNew()
    nodes.[0].Post(nodes)
    eventwait.WaitOne() |> ignore
    stopwatch.Stop()
    stopwatch.ElapsedMilliseconds