123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)openLwt.Syntaxtypet={mutablepending_tasks:unitLwt.ulist;mutablepending_idle:(unit->unitLwt.t)list;mutablerunning_tasks:int;mutablerunning_idle:bool;mutableprevent_tasks:bool;}letcreate()={pending_tasks=[];pending_idle=[];running_tasks=0;running_idle=false;prevent_tasks=false;}letrecmay_run_idle_tasksw=ifw.running_tasks=0&¬w.running_idlethenmatchw.pending_idlewith|[]->()|pending_idle->w.running_idle<-true;w.prevent_tasks<-false;w.pending_idle<-[];(* TODO: can we safely remove async and ignore the created
thread? *)Lwt.async(fun()->letpending_idle=List.revpending_idleinlet*()=Lwt_list.iter_s(funf->f())pending_idleinw.running_idle<-false;letpending_tasks=List.revw.pending_tasksinw.pending_tasks<-[];List.iter(funu->Lwt.wakeupu())pending_tasks;may_run_idle_tasksw;Lwt.return_unit)letwrap_errorf=Lwt.catch(fun()->Lwt_result.ok@@f())(funexn->Lwt.return_errorexn)letunwrap_error=functionOkr->Lwt.returnr|Errorexn->Lwt.failexnletwakeup_erroru=function|Okr->Lwt.wakeupur|Errorexn->Lwt.wakeup_exnuexnletrectaskwf=ifw.running_idle||w.prevent_tasksthen(lett,u=Lwt.task()inw.pending_tasks<-u::w.pending_tasks;let*()=tintaskwf)else(w.running_tasks<-w.running_tasks+1;let*res=wrap_errorfinw.running_tasks<-w.running_tasks-1;may_run_idle_tasksw;unwrap_errorres)letwhen_idlewf=lett,u=Lwt.task()inletcanceled=reffalseinLwt.on_cancelt(fun()->canceled:=true);letf()=if!canceledthenLwt.return_unitelselet*res=wrap_errorfinwakeup_errorures;Lwt.return_unitinw.pending_idle<-f::w.pending_idle;may_run_idle_tasksw;tletforce_idlewf=w.prevent_tasks<-true;when_idlewf