view qutils.pl @ 3:13b598d91c15

get_message_or_timeout/2 now uses thread_get_message/3 if available; player now supports optional event transform between source and destination; removed deprecated index declarations.
author samer
date Tue, 07 Feb 2012 14:49:28 +0000
parents b39711ae9035
children af1ebea468b5
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)).

%% 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)).

get_message_or_timeout(Deadline,Msg) :- 
	get_time(Now), 
	(	Now>=Deadline -> Msg=timeout %, writeln(elapsed)
	;	Timeout is Deadline-Now,
		thread_self(Thread),
		thread_get_message(Thread,Msg,[timeout(Timeout)])
	).	

:- else.

get_message_or_timeout(Deadline,Msg) :- 
	get_time(Now), 
	(	Now>=Deadline -> Msg=timeout %, writeln(elapsed)
	;	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))
		%,(Msg\=timeout -> writeln(msg:Msg); true)
	).	

:-endif.

/*
get_message_or_timeout(Deadline,Msg) :- 
	get_time(Now), 
	(	Now>=Deadline -> Msg=timeout, writeln(elapsed)
	;	catch(
			deadline_get_message(Deadline,Msg),
			time_limit_exceeded,
			Msg=timeout)
		%, (Msg\=timeout -> writeln(msg:Msg); true)
	).	

deadline_get_message(Deadline,Msg) :-
	setup_call_cleanup(
		alarm_at(Deadline, ding_ding, Id), 
		thread_get_message(Msg),
		time:remove_alarm_notrace(Id)).

ding_ding :- throw(time_limit_exceeded).


*/



%% 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('*')
	).