I started using Hopac as an alternative to Async / TPL, and I like it. I understand the main use, but some aspects are still not clear.
First of all, could we compare it Altwith F # lazyso that the work inside is Altevaluated only on Alt.pick?
Secondly, is this AutoResetEvent implementation correct and idiomatic for Hopac?
type HopacAutoResetEvent (initialState : bool) =
let setChannel : Ch<unit> = ch()
do if initialState then start <| Ch.send setChannel ()
new() = HopacAutoResetEvent(false)
member this.Wait(timeout:int) : Job<bool> =
let timedOut : Alt<bool> =
((float timeout) |> TimeSpan.FromMilliseconds |> Timer.Global.timeOut)
>>=? fun () -> Job.result false
let signaled = Ch.Alt.take setChannel >>=? fun () -> Job.result true
signaled <|> timedOut
member this.Set() : Job<unit> =
(Ch.Try.take setChannel) >>. Ch.send setChannel ()
Third, is this ManualResetEvent implementation correct and idiomatic for Hopac?
type HopacManualResetEvent (initialState : bool) =
[<VolatileFieldAttribute>]
let mutable state : bool = initialState
let setChannel : MChan<bool> = run <| Multicast.create ()
let lock = Lock.Now.create()
new() = HopacManualResetEvent(false)
member this.Wait() : Job<bool> =
let rec loop () =
job {
if state then return true
else
let! port = Multicast.port setChannel
let! res = (Multicast.recv port)
if res then return true
else return! loop ()
}
loop ()
member this.Set() : Job<unit> =
(Multicast.multicast setChannel true)
|>> (fun _ -> state <- true )
>>% ()
|> (Lock.duringJob lock)
member this.Reset() : Job<unit> =
(Multicast.multicast setChannel false)
|>> (fun _ -> state <- false )
>>% ()
|> (Lock.duringJob lock)
Cross mail: https://github.com/VesaKarvonen/Hopac/issues/26
source
share