| ... | ... | @@ -11,6 +11,7 @@ const windows = std.os.windows; |
| 11 | 11 | const linux = std.os.linux; |
| 12 | 12 | const Mutex = std.Thread.Mutex; |
| 13 | 13 | const assert = std.debug.assert; |
| 14 | const testing = std.testing; |
| 14 | 15 | |
| 15 | 16 | pub fn wait(cond: *Condition, mutex: *Mutex) void { |
| 16 | 17 | cond.impl.wait(mutex); |
| ... | ... | @@ -193,3 +194,47 @@ pub const AtomicCondition = struct { |
| 193 | 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 | } |