| ... | @@ -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 | } |