Skip to content

Instantly share code, notes, and snippets.

@palladin
Created July 15, 2011 16:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save palladin/1085027 to your computer and use it in GitHub Desktop.
Save palladin/1085027 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