commit
6ea193946d
@ -7,11 +7,28 @@ const testing = std.testing;
|
|||||||
const SpinLock = std.SpinLock;
|
const SpinLock = std.SpinLock;
|
||||||
const ResetEvent = std.ResetEvent;
|
const ResetEvent = std.ResetEvent;
|
||||||
|
|
||||||
/// Lock may be held only once. If the same thread
|
/// Lock may be held only once. If the same thread tries to acquire
|
||||||
/// tries to acquire the same mutex twice, it deadlocks.
|
/// the same mutex twice, it deadlocks. This type supports static
|
||||||
/// This type supports static initialization and is at most `@sizeOf(usize)` in size.
|
/// initialization and is at most `@sizeOf(usize)` in size. When an
|
||||||
/// When an application is built in single threaded release mode, all the functions are
|
/// application is built in single threaded release mode, all the
|
||||||
/// no-ops. In single threaded debug mode, there is deadlock detection.
|
/// functions are no-ops. In single threaded debug mode, there is
|
||||||
|
/// deadlock detection.
|
||||||
|
///
|
||||||
|
/// Example usage:
|
||||||
|
/// var m = Mutex.init();
|
||||||
|
/// defer m.deinit();
|
||||||
|
///
|
||||||
|
/// const lock = m.acquire();
|
||||||
|
/// defer lock.release();
|
||||||
|
/// ... critical code
|
||||||
|
///
|
||||||
|
/// Non-blocking:
|
||||||
|
/// if (m.tryAcquire) |lock| {
|
||||||
|
/// defer lock.release();
|
||||||
|
/// // ... critical section
|
||||||
|
/// } else {
|
||||||
|
/// // ... lock not acquired
|
||||||
|
/// }
|
||||||
pub const Mutex = if (builtin.single_threaded)
|
pub const Mutex = if (builtin.single_threaded)
|
||||||
struct {
|
struct {
|
||||||
lock: @TypeOf(lock_init),
|
lock: @TypeOf(lock_init),
|
||||||
@ -28,14 +45,20 @@ pub const Mutex = if (builtin.single_threaded)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Create a new mutex in unlocked state.
|
||||||
pub fn init() Mutex {
|
pub fn init() Mutex {
|
||||||
return Mutex{ .lock = lock_init };
|
return Mutex{ .lock = lock_init };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Free a mutex created with init. Calling this while the
|
||||||
|
/// mutex is held is illegal behavior.
|
||||||
pub fn deinit(self: *Mutex) void {
|
pub fn deinit(self: *Mutex) void {
|
||||||
self.* = undefined;
|
self.* = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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: *Mutex) ?Held {
|
pub fn tryAcquire(self: *Mutex) ?Held {
|
||||||
if (std.debug.runtime_safety) {
|
if (std.debug.runtime_safety) {
|
||||||
if (self.lock) return null;
|
if (self.lock) return null;
|
||||||
@ -44,6 +67,8 @@ pub const Mutex = if (builtin.single_threaded)
|
|||||||
return Held{ .mutex = self };
|
return Held{ .mutex = self };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Acquire the mutex. Will deadlock if the mutex is already
|
||||||
|
/// held by the calling thread.
|
||||||
pub fn acquire(self: *Mutex) Held {
|
pub fn acquire(self: *Mutex) Held {
|
||||||
return self.tryAcquire() orelse @panic("deadlock detected");
|
return self.tryAcquire() orelse @panic("deadlock detected");
|
||||||
}
|
}
|
||||||
@ -220,9 +245,12 @@ else if (builtin.link_libc or builtin.os == .linux)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returned when the lock is acquired. Call release to
|
||||||
|
/// release.
|
||||||
pub const Held = struct {
|
pub const Held = struct {
|
||||||
mutex: *Mutex,
|
mutex: *Mutex,
|
||||||
|
|
||||||
|
/// Release the held lock.
|
||||||
pub fn release(self: Held) void {
|
pub fn release(self: Held) void {
|
||||||
// first, remove the lock bit so another possibly parallel acquire() can succeed.
|
// first, remove the lock bit so another possibly parallel acquire() can succeed.
|
||||||
// use .Sub since it can be usually compiled down more efficiency
|
// use .Sub since it can be usually compiled down more efficiency
|
||||||
|
Loading…
x
Reference in New Issue
Block a user