Nie jestem pewien, czy mam to prawo, czy jest lepszy sposób lub istniejąca biblioteka rozwiązująca ten problem.Czas na żywo notowania w F #
W szczególności nie jestem pewien, czy CAS będzie potrzebował ogrodzenia pamięci ... Myślę, że nie, ale lepiej zapytaj.
Próbowałem również z agentem i zmiennym słownikiem, ale moja intuicja, że byłaby wolniejsza, została potwierdzona, a implementacja bardziej zaangażowana.
module CAS =
open System.Threading
let create (value: 'T) =
let cell = ref value
let get() = !cell
let rec swap f =
let before = get()
let newValue = f before
match Interlocked.CompareExchange<'T>(cell, newValue, before) with
| result when obj.ReferenceEquals(before, result) ->
newValue
| _ ->
swap f
get, swap
module Memoization =
let timeToLive milis f =
let get, swap = CAS.create Map.empty
let evict key =
async {
do! Async.Sleep milis
swap (Map.remove key) |> ignore
} |> Async.Start
fun key ->
let data = get()
match data.TryFind key with
| Some v -> v
| None ->
let v = f key
swap (Map.add key v) |> ignore
evict key
v
Testowałeś to? Czy to działa? – Daniel
Wydaje się działać naprawdę dobrze. –
Wydaje mi się, że to w porządku. Nie sądzę, żebyś potrzebował bariery pamięci z 'PorównajExchange'. Nitpick: powinno być 'millis'. Możesz porównać perf 'ConcurrentDictionary'. – Daniel