Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file CCCache.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326(* This file is free software, part of containers. See file "license" for more details. *)(** {1 Caches} *)type'aequal='a->'a->booltype'ahash='a->intletdefault_hash_=Hashtbl.hash(** {2 Value interface} *)type('a,'b)t={set:'a->'b->unit;get:'a->'b;(* or raise Not_found *)size:unit->int;iter:('a->'b->unit)->unit;clear:unit->unit;}(** Invariants:
- after [cache.set x y], [get cache x] must return [y] or raise [Not_found]
- [cache.set x y] is only called if [get cache x] fails, never if [x] is already bound
- [cache.size()] must be positive and correspond to the number of items in [cache.iter]
- [cache.iter f] calls [f x y] with every [x] such that [cache.get x = y]
- after [cache.clear()], [cache.get x] fails for every [x]
*)type('a,'b)callback=in_cache:bool->'a->'b->unitletclearc=c.clear()letaddcxy=try(* check that x is not bound (see invariants) *)let_=c.getxinfalsewithNot_found->c.setxy;trueletdefault_callback_~in_cache:___=()letwith_cache?(cb=default_callback_)cfx=trylety=c.getxincb~in_cache:truexy;ywithNot_found->lety=fxinc.setxy;cb~in_cache:falsexy;yletwith_cache_rec?(cb=default_callback_)cf=letrecf'x=with_cache~cbc(ff')xinf'letsizec=c.size()letitercf=c.iterfletdummy={set=(fun__->());get=(fun_->raiseNot_found);clear=(fun_->());size=(fun_->0);iter=(fun_->());}moduleLinear=structtype('a,'b)bucket=Empty|Pairof'a*'btype('a,'b)t={eq:'aequal;arr:('a,'b)bucketarray;mutablei:int;(* index for next assertion, cycles through *)}letmakeeqsize=assert(size>0);{arr=Array.makesizeEmpty;eq;i=0}letclearc=Array.fillc.arr0(Array.lengthc.arr)Empty;c.i<-0(* linear lookup *)letrecsearch_cix=ifi=Array.lengthc.arrthenraiseNot_found;matchc.arr.(i)with|Pair(x',y)whenc.eqxx'->y|Pair_|Empty->search_c(i+1)xletgetcx=search_c0xletsetcxy=c.arr.(c.i)<-Pair(x,y);c.i<-(c.i+1)modArray.lengthc.arrletitercf=Array.iter(function|Pair(x,y)->fxy|Empty->())c.arrletsizec()=letr=ref0initerc(fun__->incrr);!rendletlinear~eqsize=letsize=maxsize1inletarr=Linear.makeeqsizein{get=(funx->Linear.getarrx);set=(funxy->Linear.setarrxy);clear=(fun()->Linear.cleararr);size=Linear.sizearr;iter=Linear.iterarr;}moduleReplacing=structtype('a,'b)bucket=Empty|Pairof'a*'btype('a,'b)t={eq:'aequal;hash:'ahash;arr:('a,'b)bucketarray;mutablec_size:int;}letmakeeqhashsize=assert(size>0);{arr=Array.makesizeEmpty;eq;hash;c_size=0}letclearc=c.c_size<-0;Array.fillc.arr0(Array.lengthc.arr)Emptyletgetcx=leti=c.hashxmodArray.lengthc.arrinmatchc.arr.(i)with|Pair(x',y)whenc.eqxx'->y|Pair_|Empty->raiseNot_foundletis_empty=function|Empty->true|Pair_->falseletsetcxy=leti=c.hashxmodArray.lengthc.arrinifis_emptyc.arr.(i)thenc.c_size<-c.c_size+1;c.arr.(i)<-Pair(x,y)letitercf=Array.iter(function|Empty->()|Pair(x,y)->fxy)c.arrletsizec()=c.c_sizeendletreplacing~eq?(hash=default_hash_)size=letc=Replacing.makeeqhashsizein{get=(funx->Replacing.getcx);set=(funxy->Replacing.setcxy);clear=(fun()->Replacing.clearc);size=Replacing.sizec;iter=Replacing.iterc;}moduletypeHASH=sigtypetvalequal:tequalvalhash:thashendmoduleLRU(X:HASH)=structtypekey=X.tmoduleH=Hashtbl.Make(X)type'at={table:'anodeH.t;(* hashtable key -> node *)mutablefirst:'anodeoption;size:int;(* max size *)}and'anode={mutablekey:key;mutablevalue:'a;mutablenext:'anode;mutableprev:'anode;}(** Meta data for the value, making a chained list *)letmakesize=assert(size>0);{table=H.createsize;size;first=None}letclearc=H.clearc.table;c.first<-None;()(* take first from queue *)lettake_c=matchc.firstwith|SomenwhenStdlib.(==)n.nextn->(* last element *)c.first<-None;n|Somen->c.first<-Somen.next;n.prev.next<-n.next;n.next.prev<-n.prev;n|None->failwith"LRU: empty queue"(* push at back of queue *)letpush_cn=matchc.firstwith|None->n.next<-n;n.prev<-n;c.first<-Somen|Somen1whenStdlib.(==)n1n->()|Somen1->n.prev<-n1.prev;n.next<-n1;n1.prev.next<-n;n1.prev<-n(* remove from queue *)letremove_n=n.prev.next<-n.next;n.next.prev<-n.prev(* Replace least recently used element of [c] by x->y *)letreplace_cxy=(* remove old *)letn=take_cinH.removec.tablen.key;(* add x->y, at the back of the queue *)n.key<-x;n.value<-y;H.addc.tablexn;push_cn;()(* Insert x->y in the cache, increasing its entry count *)letinsert_cxy=letrecn={key=x;value=y;next=n;prev=n}inH.addc.tablexn;push_cn;()letgetcx=letn=H.findc.tablexin(* put n at the back of the queue *)remove_n;push_cn;n.valueletsetcxy=letlen=H.lengthc.tableinassert(len<=c.size);iflen=c.sizethenreplace_cxyelseinsert_cxyletsizec()=H.lengthc.tableletitercf=H.iter(funxnode->fxnode.value)c.tableendletlru(typea)~eq?(hash=default_hash_)size=letmoduleL=LRU(structtypet=aletequal=eqlethash=hashend)inletc=L.makesizein{get=(funx->L.getcx);set=(funxy->L.setcxy);clear=(fun()->L.clearc);size=L.sizec;iter=L.iterc;}moduleUNBOUNDED(X:HASH)=structmoduleH=Hashtbl.Make(X)letmakesize=assert(size>0);H.createsizeletclearc=H.clearcletgetcx=H.findcxletsetcxy=H.replacecxyletsizec()=H.lengthcletitercf=H.iterfcendletunbounded(typea)~eq?(hash=default_hash_)size=letmoduleC=UNBOUNDED(structtypet=aletequal=eqlethash=hashend)inletc=C.makesizein{get=(funx->C.getcx);set=(funxy->C.setcxy);clear=(fun()->C.clearc);iter=C.iterc;size=C.sizec;}