123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101(* This file is free software, part of Zipperposition. See file "license" for more details. *)(** {1 Basic signal} *)typehandler_response=|ContinueListening|StopListeningtype'at={mutablen:int;(* how many handlers? *)mutablehandlers:('a->handler_response)array;mutablealive:keepalive;(* keep some signal alive *)}(** Signal of type 'a *)andkeepalive=|Keep:'at->keepalive|NotAlive:keepalivelet_exn_handler=ref(fun_->())letnop_handler_=ContinueListeningletcreate()=lets={n=0;handlers=Array.make3nop_handler;alive=NotAlive;}ins(* remove handler at index i *)letremovesi=assert(s.n>0&&i>=0);ifi<s.n-1(* erase handler with the last one *)thens.handlers.(i)<-s.handlers.(s.n-1);s.handlers.(s.n-1)<-nop_handler;(* free handler *)s.n<-s.n-1;()letsendsx=fori=0tos.n-1dowhilebegintrymatchs.handlers.(i)xwith|ContinueListening->false(* keep *)|StopListening->truewithe->!_exn_handlere;false(* be conservative, keep... *)enddoremovesi(* i-th handler is done, remove it *)donedoneletonsf=(* resize handlers if needed *)ifs.n=Array.lengths.handlersthenbeginlethandlers=Array.make(s.n+4)nop_handlerinArray.blits.handlers0handlers0s.n;s.handlers<-handlersend;s.handlers.(s.n)<-f;s.n<-s.n+1leton_everysf=ons(funx->ignore(fx);ContinueListening)letoncesf=ons(funx->ignore(fx);StopListening)letpropagateab=on_everya(sendb)(** {2 Combinators} *)letmapsignalf=letsignal'=create()in(* weak ref *)letr=Weak.create1inWeak.setr0(Somesignal');onsignal(funx->matchWeak.getr0with|None->StopListening|Somesignal'->sendsignal'(fx);ContinueListening);signal'.alive<-Keepsignal;signal'letfiltersignalp=letsignal'=create()in(* weak ref *)letr=Weak.create1inWeak.setr0(Somesignal');onsignal(funx->matchWeak.getr0with|None->StopListening|Somesignal'->(ifpxthensendsignal'x);ContinueListening);signal'.alive<-Keepsignal;signal'letset_exn_handlerh=_exn_handler:=h