Skip to content

Instantly share code, notes, and snippets.

@fogus
Forked from palladin/gist:1085027
Created January 4, 2012 03:11
Show Gist options
  • Save fogus/1558291 to your computer and use it in GitHub Desktop.
Save fogus/1558291 to your computer and use it in GitHub Desktop.
Clojure's Atoms
open System.Threading
type Atom<'T when 'T : not struct>(value : 'T) =
let refCell = ref value
let rec swap f =
let currentValue = !refCell
let result = Interlocked.CompareExchange<'T>(refCell, f currentValue, currentValue)
if obj.ReferenceEquals(result, currentValue) then ()
else Thread.SpinWait 20; swap f
member self.Value with get() = !refCell
member self.Swap (f : 'T -> 'T) = swap f
let atom value =
new Atom<_>(value)
let (!) (atom : Atom<_>) =
atom.Value
let swap (atom : Atom<_>) (f : _ -> _) =
atom.Swap f
// example
let counter = atom (fun () -> 0)
let listOfIncrementAsync =
[ for _ in [1..1000000] do
yield async {
swap counter (fun f -> (fun result () -> result + 1) <| f())
} ]
listOfIncrementAsync |> Async.Parallel |> Async.RunSynchronously
let value = (!counter)() // returns 1000000
printfn "%d" value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment