Function signal [src]
Unblocks at least one thread blocked in a call to wait() or timedWait() with a given Mutex.
The blocked thread must be sequenced before this call with respect to acquiring the same Mutex in order to be observable for unblocking.
signal() can be called with or without the relevant Mutex being acquired and have no "effect" if there's no observable blocked threads.
Prototype
pub fn signal(self: *Condition) void
Parameters
self: *Condition
Example
test signal {
// This test requires spawning threads
if (builtin.single_threaded) {
return error.SkipZigTest;
}
const num_threads = 4;
const SignalTest = struct {
mutex: Mutex = .{},
cond: Condition = .{},
notified: bool = false,
threads: [num_threads]std.Thread = undefined,
spawn_count: std.math.IntFittingRange(0, num_threads) = 0,
fn run(self: *@This()) void {
self.mutex.lock();
defer self.mutex.unlock();
self.spawn_count += 1;
// Use timedWait() a few times before using wait()
// to test multiple threads timing out frequently.
var i: usize = 0;
while (!self.notified) : (i +%= 1) {
if (i < 5) {
self.cond.timedWait(&self.mutex, 1) catch {};
} else {
self.cond.wait(&self.mutex);
}
}
// Once we received the signal, notify another thread (inside the lock).
assert(self.notified);
self.cond.signal();
}
};
var signal_test = SignalTest{};
for (&signal_test.threads) |*t| {
t.* = try std.Thread.spawn(.{}, SignalTest.run, .{&signal_test});
}
while (true) {
std.time.sleep(10 * std.time.ns_per_ms);
signal_test.mutex.lock();
defer signal_test.mutex.unlock();
// Make sure at least one thread has finished spawning to avoid testing nothing.
if (signal_test.spawn_count > 0) break;
}
{
// Wake up one of them (outside the lock) after setting notified=true.
defer signal_test.cond.signal();
signal_test.mutex.lock();
defer signal_test.mutex.unlock();
try testing.expect(!signal_test.notified);
signal_test.notified = true;
}
for (signal_test.threads) |t| {
t.join();
}
}
Source
pub fn signal(self: *Condition) void {
self.impl.wake(.one);
}