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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//! How a `Send + Sync` [`crate::Regex`] is built out of a handle that is not.
//!
//! The header is blunt: an `irgx_regex *` owns the scratch its finds run in,
//! so two threads sharing one corrupt a match rather than race a counter, and
//! the advice is to compile one per thread. A Rust programmer, meanwhile, will
//! write `static RE: LazyLock<Regex>` and hand it to Rayon without a second
//! thought, because that is what the `regex` crate's type allows.
//!
//! Both facts are satisfied by owning a **pool** of handles instead of one.
//! Every search leases a handle, uses it alone, and returns it; the pool grows
//! to the concurrency the caller actually reaches and every handle is freed when
//! the pool drops. `unsafe impl Sync` over one shared handle would have been the
//! other way to make the type compile, and it would have been a data race.
//!
//! A pool rather than a thread-local because a thread-local keyed by pattern
//! cannot be cleaned up: the owning `Regex` can only reach its *own* thread's
//! slot, so a handle parked in a long-lived worker thread outlives the pattern
//! that made it. The pool has no such hole, and it sizes itself by how many
//! threads search at once rather than by how many threads exist.
//!
//! Two kinds of handle need this and the reasoning is identical for both, so the
//! pool is generic over a [`Recipe`] — what to compile, and how to release it —
//! and the `unsafe impl Send` that carries the argument lives in exactly one
//! place. `RegexSet` inherited a correct pool the day it was written rather than
//! a second copy of this file with `slate` substituted for `regex`.
use PhantomData;
use ManuallyDrop;
use NonNull;
use ;
use crateError;
use cratesys;
/// What a pool replicates: how to mint one handle, and how to release it.
///
/// The recipe is also the pool's *storage* — it holds the pattern text a later
/// handle is compiled from — which is why it is one trait and not a compile
/// closure beside a free function. A pool that could not recompile could not
/// grow, and a pool that borrowed its pattern from elsewhere would put the
/// lifetime back into the type the caller wanted to put in a `static`.
pub
/// One handle, released when this value drops.
>);
// SAFETY: the handle is single-threaded, which is not the same as thread-bound.
// Everything it owns lives in the C allocator, whose free is callable from any
// thread, and the engine keeps no thread-local state tied to a handle (the fault
// slot is per-thread and read on the thread that filled it). Moving one across
// threads is therefore sound as long as only one thread uses it at a time, and
// `Pool` is the thing that guarantees that: a handle is only ever reachable
// through a `Lease`, and the mutex that hands the lease out also supplies the
// happens-before edge between the previous holder's last write and this one's
// first read.
unsafe
/// A recipe's compiled form, replicated per concurrent user.
pub
/// Exclusive use of one handle, returned to its pool on drop.
pub
/// A non-negative status that wrote no handle is the library breaking its own
/// contract. Refusing beats handing a null pointer to every later call.
pub