authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-21 13:15:04-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-23 13:36:21-08:00
log4eb4d26fa14524652bed69325eb491f39701d995
treeea2282b63ccd6d8785a74fa8ceedb81aab6a90e6
parent6e2622661cdf9dd48cf962e5d6902324b15468c3

std.Mutex: integrate with pthreads

When using pthreads for threading, std.Mutex uses pthread_mutex_t as the implementation. This integrates better with tooling.

2 files changed, 49 insertions(+), 0 deletions(-)

lib/std/c.zig+1
......@@ -316,6 +316,7 @@ pub extern "c" fn dn_expand(
316316pub const PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{};
317317pub extern "c" fn pthread_mutex_lock(mutex: *pthread_mutex_t) c_int;
318318pub extern "c" fn pthread_mutex_unlock(mutex: *pthread_mutex_t) c_int;
319pub extern "c" fn pthread_mutex_trylock(mutex: *pthread_mutex_t) c_int;
319320pub extern "c" fn pthread_mutex_destroy(mutex: *pthread_mutex_t) c_int;
320321
321322pub const PTHREAD_COND_INITIALIZER = pthread_cond_t{};
lib/std/mutex.zig+48
......@@ -37,6 +37,8 @@ pub const Mutex = if (builtin.single_threaded)
3737 Dummy
3838else if (builtin.os.tag == .windows)
3939 WindowsMutex
40else if (std.Thread.use_pthreads)
41 PthreadMutex
4042else if (builtin.link_libc or builtin.os.tag == .linux)
4143 // stack-based version of https://github.com/Amanieu/parking_lot/blob/master/core/src/word_lock.rs
4244 struct {
......@@ -166,6 +168,52 @@ else if (builtin.link_libc or builtin.os.tag == .linux)
166168else
167169 SpinLock;
168170
171pub const PthreadMutex = struct {
172 pthread_mutex: std.c.pthread_mutex_t = init,
173
174 pub const Held = struct {
175 mutex: *PthreadMutex,
176
177 pub fn release(self: Held) void {
178 switch (std.c.pthread_mutex_unlock(&self.mutex.pthread_mutex)) {
179 0 => return,
180 std.c.EINVAL => unreachable,
181 std.c.EAGAIN => unreachable,
182 std.c.EPERM => unreachable,
183 else => unreachable,
184 }
185 }
186 };
187
188 /// Create a new mutex in unlocked state.
189 pub const init = std.c.PTHREAD_MUTEX_INITIALIZER;
190
191 /// Try to acquire the mutex without blocking. Returns null if
192 /// the mutex is unavailable. Otherwise returns Held. Call
193 /// release on Held.
194 pub fn tryAcquire(self: *PthreadMutex) ?Held {
195 if (std.c.pthread_mutex_trylock(&self.pthread_mutex) == 0) {
196 return Held{ .mutex = self };
197 } else {
198 return null;
199 }
200 }
201
202 /// Acquire the mutex. Will deadlock if the mutex is already
203 /// held by the calling thread.
204 pub fn acquire(self: *PthreadMutex) Held {
205 switch (std.c.pthread_mutex_lock(&self.pthread_mutex)) {
206 0 => return Held{ .mutex = self },
207 std.c.EINVAL => unreachable,
208 std.c.EBUSY => unreachable,
209 std.c.EAGAIN => unreachable,
210 std.c.EDEADLK => unreachable,
211 std.c.EPERM => unreachable,
212 else => unreachable,
213 }
214 }
215};
216
169217/// This has the sematics as `Mutex`, however it does not actually do any
170218/// synchronization. Operations are safety-checked no-ops.
171219pub const Dummy = struct {