Mercurial > hg > reactive
view qutils.pl @ 6:ef5802225f99
get_message_or_timeout now uses deadline/1 option of thread_get_message if available.
author | samer |
---|---|
date | Mon, 13 Feb 2012 13:04:26 +0000 |
parents | af1ebea468b5 |
children | 99572a386ccf |
line wrap: on
line source
:- module( qutils, [ with_message/2 , with_message_or_timeout/4 , get_message_or_timeout/2 , send_with_size_limit/3 ]). :- meta_predicate with_message(?,0). :- meta_predicate with_message_or_timeout(+,?,0,0). :- use_module(library(time)). :- use_module(library(debug)). %% get_message_or_timeout( +TimeOut, -Msg) is det. % % Time-limited wait for next term in message queue. % Waits up to TimeOut seconds for the next message that % unifies with Msg in the current thread. If none arrives, % then Msg is unified with timeout. % NB: may fail if Msg is bound on input. get_message_or_timeout(inf,Msg) :- !, thread_get_message(Msg). :- if(current_predicate(thread_get_message/3)). :- if(current_predicate_option(thread_get_message/3,3,deadline(_))). :- writeln('% compiling get_message_or_timeout/2 using deadline/1 option.'). get_message_or_timeout(Deadline,Msg) :- thread_self(Thread), thread_get_message(Thread,Msg,[deadline(Deadline)]), debug(qutils,'got message: ~w.',[Msg]). :- else. :- writeln('% compiling get_message_or_timeout/2 using timeout/1 option.'). get_message_or_timeout(Deadline,Msg) :- get_time(Now), ( Now>=Deadline -> Msg=timeout, debug(qutils,'deadline already missed.',[]) ; Timeout is Deadline-Now, thread_self(Thread), thread_get_message(Thread,Msg,[timeout(Timeout)]), debug(qutils,'got message: ~w.',[Msg]) ). :- endif. :- else. :- writeln('% compiling get_message_or_timeout/2 using alarm and message send.'). get_message_or_timeout(Deadline,Msg) :- get_time(Now), ( Now>=Deadline -> Msg=timeout, debug(qutils,'deadline already missed.',[]) ; thread_self(Thread), setup_call_cleanup( alarm_at(Deadline, thread_send_message(Thread,timeout), Id), thread_get_message(Thread,Msg), time:remove_alarm_notrace(Id)), debug(qutils,'got message: ~w.',[Msg]) ). :-endif. %% with_message( Msg, :Goal) is nondet. % % Waits for next message, unify with Msg, and call Goal. % This procedure gets the next term out of the current thread's % message queue, waiting if necessary. If it is 'quit', then % it succeeds immediately leaving Msg unchanged. If it unifies % with Msg, then Goal is called. Otherwise, a message is printed % and the proceduce succeeds. with_message(Temp,OnEvent) :- thread_get_message(Msg), ( Msg=quit -> true ; Msg=Temp -> call(OnEvent) ; writeln(template_mismatch(Temp,Msg)) ). %% with_message_or_timeout( +TimeOut, Msg, :OnEvent, :OnTimeOut) is nondet. % % Time limited wait for message with handler goals for either case. % Waits up to TimeOut seconds for next message, unify with Msg, % and call OnEvent. If none arrives before TimeOut expires, % OnTimeOut is called instead. If the message is 'quit', it % just returns. If the message does not unify with Msg, some % text is printed and the proceduce succeeds. with_message_or_timeout(T,Temp,OnEvent,OnTimeout) :- get_message_or_timeout(T,Msg), ( Msg=quit -> true ; Msg=timeout -> call(OnTimeout) ; Msg=Temp -> call(OnEvent) ; writeln(template_mismatch(Temp,Msg)) ). %% send_with_size_limit( +Max:natural, +Queue:queue_id, +Msg:term) is det. % % Adds term to message queue unless queue is already full. % If message queue Queu already contains more than Max elements, % then "*" is printed and the procedure succeeds. NB. the message % is discarded. send_with_size_limit(Max,Queue,Msg) :- message_queue_property(Queue,size(QSize)), ( QSize<Max -> thread_send_message(Queue,Msg) ; writeln('*') ).