| ... | @@ -37,6 +37,8 @@ pub const Mutex = if (builtin.single_threaded) | ... | @@ -37,6 +37,8 @@ pub const Mutex = if (builtin.single_threaded) |
| 37 | Dummy | 37 | Dummy |
| 38 | else if (builtin.os.tag == .windows) | 38 | else if (builtin.os.tag == .windows) |
| 39 | WindowsMutex | 39 | WindowsMutex |
| | 40 | else if (std.Thread.use_pthreads) |
| | 41 | PthreadMutex |
| 40 | else if (builtin.link_libc or builtin.os.tag == .linux) | 42 | else if (builtin.link_libc or builtin.os.tag == .linux) |
| 41 | // stack-based version of https://github.com/Amanieu/parking_lot/blob/master/core/src/word_lock.rs | 43 | // stack-based version of https://github.com/Amanieu/parking_lot/blob/master/core/src/word_lock.rs |
| 42 | struct { | 44 | struct { |
| ... | @@ -166,6 +168,52 @@ else if (builtin.link_libc or builtin.os.tag == .linux) | ... | @@ -166,6 +168,52 @@ else if (builtin.link_libc or builtin.os.tag == .linux) |
| 166 | else | 168 | else |
| 167 | SpinLock; | 169 | SpinLock; |
| 168 | | 170 | |
| | 171 | pub 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 | |
| 169 | /// This has the sematics as `Mutex`, however it does not actually do any | 217 | /// This has the sematics as `Mutex`, however it does not actually do any |
| 170 | /// synchronization. Operations are safety-checked no-ops. | 218 | /// synchronization. Operations are safety-checked no-ops. |
| 171 | pub const Dummy = struct { | 219 | pub const Dummy = struct { |