123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108(*********************************************************************************)(* OCaml-Stk *)(* *)(* Copyright (C) 2023-2024 INRIA All rights reserved. *)(* Author: Maxence Guesdon, INRIA Saclay *)(* *)(* This program is free software; you can redistribute it and/or modify *)(* it under the terms of the GNU General Public License as *)(* published by the Free Software Foundation, version 3 of the License. *)(* *)(* This program is distributed in the hope that it will be useful, *)(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)(* GNU General Public License for more details. *)(* *)(* You should have received a copy of the GNU General Public *)(* License along with this program; if not, write to the Free Software *)(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)(* 02111-1307 USA *)(* *)(* As a special exception, you have permission to link this program *)(* with the OCaml compiler and distribute executables, as long as you *)(* follow the requirements of the GNU GPL in regard to all of the *)(* software in the executable aside from the OCaml compiler. *)(* *)(* Contact: Maxence.Guesdon@inria.fr *)(* *)(*********************************************************************************)moduleCbId=Misc.Id()type_ev=..moduleO=structtypet=unitevletcomparett'=(*[%debug
(fun m -> m "comparing %s and %s"
(Printexc.to_string (Obj.magic t))
(Printexc.to_string (Obj.magic t'))); *)Stdlib.comparett'endmoduleM=Map.Make(O)moduleCbIMap=Map.Make(CbId)typecallbacks={mutableby_ev:(unit->unit)CbIMap.tM.t;mutableby_id:unitevCbIMap.t;}letcallbacks()={by_ev=M.empty;by_id=CbIMap.empty}typecallback_id={id:CbId.t;unregister:unit->unit}letmagic_ev:'aev->unitev=funev->Obj.magicevletmagic_cb:'a->(unit->unit)=funcb->Obj.magiccbletcallbacks_of_evcallbacksev=matchM.find_optevcallbacks.by_evwith|None->[]|Somem->CbIMap.fold(fun_idcbacc->cb::acc)m[]letget:callbacks->'aev->'alist=funcallbacksev->Obj.magic(callbacks_of_evcallbacks(magic_evev))letunregister=letremovecallbacksevid=matchM.find_optevcallbacks.by_evwith|None->()|Somecbs->letcbs=CbIMap.removeidcbsincallbacks.by_ev<-M.addevcbscallbacks.by_ev;callbacks.by_id<-CbIMap.removeidcallbacks.by_idinfuncallbacksid->[%debug"unregistering callback %s"(CbId.to_stringid)];matchCbIMap.find_optidcallbacks.by_idwith|None->()|Someev->removecallbacksevidletregistercallbacks?countevcb=letid=CbId.gen()inletcbs=matchM.find_optevcallbacks.by_evwith|None->CbIMap.empty|Somem->minletcb=matchcountwith|None->cb|Somecount->letcount=refcountinletfx=decrcount;if!count<=0thenunregistercallbacksid;cbxinfincallbacks.by_ev<-M.addev(CbIMap.addidcbcbs)callbacks.by_ev;callbacks.by_id<-CbIMap.addidevcallbacks.by_id;[%debug"Registered callback %s for %s"(CbId.to_stringid)(Printexc.to_string(Obj.magicev))];{id;unregister=(fun()->unregistercallbacksid)}letregister:callbacks->?count:int->'aev->'a->callback_id=funcallbacks?countevcb->registercallbacks?count(magic_evev)(magic_cbcb)letunregistercb=cb.unregister()