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
// Copyright 2025 Lablup Inc. and Jeongkyu Shin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! A one-way boolean latch that any number of tasks can await
//! (issue #311).
//!
//! `all-smi api` previously learned about shutdown from exactly two
//! sources, `Ctrl+C` and `SIGTERM`. The Windows Service Control Manager
//! has neither: a Stop control arrives on a handler thread with no
//! signal to raise, so the SCM backend needs a way to reach the same
//! graceful path (server drain, then energy WAL flush). The same shape
//! answers the mirror question of when the service may report
//! `SERVICE_RUNNING`, which is "once a listener is bound".
//!
//! That boundary was revisited in issue #324, which added a real
//! readiness signal, and deliberately left unchanged. See
//! [`crate::api::shutdown::mark_serving`] for the reasoning; the short
//! version is that this latch answers "is it serving", `/-/ready` answers
//! "is it ready", and the SCM only has a question of the first kind.
//!
//! Both are one-way transitions: `false` once, `true` forever after.
//! [`Latch`](crate::api::latch::Latch) is that primitive, and it is a
//! plain value rather than a process global so its semantics can be unit
//! tested deterministically on any platform, including hosts that will
//! never run a Windows service.
use Arc;
use watch;
/// A latch that starts closed and can be opened exactly once.
///
/// Cloning shares the underlying state. [`Latch::wait`] resolves for
/// *every* waiter, including waiters created after the trigger, which is
/// why this wraps a [`watch`] channel rather than a
/// [`tokio::sync::Notify`]: `notify_one` would hand the single stored
/// permit to whichever waiter got there first, and `notify_waiters`
/// would be lost entirely when it fires before anyone subscribes.
// Test module lives in `latch_tests.rs` to keep this file focused.