121 lines
3.2 KiB
Perl
121 lines
3.2 KiB
Perl
|
/* $Id$
|
||
|
|
||
|
Part of SWI-Prolog
|
||
|
|
||
|
Author: Jan Wielemaker
|
||
|
E-mail: jan@swi.psy.uva.nl
|
||
|
WWW: http://www.swi-prolog.org
|
||
|
Copyright (C): 1985-2002, University of Amsterdam
|
||
|
|
||
|
This program is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU General Public License
|
||
|
as published by the Free Software Foundation; either version 2
|
||
|
of the License, or (at your option) any later version.
|
||
|
|
||
|
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 General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU Lesser General Public
|
||
|
License along with this library; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
|
||
|
As a special exception, if you link this library with other files,
|
||
|
compiled with a Free Software compiler, to produce an executable, this
|
||
|
library does not by itself cause the resulting executable to be covered
|
||
|
by the GNU General Public License. This exception does not however
|
||
|
invalidate any other reasons why the executable file might be covered by
|
||
|
the GNU General Public License.
|
||
|
*/
|
||
|
|
||
|
:- module(stream_pool,
|
||
|
[ add_stream_to_pool/2, % +Stream, :Goal
|
||
|
delete_stream_from_pool/1, % +Stream
|
||
|
close_stream_pool/0,
|
||
|
dispatch_stream_pool/1, % +TimeOut
|
||
|
stream_pool_main_loop/0
|
||
|
]).
|
||
|
:- use_module(library(quintus)).
|
||
|
|
||
|
:- meta_predicate
|
||
|
add_stream_to_pool(+, :).
|
||
|
|
||
|
:- volatile
|
||
|
pool/2. % sockets don't survive a saved-state
|
||
|
:- dynamic
|
||
|
pool/2. % Stream, Action
|
||
|
|
||
|
% add_stream_to_pool(+Stream :Goal)
|
||
|
%
|
||
|
% Call Goal whenever there is input on Stream.
|
||
|
|
||
|
add_stream_to_pool(Stream, Action) :-
|
||
|
strip_module(Action, Module, Plain),
|
||
|
register_stream(Stream, Module:Plain).
|
||
|
|
||
|
register_stream(Stream, Goal) :-
|
||
|
assert(pool(Stream, Goal)).
|
||
|
|
||
|
% delete_stream_from_pool(+Stream)
|
||
|
%
|
||
|
% Retract stream from the pool
|
||
|
|
||
|
delete_stream_from_pool(Stream) :-
|
||
|
retractall(pool(Stream, _)).
|
||
|
|
||
|
% close_stream_pool
|
||
|
|
||
|
close_stream_pool :-
|
||
|
( retract(pool(Stream, _)),
|
||
|
close(Stream, [force(true)]),
|
||
|
fail
|
||
|
; true
|
||
|
).
|
||
|
|
||
|
% dispatch_stream_pool(+TimeOut)
|
||
|
%
|
||
|
% Wait for input on one or more streams and handle that. Wait for
|
||
|
% at most TimeOut seconds (0 means infinite).
|
||
|
|
||
|
dispatch_stream_pool(Timeout) :-
|
||
|
findall(S, pool(S, _), Pool),
|
||
|
catch(wait_for_input(Pool, Ready, Timeout), E, true),
|
||
|
debug(tcp, 'Select ~w --> ~w (E=~w)', [Pool, Ready, E]),
|
||
|
( var(E)
|
||
|
-> actions(Ready)
|
||
|
; E = error(existence_error(stream, Stream), _)
|
||
|
-> delete_stream_from_pool(Stream)
|
||
|
).
|
||
|
|
||
|
actions([]).
|
||
|
actions([H|T]) :-
|
||
|
action(H),
|
||
|
actions(T).
|
||
|
|
||
|
action(Stream) :-
|
||
|
pool(Stream, Action),
|
||
|
( catch(Action, E, true)
|
||
|
-> ( var(E)
|
||
|
-> true
|
||
|
; print_message(error, E)
|
||
|
)
|
||
|
; print_message(warning,
|
||
|
goal_failed(Action, stream_pool))
|
||
|
).
|
||
|
|
||
|
% stream_pool_main_loop
|
||
|
%
|
||
|
% Keep handling input from the streams in the pool until they have
|
||
|
% all died away.
|
||
|
|
||
|
stream_pool_main_loop :-
|
||
|
pool(_, _), !,
|
||
|
( current_prolog_flag(windows, true)
|
||
|
-> dispatch_stream_pool(1) % so we can break out easily
|
||
|
; dispatch_stream_pool(0)
|
||
|
),
|
||
|
stream_pool_main_loop.
|
||
|
stream_pool_main_loop.
|
||
|
|