123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128(**************************************************************************)(* Lablgtk *)(* *)(* This program is free software; you can redistribute it *)(* and/or modify it under the terms of the GNU Library General *)(* Public License as published by the Free Software Foundation *)(* version 2, with the exception described in file COPYING which *)(* comes with the library. *)(* *)(* 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 Library General Public License for more details. *)(* *)(* You should have received a copy of the GNU Library 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 *)(* *)(* *)(**************************************************************************)(* $Id$ *)openGtkMain(* Job handling for Windows *)letjobs:(unit->unit)Queue.t=Queue.create()letm=Mutex.create()letwith_jobsf=Mutex.lockm;lety=fjobsinMutex.unlockm;yletloop_id=refNoneletreset()=loop_id:=Noneletcannot_sync()=match!loop_idwithNone->true|Someid->Thread.id(Thread.self())=idletgui_safe()=not(Sys.os_type="Win32")||!loop_id=Some(Thread.id(Thread.self()))lethas_jobs()=not(with_jobsQueue.is_empty)letn_jobs()=with_jobsQueue.lengthletdo_next_job()=with_jobsQueue.take()lethas_timeout=reffalseletasyncjx=with_jobs(funjobs->Queue.add(fun()->GtkSignal.safe_calljx~where:"asynchronous call")jobs;ifnot!has_timeoutthenbeginhas_timeout:=true;ignore(Glib.Timeout.add1(fun()->has_timeout:=false;false))end)type'aresult=Valof'a|Exnofexn|NAletsyncfx=ifcannot_sync()thenfxelseletm=Mutex.create()inletres=refNAinMutex.lockm;letc=Condition.create()inletjx=lety=tryVal(fx)withe->ExneinMutex.lockm;res:=y;Mutex.unlockm;Condition.signalcinasyncjx;while!res=NAdoCondition.waitcmdone;match!reswithValy->y|Exne->raisee|NA->assertfalseletdo_jobs_delay=ref0.013;;letset_do_jobs_delayd=do_jobs_delay:=max0.d;;letdo_jobs()=fori=1ton_jobs()dodo_next_job()done;true(* We check first whether there are some event pending, and run
some iterations. We then need to delay, thus focing a thread switch. *)letbusy_waiting=ref(trySys.getenv"LABLGTK_BUSY_WAIT"<>"0"with_->false)letthread_main_real()=tryletloop=(Glib.Main.createtrue)inMain.loops:=loop::!Main.loops;Glib.Main.wrap_poll_func();(* mark polling as blocking *)loop_id:=Some(Thread.id(Thread.self()));whileGlib.Main.is_runningloopdoifnot!busy_waitingthenignore(Glib.Main.iterationtrue)(* blocking *)elsebeginleti=ref0in(* Non blocking busy waiting *)Thread.delay!do_jobs_delay;while!i<100&&Glib.Main.pending()doGlib.Main.iterationtrue;incridoneend;do_jobs()done;Main.loops:=List.tl!Main.loops;withexn->Main.loops:=List.tl!Main.loops;raiseexnletthread_main()=syncthread_main_real()letmain()=GtkMain.Main.main_func:=thread_main;thread_main()letstart()=reset();Thread.createmain()(* The code below would do nothing...
let _ =
let mutex = Mutex.create () in
let depth = ref 0 in
GtkSignal.enter_callback :=
(fun () -> if !depth = 0 then Mutex.lock mutex; incr depth);
GtkSignal.exit_callback :=
(fun () -> decr depth; if !depth = 0 then Mutex.unlock mutex)
*)