Skip to content

Instantly share code, notes, and snippets.

@Thorium
Created May 3, 2016 12:04
Show Gist options
  • Save Thorium/76eb4b59d41c688a5da5de69c681c3ee to your computer and use it in GitHub Desktop.
Save Thorium/76eb4b59d41c688a5da5de69c681c3ee to your computer and use it in GitHub Desktop.
This is variant of https://gist.github.com/Thorium/df46659348b0e2146cf6 that is having a time-out. You may want to use this if you e.g. cache a database query result or other mutable data source.
open System
open System.Collections.Concurrent
let cache = ConcurrentDictionary<(string * obj),Lazy<obj>>()
let cacheTimes = ConcurrentDictionary<string,DateTime>()
let cacheTimeSeconds = 30.
let memoizeConcurrent (caller:string) (f: ('a -> 'b)) = fun x ->
match cacheTimes.TryGetValue caller with
| true, time when time < DateTime.UtcNow.AddSeconds(-cacheTimeSeconds)
-> cache.TryRemove((caller, x|>box)) |> ignore
| _ -> ()
(cache.GetOrAdd((caller, x|>box),
lazy (( cacheTimes.AddOrUpdate(caller, DateTime.UtcNow, fun _ _ ->DateTime.UtcNow) |> ignore
f x)|>box)).Force() |> unbox) : 'b
//Example test:
(* Example test:
let myfun = memoizeConcurrent "myTest" (fun f -> Console.WriteLine("SideEffect"); f + 1)
myfun 3
myfun 5
myfun 3
System.Threading.Thread.Sleep ((cacheTimeSeconds |> int) * 1000 + 100)
myfun 3
myfun 3
*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment