Έχουν δημοσιευτεί
Κυριακή, 11 Ιουλίου 2010 7:49 μμ
από το μέλος
PALLADIN
Μελετώντας την
Clojure, την προσοχή μου τράβηξε ένα απλό αλλά πολύ χρήσιμο construct, το
Atom.
Το Atom φαίνεται να είναι το πάντρεμα των ref cells της ML με lock free
CAS concurrency semantics.
Επειδή τέτοια constructs είναι πολύ χρήσιμα στην F#, σκέφτηκα να υλοποιήσω κάτι ανάλογο.
My attempt:
type Atom<'a when 'a : not struct>(value : 'a) =
let refCell = ref value
let rec swap f =
let currentValue = !refCell
let result = Interlocked.CompareExchange<'a>(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 : 'a -> 'a) = swap f
let atom value =
new Atom<_>(value)
let (!) (atom : Atom<_>) =
atom.Value
let swap (atom : Atom<_>) (f : _ -> _) =
atom.Swap f
Και ως παράδειγμα χρήσης, σκέφτηκα έναν απλό multithreaded counter.
(Σημείωση: βάζω το int μέσα στο lambda επειδή πρέπει να δώσω στο Atom ένα reference type)
let counter = atom (fun () -> 0)
let listOfIncrementAsync = [ for _ in [1..1000000] -> async { swap counter (fun f -> (fun result () -> result + 1) <| f()) } ]
listOfIncrementAsync |> Async.Parallel |> Async.Run |> ignore
printfn "%d" ((!counter)()) //1000000