Skip to content

Commit

Permalink
Add mutex implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
MrSmith33 committed Aug 24, 2024
1 parent 5d67ed5 commit ad35618
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
1 change: 1 addition & 0 deletions build/builder.d
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ immutable TargetAlias[] targetAliases = [
{"a64", "arm64"},
{"aarch64", "arm64"},
{"x86_64", "x64"},
{"amd64", "x64"},
];

void printOptions() {
Expand Down
97 changes: 97 additions & 0 deletions source/vox/lib/mutex.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/// Copyright: Copyright (c) 2024 Andrey Penechko
/// License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0)
/// Authors: Andrey Penechko
module vox.lib.mutex;

import vox.lib.atomic;
import vox.lib.error : panic;
import vox.lib.types;

@nogc nothrow @system:

struct Mutex {
@nogc nothrow @system:

enum State : u32 { unlocked, locked, contested };
State state;

bool tryLock() {
return cas!(MemoryOrder.acq, MemoryOrder.acq)(&state, State.unlocked, State.locked);
}

void lock() {
if (tryLock()) return;
while (atomicExchange(&state, State.contested) != State.unlocked) {
wait(&state, State.contested);
}
}

void unlock() {
if (atomicExchange!(MemoryOrder.rel)(&state, State.unlocked) == State.contested) {
notifyOne(&state);
}
}
}

struct RecursiveMutex {
import vox.lib.thread;
enum State : u32 { unlocked, locked, contested };
State state;
u32 counter;
Tid owner;

private bool tryLockState() {
return cas!(MemoryOrder.acq, MemoryOrder.acq)(&state, State.unlocked, State.locked);
}

bool tryLock(Tid tid) {
if(tid == Tid(0)) panic("tid == 0");
if (owner == tid) {
// recursion
assert(counter > 0);
++counter;
return true;
}
if (tryLockState()) {
assert(owner == Tid(0));
assert(counter == 0);
owner = tid;
++counter;
return true;
}
return false;
}

void lock(Tid tid) {
if(tid == Tid(0)) panic("tid == 0");
if (owner == tid) {
// recursion
assert(counter > 0);
++counter;
return;
}

if (tryLockState()) goto first_lock;

while (atomicExchange(&state, State.contested) != State.unlocked) {
wait(&state, State.contested);
}

first_lock:

assert(owner == Tid(0));
assert(counter == 0);
owner = tid;
++counter;
}

void unlock() {
--counter;
if (counter == 0) {
owner = Tid(0);
if (atomicExchange!(MemoryOrder.rel)(&state, State.unlocked) == State.contested) {
notifyOne(&state);
}
}
}
}

0 comments on commit ad35618

Please # to comment.