123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146(*
* Copyright (c) 2022 Tarides <contact@tarides.com>
*
* Permission to use, copy, modify, and 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.
*)openImportincludeStorage_intfmoduleRead_only(M:Make)=functor(K:Type.S)(V:Type.S)->structmoduleS=M(K)(V)type'at=S.ttypekey=S.keytypevalue=S.valueletv=S.vletmem=S.memletfind=S.findletclose=S.closeendmoduleContent_addressable(M:Make):Content_addressable.Maker=functor(H:Hash.S)(V:Type.S)->structincludeRead_only(M)(H)(V)moduleH=Hash.Typed(H)(V)letbatch=S.batchletaddtvalue=letkey=H.hashvalueinlet+()=S.settkeyvalueinkeyletequal_hash=Type.(equalH.t|>unstage)letpp_hash=Type.(ppH.t)letunsafe_addtkv=let+hash'=addtvinifequal_hashkhash'then()elseFmt.failwith"[unsafe_append] %a is not a valid key. Expecting %a instead.\n"pp_hashkpp_hashhash'endmoduleAppend_only(M:Make):Append_only.Maker=functor(Key:Type.S)(Value:Type.S)->structincludeRead_only(M)(Key)(Value)letbatch=S.batchletadd=S.setendmoduleAtomic_write(M:Make):Atomic_write.Maker=functor(Key:Type.S)(Value:Type.S)->structmoduleS=M(Key)(Value)moduleW=Watch.Make(Key)(Value)moduleL=Lock.Make(Key)typet={t:S.t;w:W.t;l:L.t}typekey=S.keytypevalue=S.valuetypewatch=W.watchletwatches=W.v()letlock=L.v()letvconfig=let*t=S.vconfiginLwt.return{t;w=watches;l=lock}letfind{t;_}=S.findtletmem{t;_}=S.memtmoduleInternal=structletsettwkeyvalue=let*()=S.settkeyvalueinW.notifywkey(Somevalue)letremovetwkey=let*()=S.removetkeyinW.notifywkeyNoneendletlist{t;_}=S.keystletset{t;l;w}keyvalue=L.with_locklkey@@fun()->Internal.settwkeyvalueletremove{t;l;w}key=L.with_locklkey@@fun()->Internal.removetwkeylettest_and_set=letvalue_equal=Type.(unstage(equal(optionValue.t)))infun{t;l;w}key~test~set:set_value->L.with_locklkey@@fun()->let*v=S.findtkeyinifvalue_equalvtestthenlet*()=matchset_valuewith|Someset_value->Internal.settwkeyset_value|None->Internal.removetwkeyinLwt.return_trueelseLwt.return_falseletwatch_key{w;_}key=W.watch_keywkeyletwatch{w;_}=W.watchwletunwatch{w;_}=W.unwatchwletclear{t;w;_}=let*()=W.clearwinS.cleartletclose{t;w;_}=let*()=W.clearwinS.closetend