1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586(******************************************************************************)(* Copyright (c) 2014-2016 Skylable Ltd. <info-copyright@skylable.com> *)(* *)(* Permission to use, copy, modify, and/or distribute this software for any *)(* purpose with or without fee is hereby granted, provided that the above *)(* copyright notice and this permission notice appear in all copies. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES *)(* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF *)(* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR *)(* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES *)(* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN *)(* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *)(* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *)(******************************************************************************)moduletypeMonad=sigtype+'attype('a,'b)result=Okof'a|Errorof'bvalreturn:'a->'atvalfail:exn->'atval(>>?):'at->(('a,exn)result->'bt)->'btendmoduletypeS=sigtypekeytype'adeferredtype'attype'avalidator=(key*'aoption)->'adeferredvalcreate:int->'atvalwith_cache:'at->(key->'adeferred)->key->'adeferredvalwith_validator:'at->'avalidator->key->'adeferredvalget:'at->key->'aoptiondeferredvalset:'at->key->'a->unitendmoduleMake(K:Map.OrderedType)(M:Monad)=structmoduleAnycache_LRUMap=Anycache_LRU.Make(K)type'at='aM.tAnycache_LRUMap.cachetypekey=K.ttype'adeferred='aM.ttype'avalidator=(K.t*'aoption)->'aM.tletcreate=Anycache_LRUMap.createopen!Mletfindcachekey~f=matchAnycache_LRUMap.findcachekeywith|None->f(key,None)|Someold->old>>?function|Okdata->f(key,Somedata)|Error_->f(key,None)letret(_,v)=M.returnvletgetcachekey=findcachekey~f:retletsetcachekeyvalue=Anycache_LRUMap.replacecachekey(M.returnvalue)letwith_validatorcache(revalidate:'avalidator)key:'aM.t=letpending=findcachekey~f:revalidatein(* ensure ordering: first add the deferred, then inspect result *)Anycache_LRUMap.replacecachekeypending;pending>>?function|Okr->M.returnr|Errore->M.faileletwith_cachecachefquery=with_validatorcache(function|key,None->fkey|_key,Somedata->M.returndata)queryendmoduleDirect=structtype('a,'b)result=('a,'b)Result.result=Okof'a|Errorof'btype'at=('a,exn)resultletreturnx=Okxletfaile=Errorelet(>>?)vf=fvendincludeMake(String)(Direct)