Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file hash_queue.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393open!ImportopenHash_queue_intfmoduletypeKey=KeymoduletypeS_backend=S_backendmoduleMake_backend(Table:Hashtbl_intf.Hashtbl):S_backend=structmoduletypeBackend=S1withtype'keycreate_arg:='keyHashtbl.Hashable.twithtype'keycreate_key:='keymoduleBackend:Backend=structmoduleKey_value=structmoduleT=structtype('key,'value)t={key:'key;mutablevalue:'value}endincludeTletkeyt=t.keyletvaluet=t.valueletsexp_of_tsexp_of_keysexp_of_data{key;value}=[%sexp_of:key*data](key,value);;endopenKey_value.TmoduleElt=Doubly_linked.Elttype('key,'data)t={mutablenum_readers:int;queue:('key,'data)Key_value.tDoubly_linked.t;table:('key,('key,'data)Key_value.tElt.t)Table.t}letsexp_of_tsexp_of_keysexp_of_datat=[%sexp_of:(key,data)Key_value.tDoubly_linked.t]t.queue;;letinvariantt=assert(Doubly_linked.lengtht.queue=Table.lengtht.table);(* Look at each element in the queue, checking:
* - every element in the queue is in the hash table
* - there are no duplicate keys
*)letkeys=Table.create~size:(Table.lengtht.table)(Table.hashable_st.table)inDoubly_linked.itert.queue~f:(funkv->letkey=kv.keyinmatchTable.findt.tablekeywith|None->assertfalse|Some_->assert(not(Table.memkeyskey));Table.setkeys~key~data:());;letcreate?(growth_allowed=true)?(size=16)hashable={num_readers=0;queue=Doubly_linked.create();table=Table.create~growth_allowed~size(Table.Hashable.to_keyhashable)};;letreadtf=t.num_readers<-t.num_readers+1;Exn.protect~f~finally:(fun()->t.num_readers<-t.num_readers-1);;letensure_can_modifyt=ift.num_readers>0thenfailwith"It is an error to modify a Hash_queue.t while iterating over it.";;letcleart=ensure_can_modifyt;Doubly_linked.cleart.queue;Table.cleart.table;;letlengtht=Table.lengtht.tableletis_emptyt=lengtht=0letlookuptk=matchTable.findt.tablekwith|None->None|Someelt->Some(Elt.valueelt).value;;letlookup_exntk=(Elt.value(Table.find_exnt.tablek)).valueletmemtk=Table.memt.tablek(* Note that this is the tail-recursive Core_list.map *)letto_listt=List.map(Doubly_linked.to_listt.queue)~f:Key_value.valueletto_arrayt=Array.map(Doubly_linked.to_arrayt.queue)~f:Key_value.valueletfor_allt~f=readt(fun()->Doubly_linked.for_allt.queue~f:(funkv->fkv.value));;letexistst~f=readt(fun()->Doubly_linked.existst.queue~f:(funkv->fkv.value));;letfind_mapt~f=readt(fun()->Doubly_linked.find_mapt.queue~f:(funkv->fkv.value));;letfindt~f=readt(fun()->Option.map(Doubly_linked.findt.queue~f:(funkv->fkv.value))~f:Key_value.value);;letenqueuetback_or_frontkeyvalue=ensure_can_modifyt;ifTable.memt.tablekeythen`Key_already_presentelse(letcontents={Key_value.key;value}inletelt=matchback_or_frontwith|`back->Doubly_linked.insert_lastt.queuecontents|`front->Doubly_linked.insert_firstt.queuecontentsinTable.sett.table~key~data:elt;`Ok);;letenqueue_backt=enqueuet`backletenqueue_frontt=enqueuet`frontletraise_enqueue_duplicate_keytkey=raise_s[%message"Hash_queue.enqueue_exn: duplicate key"~_:(Table.sexp_of_keyt.tablekey:Sexp.t)];;letenqueue_exntback_or_frontkeyvalue=matchenqueuetback_or_frontkeyvaluewith|`Key_already_present->raise_enqueue_duplicate_keytkey|`Ok->();;letenqueue_back_exnt=enqueue_exnt`backletenqueue_front_exnt=enqueue_exnt`front(* Performance hack: we implement this version separately to avoid allocation from the
option. *)letlookup_and_move_to_back_exntkey=ensure_can_modifyt;letelt=Table.find_exnt.tablekeyinDoubly_linked.move_to_backt.queueelt;Key_value.value(Elt.valueelt);;letlookup_and_move_to_backtkey=letopenOption.Let_syntaxinensure_can_modifyt;let%mapelt=Table.findt.tablekeyinDoubly_linked.move_to_backt.queueelt;Key_value.value(Elt.valueelt);;letlookup_and_move_to_front_exntkey=ensure_can_modifyt;letelt=Table.find_exnt.tablekeyinDoubly_linked.move_to_frontt.queueelt;Key_value.value(Elt.valueelt);;letlookup_and_move_to_fronttkey=letopenOption.Let_syntaxinensure_can_modifyt;let%mapelt=Table.findt.tablekeyinDoubly_linked.move_to_frontt.queueelt;Key_value.value(Elt.valueelt);;letdequeue_with_keytback_or_front=ensure_can_modifyt;letmaybe_kv=matchback_or_frontwith|`back->Doubly_linked.remove_lastt.queue|`front->Doubly_linked.remove_firstt.queueinmatchmaybe_kvwith|None->None|Somekv->Table.removet.tablekv.key;Some(kv.key,kv.value);;letraise_dequeue_with_key_empty()=raise_s[%message"Hash_queue.dequeue_with_key: empty queue"];;letdequeue_with_key_exntback_or_front=matchdequeue_with_keytback_or_frontwith|None->raise_dequeue_with_key_empty()|Some(k,v)->k,v;;letdequeue_back_with_keyt=dequeue_with_keyt`backletdequeue_back_with_key_exnt=dequeue_with_key_exnt`backletdequeue_front_with_keyt=dequeue_with_keyt`frontletdequeue_front_with_key_exnt=dequeue_with_key_exnt`frontletdequeuetback_or_front=matchdequeue_with_keytback_or_frontwith|None->None|Some(_,v)->Somev;;letdequeue_backt=dequeuet`backletdequeue_frontt=dequeuet`frontletlast_with_keyt=matchDoubly_linked.lastt.queuewith|None->None|Some{key;value}->Some(key,value);;letlastt=matchDoubly_linked.lastt.queuewith|None->None|Somekv->Somekv.value;;letfirst_with_keyt=matchDoubly_linked.firstt.queuewith|None->None|Some{key;value}->Some(key,value);;letfirstt=matchDoubly_linked.firstt.queuewith|None->None|Somekv->Somekv.value;;letraise_dequeue_empty()=raise_s[%message"Hash_queue.dequeue_exn: empty queue"]letdequeue_exntback_or_front=matchdequeuetback_or_frontwith|None->raise_dequeue_empty()|Somev->v;;letdequeue_back_exnt=dequeue_exnt`backletdequeue_front_exnt=dequeue_exnt`frontletkeyst=(* Return the keys in the order of the queue. *)List.map(Doubly_linked.to_listt.queue)~f:Key_value.key;;letiterit~f=readt(fun()->Doubly_linked.itert.queue~f:(funkv->f~key:kv.key~data:kv.value));;letitert~f=iterit~f:(fun~key:_~data->fdata)letfoldit~init~f=readt(fun()->Doubly_linked.foldt.queue~init~f:(funackv->fac~key:kv.key~data:kv.value));;letfoldt~init~f=foldit~init~f:(funac~key:_~data->facdata)letcountt~f=Container.count~foldt~fletsummt~f=Container.summ~foldt~fletmin_eltt~compare=Container.min_elt~foldt~compareletmax_eltt~compare=Container.max_elt~foldt~compareletfold_resultt~init~f=Container.fold_result~fold~init~ftletfold_untilt~init~f=Container.fold_until~fold~init~ftletdequeue_allt~f=letrecloop()=matchdequeue_fronttwith|None->()|Somev->fv;loop()inloop();;letremovetk=ensure_can_modifyt;matchTable.find_and_removet.tablekwith|None->`No_such_key|Someelt->Doubly_linked.removet.queueelt;`Ok;;letraise_remove_unknown_keytkey=raise_s[%message"Hash_queue.remove_exn: unknown key"~_:(Table.sexp_of_keyt.tablekey:Sexp.t)];;letremove_exntk=ensure_can_modifyt;matchremovetkwith|`No_such_key->raise_remove_unknown_keytk|`Ok->();;letlookup_and_removetk=ensure_can_modifyt;matchTable.find_and_removet.tablekwith|None->None|Someelt->Doubly_linked.removet.queueelt;Some(Elt.valueelt).value;;letreplacetkv=ensure_can_modifyt;matchTable.findt.tablekwith|None->`No_such_key|Someelt->(Elt.valueelt).value<-v;`Ok;;letraise_replace_unknown_keytkey=raise_s[%message"Hash_queue.replace_exn: unknown key"~_:(Table.sexp_of_keyt.tablekey:Sexp.t)];;letreplace_exntkv=ensure_can_modifyt;matchreplacetkvwith|`No_such_key->raise_replace_unknown_keytk|`Ok->();;letdrop?(n=1)tback_or_front=ifn>=lengthtthencleartelsefor_=1tondoignore(dequeue_with_keytback_or_front:_option)done;;letdrop_back?nt=drop?nt`backletdrop_front?nt=drop?nt`frontletcopyt=letcopied=create~size:(lengtht)(Table.hashablet.table)initerit~f:(fun~key~data->enqueue_back_exncopiedkeydata);copied;;endmoduletypeS=S0withtype('key,'data)hash_queue:=('key,'data)Backend.tmoduleMake_with_hashable(T:sigmoduleKey:Keyvalhashable:Key.tHashtbl.Hashable.tend):Swithtypekey=T.Key.t=structinclude(Backend:Backendwithtype('k,'d)t:=('k,'d)Backend.t)typekey=T.Key.ttype'datat=(T.Key.t,'data)Backend.t[@@derivingsexp_of]lethashable=T.hashableletcreate?growth_allowed?size()=create?growth_allowed?sizehashableendmoduleMake(Key:Key):Swithtypekey=Key.t=Make_with_hashable(structmoduleKey=Keylethashable=Table.Hashable.of_key(moduleKey)end)includeBackendendincludeMake_backend(Hashtbl)