authorgravatar for 77312308+billzez@users.noreply.github.combillzez <77312308+billzez@users.noreply.github.com> 2022-02-08 23:35:48-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-11 12:13:51-07:00
logbf6af1963cfb3451b3338d7488ec26f5fb7af0ed
tree2e28c99a0cc4ab4aa4332150b4f8d991bd5e0954
parent45d4e2f8160d8807c353a514332ab49bd8355980

update RwLock to use static initialization (#10838)


2 files changed, 14 insertions(+), 64 deletions(-)

lib/std/Thread.zig+1
...@@ -16,6 +16,7 @@ pub const StaticResetEvent = @import("Thread/StaticResetEvent.zig");...@@ -16,6 +16,7 @@ pub const StaticResetEvent = @import("Thread/StaticResetEvent.zig");
16pub const Mutex = @import("Thread/Mutex.zig");16pub const Mutex = @import("Thread/Mutex.zig");
17pub const Semaphore = @import("Thread/Semaphore.zig");17pub const Semaphore = @import("Thread/Semaphore.zig");
18pub const Condition = @import("Thread/Condition.zig");18pub const Condition = @import("Thread/Condition.zig");
19pub const RwLock = @import("Thread/RwLock.zig");
1920
20pub const use_pthreads = target.os.tag != .windows and target.os.tag != .wasi and builtin.link_libc;21pub const use_pthreads = target.os.tag != .windows and target.os.tag != .wasi and builtin.link_libc;
21const is_gnu = target.abi.isGnu();22const is_gnu = target.abi.isGnu();
lib/std/Thread/RwLock.zig+13-64
...@@ -3,15 +3,12 @@...@@ -3,15 +3,12 @@
3//! This API requires being initialized at runtime, and initialization3//! This API requires being initialized at runtime, and initialization
4//! can fail. Once initialized, the core operations cannot fail.4//! can fail. Once initialized, the core operations cannot fail.
55
6impl: Impl,6impl: Impl = .{},
77
8const RwLock = @This();8const RwLock = @This();
9const std = @import("../std.zig");9const std = @import("../std.zig");
10const builtin = @import("builtin");10const builtin = @import("builtin");
11const assert = std.debug.assert;11const assert = std.debug.assert;
12const Mutex = std.Thread.Mutex;
13const Semaphore = std.Semaphore;
14const CondVar = std.CondVar;
1512
16pub const Impl = if (builtin.single_threaded)13pub const Impl = if (builtin.single_threaded)
17 SingleThreadedRwLock14 SingleThreadedRwLock
...@@ -20,14 +17,6 @@ else if (std.Thread.use_pthreads)...@@ -20,14 +17,6 @@ else if (std.Thread.use_pthreads)
20else17else
21 DefaultRwLock;18 DefaultRwLock;
2219
23pub fn init(rwl: *RwLock) void {
24 return rwl.impl.init();
25}
26
27pub fn deinit(rwl: *RwLock) void {
28 return rwl.impl.deinit();
29}
30
31/// Attempts to obtain exclusive lock ownership.20/// Attempts to obtain exclusive lock ownership.
32/// Returns `true` if the lock is obtained, `false` otherwise.21/// Returns `true` if the lock is obtained, `false` otherwise.
33pub fn tryLock(rwl: *RwLock) bool {22pub fn tryLock(rwl: *RwLock) bool {
...@@ -64,20 +53,8 @@ pub fn unlockShared(rwl: *RwLock) void {...@@ -64,20 +53,8 @@ pub fn unlockShared(rwl: *RwLock) void {
64/// Single-threaded applications use this for deadlock checks in53/// Single-threaded applications use this for deadlock checks in
65/// debug mode, and no-ops in release modes.54/// debug mode, and no-ops in release modes.
66pub const SingleThreadedRwLock = struct {55pub const SingleThreadedRwLock = struct {
67 state: enum { unlocked, locked_exclusive, locked_shared },56 state: enum { unlocked, locked_exclusive, locked_shared } = .unlocked,
68 shared_count: usize,57 shared_count: usize = 0,
69
70 pub fn init(rwl: *SingleThreadedRwLock) void {
71 rwl.* = .{
72 .state = .unlocked,
73 .shared_count = 0,
74 };
75 }
76
77 pub fn deinit(rwl: *SingleThreadedRwLock) void {
78 assert(rwl.state == .unlocked);
79 assert(rwl.shared_count == 0);
80 }
8158
82 /// Attempts to obtain exclusive lock ownership.59 /// Attempts to obtain exclusive lock ownership.
83 /// Returns `true` if the lock is obtained, `false` otherwise.60 /// Returns `true` if the lock is obtained, `false` otherwise.
...@@ -152,55 +129,41 @@ pub const SingleThreadedRwLock = struct {...@@ -152,55 +129,41 @@ pub const SingleThreadedRwLock = struct {
152};129};
153130
154pub const PthreadRwLock = struct {131pub const PthreadRwLock = struct {
155 rwlock: pthread_rwlock_t,132 rwlock: std.c.pthread_rwlock_t = .{},
156
157 pub fn init(rwl: *PthreadRwLock) void {
158 rwl.* = .{ .rwlock = .{} };
159 }
160
161 pub fn deinit(rwl: *PthreadRwLock) void {
162 const safe_rc: std.os.E = switch (builtin.os.tag) {
163 .dragonfly, .netbsd => .AGAIN,
164 else => .SUCCESS,
165 };
166 const rc = std.c.pthread_rwlock_destroy(&rwl.rwlock);
167 assert(rc == .SUCCESS or rc == safe_rc);
168 rwl.* = undefined;
169 }
170133
171 pub fn tryLock(rwl: *PthreadRwLock) bool {134 pub fn tryLock(rwl: *PthreadRwLock) bool {
172 return pthread_rwlock_trywrlock(&rwl.rwlock) == .SUCCESS;135 return std.c.pthread_rwlock_trywrlock(&rwl.rwlock) == .SUCCESS;
173 }136 }
174137
175 pub fn lock(rwl: *PthreadRwLock) void {138 pub fn lock(rwl: *PthreadRwLock) void {
176 const rc = pthread_rwlock_wrlock(&rwl.rwlock);139 const rc = std.c.pthread_rwlock_wrlock(&rwl.rwlock);
177 assert(rc == .SUCCESS);140 assert(rc == .SUCCESS);
178 }141 }
179142
180 pub fn unlock(rwl: *PthreadRwLock) void {143 pub fn unlock(rwl: *PthreadRwLock) void {
181 const rc = pthread_rwlock_unlock(&rwl.rwlock);144 const rc = std.c.pthread_rwlock_unlock(&rwl.rwlock);
182 assert(rc == .SUCCESS);145 assert(rc == .SUCCESS);
183 }146 }
184147
185 pub fn tryLockShared(rwl: *PthreadRwLock) bool {148 pub fn tryLockShared(rwl: *PthreadRwLock) bool {
186 return pthread_rwlock_tryrdlock(&rwl.rwlock) == .SUCCESS;149 return std.c.pthread_rwlock_tryrdlock(&rwl.rwlock) == .SUCCESS;
187 }150 }
188151
189 pub fn lockShared(rwl: *PthreadRwLock) void {152 pub fn lockShared(rwl: *PthreadRwLock) void {
190 const rc = pthread_rwlock_rdlock(&rwl.rwlock);153 const rc = std.c.pthread_rwlock_rdlock(&rwl.rwlock);
191 assert(rc == .SUCCESS);154 assert(rc == .SUCCESS);
192 }155 }
193156
194 pub fn unlockShared(rwl: *PthreadRwLock) void {157 pub fn unlockShared(rwl: *PthreadRwLock) void {
195 const rc = pthread_rwlock_unlock(&rwl.rwlock);158 const rc = std.c.pthread_rwlock_unlock(&rwl.rwlock);
196 assert(rc == .SUCCESS);159 assert(rc == .SUCCESS);
197 }160 }
198};161};
199162
200pub const DefaultRwLock = struct {163pub const DefaultRwLock = struct {
201 state: usize,164 state: usize = 0,
202 mutex: Mutex,165 mutex: std.Thread.Mutex = .{},
203 semaphore: Semaphore,166 semaphore: std.Thread.Semaphore = .{},
204167
205 const IS_WRITING: usize = 1;168 const IS_WRITING: usize = 1;
206 const WRITER: usize = 1 << 1;169 const WRITER: usize = 1 << 1;
...@@ -209,20 +172,6 @@ pub const DefaultRwLock = struct {...@@ -209,20 +172,6 @@ pub const DefaultRwLock = struct {
209 const READER_MASK: usize = std.math.maxInt(Count) << @ctz(usize, READER);172 const READER_MASK: usize = std.math.maxInt(Count) << @ctz(usize, READER);
210 const Count = std.meta.Int(.unsigned, @divFloor(std.meta.bitCount(usize) - 1, 2));173 const Count = std.meta.Int(.unsigned, @divFloor(std.meta.bitCount(usize) - 1, 2));
211174
212 pub fn init(rwl: *DefaultRwLock) void {
213 rwl.* = .{
214 .state = 0,
215 .mutex = Mutex.init(),
216 .semaphore = Semaphore.init(0),
217 };
218 }
219
220 pub fn deinit(rwl: *DefaultRwLock) void {
221 rwl.semaphore.deinit();
222 rwl.mutex.deinit();
223 rwl.* = undefined;
224 }
225
226 pub fn tryLock(rwl: *DefaultRwLock) bool {175 pub fn tryLock(rwl: *DefaultRwLock) bool {
227 if (rwl.mutex.tryLock()) {176 if (rwl.mutex.tryLock()) {
228 const state = @atomicLoad(usize, &rwl.state, .SeqCst);177 const state = @atomicLoad(usize, &rwl.state, .SeqCst);