1const std = @import("../std.zig");
2const RwLock = std.event.RwLock;
3
4/// Thread-safe async/await RW lock that protects one piece of data.
5/// Functions which are waiting for the lock are suspended, and
6/// are resumed when the lock is released, in order.
7pub fn RwLocked(comptime T: type) type {
8    return struct {
9        lock: RwLock,
10        locked_data: T,
11
12        const Self = @This();
13
14        pub const HeldReadLock = struct {
15            value: *const T,
16            held: RwLock.HeldRead,
17
18            pub fn release(self: HeldReadLock) void {
19                self.held.release();
20            }
21        };
22
23        pub const HeldWriteLock = struct {
24            value: *T,
25            held: RwLock.HeldWrite,
26
27            pub fn release(self: HeldWriteLock) void {
28                self.held.release();
29            }
30        };
31
32        pub fn init(data: T) Self {
33            return Self{
34                .lock = RwLock.init(),
35                .locked_data = data,
36            };
37        }
38
39        pub fn deinit(self: *Self) void {
40            self.lock.deinit();
41        }
42
43        pub fn acquireRead(self: *Self) callconv(.Async) HeldReadLock {
44            return HeldReadLock{
45                .held = self.lock.acquireRead(),
46                .value = &self.locked_data,
47            };
48        }
49
50        pub fn acquireWrite(self: *Self) callconv(.Async) HeldWriteLock {
51            return HeldWriteLock{
52                .held = self.lock.acquireWrite(),
53                .value = &self.locked_data,
54            };
55        }
56    };
57}
58