Textually #included by:
vc-evjump.setl (Section A.13 [vc-evjump.setl])
vc-evzoom.setl (Section A.14 [vc-evzoom.setl])
Textually #includes:
vc-exit.setl (Section A.15 [vc-exit.setl])
vc-getname.setl (Section A.16 [vc-getname.setl])
vc-msg.setl (Section A.30 [vc-msg.setl])
vc-obtain.setl (Section A.31 [vc-obtain.setl])
vc-provide.setl (Section A.32 [vc-provide.setl])
Source code: *
-- This file is meant to be #included by others, after they define:
--
-- yhwh - the name of the program that #includes this code
-- event_type - the name of the service being provided
-- of_interest - the command tokens we look for
-- n_parms - how many parameters after the command tokens to expect
const n = #of_interest;
const notice_fd = fileno obtain_service (`notice');
const sigterm_fd = open (`SIGTERM', `signal'); -- catch TERM signals
const server_fd = fileno provide_service (event_type);
var clients := {};
var current_event := om;
open (`SIGPIPE', `ignore'); -- as when we write to closed observers
loop
[ready] := select ([{sigterm_fd, server_fd, notice_fd} +
domain clients]);
if sigterm_fd in ready then
msg (yhwh + ` (' + str pid + `) caught SIGTERM');
quit_gracefully;
end if;
for client = clients(pump_fd) | pump_fd in ready loop
ack := getline pump_fd;
if eof then
done_client (pump_fd);
else
if client.last_eventcurrent_event then
tell_client (pump_fd, current_event);
else
clients(pump_fd).hungry := true;
end if;
end if;
end loop;
if server_fd in ready then
fd := accept (server_fd);
if fdom then
name := getname fd;
msg (name+` accepted');
pump_fd := pump();
if pump_fd = -1 then
-- child
while (event := getline stdin)om loop
printa (fd, event);
if (ack := getline fd) = om then
stop;
end if;
print;
end loop;
stop;
end if;
-- parent continues here
close (fd);
client := {};
client.name := name;
client.hungry := true;
clients(pump_fd) := client;
-- send initial event if any
if current_eventom then
tell_client (pump_fd, current_event);
end if;
end if;
end if;
if notice_fd in ready then
reada (notice_fd, raw_event);
if is_string raw_event then
t := split (raw_event);
if t(1..n) = of_interest and #t-n = n_parms then
tell_observers ((+/[` '+x : x in t(n+1..)])(2..));
end if;
end if;
end if;
end loop;
proc tell_observers (event);
for client = clients(pump_fd) loop
if client.hungry then
tell_client (pump_fd, event);
end if;
end loop;
current_event := event;
end proc tell_observers;
proc tell_client (pump_fd, event);
printa (pump_fd, event);
flush (pump_fd);
if last_errorno_error then
done_client (pump_fd);
else
client := clients(pump_fd);
client.hungry := false;
client.last_event := event;
clients(pump_fd) := client;
end if;
end proc tell_client;
proc done_client (pump_fd);
msg (clients(pump_fd).name + ` done');
close (pump_fd);
clients(pump_fd) := om;
end proc done_client;
proc quit_gracefully;
exit_gracefully ([[`pump for client ' + client.name, pump_fd] :
client = clients(pump_fd)]);
end proc;
#include ``vc-provide.setl''
#include ``vc-obtain.setl''
#include ``vc-getname.setl''
#include ``vc-exit.setl''
#include ``vc-msg.setl''