Skip to content

Instantly share code, notes, and snippets.

@mastoj
Last active December 18, 2015 12:11
Show Gist options
  • Save mastoj/524d9a727587a6dd323b to your computer and use it in GitHub Desktop.
Save mastoj/524d9a727587a6dd323b to your computer and use it in GitHub Desktop.
module CachingAgent
open System
type AgentCacheMessage<'T> = AsyncReplyChannel<'T>
type Agent<'T> = MailboxProcessor<'T>
let CreateCache<'T> timespan (funcGen:Func<'T>) = Agent.Start(fun inbox ->
let rec loop expire (cached:Lazy<'T>) = async {
let! (message:AgentCacheMessage<'T>) = inbox.Receive()
let renew = expire <= DateTime.Now
let cached' = if renew then lazy (funcGen.Invoke()) else cached
let expire' = if renew then DateTime.Now + timespan else expire
message.Reply(cached'.Force())
return! loop expire' cached'
}
loop (DateTime.Now + timespan) (lazy (funcGen.Invoke()))
)
let GetValue<'T> (agent:Agent<AgentCacheMessage<'T>>) = agent.PostAndAsyncReply(fun rp -> rp) |> Async.StartAsTask
class Program
{
static void Main(string[] args)
{
var taskFactory = new TaskFactory();
var x = 0;
Func<int> generator = () =>
{
Thread.Sleep(2000);
Console.WriteLine("Generating value");
return x++;
};
var cache = CachingAgent.CreateCache(TimeSpan.FromSeconds(5), generator);
for (int i = 0; i < 20; i++)
{
var result = CachingAgent.GetValue(cache).Result;
Console.WriteLine(result);
Thread.Sleep(1000);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment