1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! **The driver's end of the routing leg** (REMOTE §3, §5, §9 step 7;
//! bl-024b): what a loaded remote name actually does when the model calls it.
//!
//! The injection runs inside the **driver**, a child process (see
//! [`super::ask`]), so this is the same deposit round trip the roster read is —
//! `Query`/`Action` envelopes into `<yog-state-root>/gestures/`, replies read
//! back with the one reply codec. No verb and no transport were added for the
//! driver's side either: `invoke` and `capture` are boundary gestures every
//! face gains.
//!
//! **Two gestures rather than one, and that is the whole shape.** The engine's
//! intake is one thread for the world, so a gesture that waited for a tool to
//! finish would stop every other deposit converging for as long as the tool
//! ran. `invoke` therefore queues and answers immediately, and the *waiting* is
//! here, in the child that has nothing else to do — which is also the only
//! process that knows how long this call is worth waiting for.
//!
//! **The deadline is the visible refusal** (REMOTE §5: *"a vanished client is a
//! visible refusal, not a hang"*). Nothing anywhere asks whether the far
//! machine is connected: a tool host holds its connection only while it is
//! waiting, so it is *absent* for the whole time it is busy, and a presence
//! test would refuse the second call of a host that is certainly there. What a
//! machine that never answers earns is this loop running out, in band, naming
//! how long it waited.
//!
//! **One stop check, and it is [`ask`]'s** (bl-3a88). Two waits nest here — the
//! poll loop below and, inside each of its round trips, the wait on the engine —
//! so a stop flag read in both places is one fact with two answers, and *which*
//! answer a caller gets is decided by where the flag happened to land. That is
//! not a race a test can synchronize on: the interval between reading the reply
//! and reading the flag has no observable event in it. So the flag is read at
//! the one place that waits on a reply, and [`routed`] names the host there —
//! whichever nested wait notices, the sentence the model reads is the same one.
//! The cost is that a stop landing just after a poll answered is noticed at the
//! next round trip rather than at once, one `patience.tick` later; the wait
//! still "ends early on litany's stop flag" (REMOTE §5) by two orders of
//! magnitude of its bound.
use ;
use ;
use ;
use ;
use crate;
use crateCapture;
/// Run one loaded remote name on the machine that advertised it, and answer
/// what it captured — or the sentence saying why nothing did.
/// One `Reply::Routed` round trip: the handle, and the capture if there is one
/// yet. A refusal envelope and an envelope of another kind are the same class
/// of answer — the engine did not say what was asked — and both name what came
/// back, exactly as [`ask::roster`] does.
///
/// **A wait that ended on the stop flag is named with `client` here**, because
/// this is the innermost layer that knows whose call it was and [`ask`] is the
/// only layer that reads the flag (see the module note). Only the *wait* is
/// rewritten: an answer that arrived is decoded and reported as itself, stop or
/// no stop.
/// How long a driver waits on a *tool* — as against on the engine
/// ([`Budget::default`], which bounds one deposit round trip). Two bounds
/// because they measure two different things: an engine that has not answered
/// in ten seconds is down, and a tool that has not answered in ten seconds is
/// working.