authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-01-30 12:00:49+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-01-30 12:00:49+02:00
log9c36ae46260cc680663ba3347da06e5e2a16590b
tree8bd50fbf997c799c6cd4e644641c8a0d48715fe8
parent924eb08b613e3333419512f4de02b167aba9336d
parentbdd1a9e48c7a1a09cf0a3b7c0d5be6547f8ef1aa
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10728 from naeu/thread-tests

Add tests for std.Thread.Condition and std.Thread.Semaphore

2 files changed, 73 insertions(+), 0 deletions(-)

lib/std/Thread/Condition.zig+45
......@@ -11,6 +11,7 @@ const windows = std.os.windows;
1111const linux = std.os.linux;
1212const Mutex = std.Thread.Mutex;
1313const assert = std.debug.assert;
14const testing = std.testing;
1415
1516pub fn wait(cond: *Condition, mutex: *Mutex) void {
1617 cond.impl.wait(mutex);
......@@ -193,3 +194,47 @@ pub const AtomicCondition = struct {
193194 waiter.data.notify();
194195 }
195196};
197
198test "Thread.Condition" {
199 if (builtin.single_threaded) {
200 return error.SkipZigTest;
201 }
202
203 const TestContext = struct {
204 cond: *Condition,
205 cond_main: *Condition,
206 mutex: *Mutex,
207 n: *i32,
208 fn worker(ctx: *@This()) void {
209 ctx.mutex.lock();
210 ctx.n.* += 1;
211 ctx.cond_main.signal();
212 ctx.cond.wait(ctx.mutex);
213 ctx.n.* -= 1;
214 ctx.cond_main.signal();
215 ctx.mutex.unlock();
216 }
217 };
218 const num_threads = 3;
219 var threads: [num_threads]std.Thread = undefined;
220 var cond = Condition{};
221 var cond_main = Condition{};
222 var mut = Mutex{};
223 var n: i32 = 0;
224 var ctx = TestContext{ .cond = &cond, .cond_main = &cond_main, .mutex = &mut, .n = &n };
225
226 mut.lock();
227 for (threads) |*t| t.* = try std.Thread.spawn(.{}, TestContext.worker, .{&ctx});
228 cond_main.wait(&mut);
229 while (n < num_threads) cond_main.wait(&mut);
230
231 cond.signal();
232 cond_main.wait(&mut);
233 try testing.expect(n == (num_threads - 1));
234
235 cond.broadcast();
236 while (n > 0) cond_main.wait(&mut);
237 try testing.expect(n == 0);
238
239 for (threads) |t| t.join();
240}
lib/std/Thread/Semaphore.zig+28
......@@ -11,6 +11,8 @@ const Semaphore = @This();
1111const std = @import("../std.zig");
1212const Mutex = std.Thread.Mutex;
1313const Condition = std.Thread.Condition;
14const builtin = @import("builtin");
15const testing = std.testing;
1416
1517pub fn wait(sem: *Semaphore) void {
1618 sem.mutex.lock();
......@@ -31,3 +33,29 @@ pub fn post(sem: *Semaphore) void {
3133 sem.permits += 1;
3234 sem.cond.signal();
3335}
36
37test "Thread.Semaphore" {
38 if (builtin.single_threaded) {
39 return error.SkipZigTest;
40 }
41
42 const TestContext = struct {
43 sem: *Semaphore,
44 n: *i32,
45 fn worker(ctx: *@This()) void {
46 ctx.sem.wait();
47 ctx.n.* += 1;
48 ctx.sem.post();
49 }
50 };
51 const num_threads = 3;
52 var sem = Semaphore{ .permits = 1 };
53 var threads: [num_threads]std.Thread = undefined;
54 var n: i32 = 0;
55 var ctx = TestContext{ .sem = &sem, .n = &n };
56
57 for (threads) |*t| t.* = try std.Thread.spawn(.{}, TestContext.worker, .{&ctx});
58 for (threads) |t| t.join();
59 sem.wait();
60 try testing.expect(n == num_threads);
61}