jeffp:Aren't there concurrency constructs which remove the need for an explicit use of mutable state?
F# doesn't define it's own concurrency constructs, instead it uses the concurrency constructs from the CLR, which consequently are mutable-state-oriented. Mutable state is a standard practice for sharing data between concurrent processes. You can of course implement your own more functional-esque concurrency constucts in F# if you wish, say an MVar.
type MVar<'a> =
{ contents : 'a option ref; read : AutoResetEvent; write : AutoResetEvent } with
interface IDisposable with
member mv.Dispose() = mv.read.Close(); mv.write.Close()
let newFullMVar x = { contents = ref (Some x); read = new AutoResetEvent(true); write = new AutoResetEvent(false) }
let newEmptyMVar () = { contents = ref None; read = new AutoResetEvent(false); write = new AutoResetEvent(true) }
let readMVar mv =
mv.read.WaitOne() |> ignore
let v = !mv.contents
mv.contents := None
mv.write.Set() |> ignore
Option.get v
let writeMVar mv x =
mv.write.WaitOne() |> ignore
mv.contents := Some x
mv.read.Set() |> ignore
jeffp:Is this function equivalent to the following?
Pretty much.
Here's a better version that uses CLR asynchronous method invocation.
open System
#I "C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5"
#r "System.Core.dll"
let timeout (ms : int) f x =
let df = new Func<'a,'b>(f)
let ar = df.BeginInvoke(x, null, null)
if ar.AsyncWaitHandle.WaitOne(ms, false) then Some (df.EndInvoke(ar)) else None
The exact delegate type used for df is not important -- it can be any delegate with the right signature. However there is an issue with how delegate types are compiled in F#, so you can't define your own delegate in F# and use it here. Instead you need to use a previously compiled delegate type; I have chosen System.Func, added with LINQ in v3.5.