| author | |
| committer | |
| log | 9c36ae46260cc680663ba3347da06e5e2a16590b |
| tree | 8bd50fbf997c799c6cd4e644641c8a0d48715fe8 |
| parent | 924eb08b613e3333419512f4de02b167aba9336d |
| parent | bdd1a9e48c7a1a09cf0a3b7c0d5be6547f8ef1aa |
| signature |
Add tests for std.Thread.Condition and std.Thread.Semaphore2 files changed, 73 insertions(+), 0 deletions(-)
lib/std/Thread/Condition.zig+45| ... | @@ -11,6 +11,7 @@ const windows = std.os.windows; | ... | @@ -11,6 +11,7 @@ const windows = std.os.windows; |
| 11 | const linux = std.os.linux; | 11 | const linux = std.os.linux; |
| 12 | const Mutex = std.Thread.Mutex; | 12 | const Mutex = std.Thread.Mutex; |
| 13 | const assert = std.debug.assert; | 13 | const assert = std.debug.assert; |
| 14 | const testing = std.testing; | ||
| 14 | 15 | ||
| 15 | pub fn wait(cond: *Condition, mutex: *Mutex) void { | 16 | pub fn wait(cond: *Condition, mutex: *Mutex) void { |
| 16 | cond.impl.wait(mutex); | 17 | cond.impl.wait(mutex); |
| ... | @@ -193,3 +194,47 @@ pub const AtomicCondition = struct { | ... | @@ -193,3 +194,47 @@ pub const AtomicCondition = struct { |
| 193 | waiter.data.notify(); | 194 | waiter.data.notify(); |
| 194 | } | 195 | } |
| 195 | }; | 196 | }; |
| 197 | |||
| 198 | test "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(); | ... | @@ -11,6 +11,8 @@ const Semaphore = @This(); |
| 11 | const std = @import("../std.zig"); | 11 | const std = @import("../std.zig"); |
| 12 | const Mutex = std.Thread.Mutex; | 12 | const Mutex = std.Thread.Mutex; |
| 13 | const Condition = std.Thread.Condition; | 13 | const Condition = std.Thread.Condition; |
| 14 | const builtin = @import("builtin"); | ||
| 15 | const testing = std.testing; | ||
| 14 | 16 | ||
| 15 | pub fn wait(sem: *Semaphore) void { | 17 | pub fn wait(sem: *Semaphore) void { |
| 16 | sem.mutex.lock(); | 18 | sem.mutex.lock(); |
| ... | @@ -31,3 +33,29 @@ pub fn post(sem: *Semaphore) void { | ... | @@ -31,3 +33,29 @@ pub fn post(sem: *Semaphore) void { |
| 31 | sem.permits += 1; | 33 | sem.permits += 1; |
| 32 | sem.cond.signal(); | 34 | sem.cond.signal(); |
| 33 | } | 35 | } |
| 36 | |||
| 37 | test "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 | } |