std.Mutex: integrate with pthreads

When using pthreads for threading, std.Mutex uses pthread_mutex_t as the
implementation. This integrates better with tooling.
This commit is contained in:
Andrew Kelley 2020-12-21 13:15:04 -07:00
parent 6e2622661c
commit 4eb4d26fa1
2 changed files with 49 additions and 0 deletions

View File

@ -316,6 +316,7 @@ pub extern "c" fn dn_expand(
pub const PTHREAD_MUTEX_INITIALIZER = pthread_mutex_t{};
pub extern "c" fn pthread_mutex_lock(mutex: *pthread_mutex_t) c_int;
pub extern "c" fn pthread_mutex_unlock(mutex: *pthread_mutex_t) c_int;
pub extern "c" fn pthread_mutex_trylock(mutex: *pthread_mutex_t) c_int;
pub extern "c" fn pthread_mutex_destroy(mutex: *pthread_mutex_t) c_int;
pub const PTHREAD_COND_INITIALIZER = pthread_cond_t{};

View File

@ -37,6 +37,8 @@ pub const Mutex = if (builtin.single_threaded)
Dummy
else if (builtin.os.tag == .windows)
WindowsMutex
else if (std.Thread.use_pthreads)
PthreadMutex
else if (builtin.link_libc or builtin.os.tag == .linux)
// stack-based version of https://github.com/Amanieu/parking_lot/blob/master/core/src/word_lock.rs
struct {
@ -166,6 +168,52 @@ else if (builtin.link_libc or builtin.os.tag == .linux)
else
SpinLock;
pub const PthreadMutex = struct {
pthread_mutex: std.c.pthread_mutex_t = init,
pub const Held = struct {
mutex: *PthreadMutex,
pub fn release(self: Held) void {
switch (std.c.pthread_mutex_unlock(&self.mutex.pthread_mutex)) {
0 => return,
std.c.EINVAL => unreachable,
std.c.EAGAIN => unreachable,
std.c.EPERM => unreachable,
else => unreachable,
}
}
};
/// Create a new mutex in unlocked state.
pub const init = std.c.PTHREAD_MUTEX_INITIALIZER;
/// Try to acquire the mutex without blocking. Returns null if
/// the mutex is unavailable. Otherwise returns Held. Call
/// release on Held.
pub fn tryAcquire(self: *PthreadMutex) ?Held {
if (std.c.pthread_mutex_trylock(&self.pthread_mutex) == 0) {
return Held{ .mutex = self };
} else {
return null;
}
}
/// Acquire the mutex. Will deadlock if the mutex is already
/// held by the calling thread.
pub fn acquire(self: *PthreadMutex) Held {
switch (std.c.pthread_mutex_lock(&self.pthread_mutex)) {
0 => return Held{ .mutex = self },
std.c.EINVAL => unreachable,
std.c.EBUSY => unreachable,
std.c.EAGAIN => unreachable,
std.c.EDEADLK => unreachable,
std.c.EPERM => unreachable,
else => unreachable,
}
}
};
/// This has the sematics as `Mutex`, however it does not actually do any
/// synchronization. Operations are safety-checked no-ops.
pub const Dummy = struct {