Skip to content

Commit a1e41dc

Browse files
committed
Implement 'std::mutex'
1 parent 8162673 commit a1e41dc

3 files changed

Lines changed: 129 additions & 1 deletion

File tree

specifications/std/thread.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,62 @@ void main {
131131
132132
// data == 8
133133
}
134-
```
134+
```
135+
136+
## std::mutex
137+
138+
Blocking mutex implementation that uses kernel-level synchronization primitives:
139+
- On Unix: uses pthread mutex (futex-based blocking)
140+
- On Windows: uses CRITICAL_SECTION
141+
142+
This is more efficient than spinlock for longer-held locks, as waiting threads are put to sleep instead of spinning.
143+
144+
### lock
145+
146+
Acquires the mutex, blocking if it's already held by another thread.
147+
148+
### unlock
149+
150+
Releases the mutex, allowing other waiting threads to acquire it.
151+
152+
### trylock
153+
154+
Attempts to acquire the mutex without blocking. Returns 0 on success, non-zero if the mutex is already locked.
155+
156+
### destroy
157+
158+
Destroys the mutex and releases associated resources. Should be called when the mutex is no longer needed.
159+
160+
Example:
161+
162+
```d
163+
import <std/io> <std/thread>
164+
165+
int counter = 0;
166+
std::mutex mtx;
167+
168+
int increment(char* arg) {
169+
for (int i=0; i<10000; i++) {
170+
mtx.lock();
171+
counter += 1;
172+
mtx.unlock();
173+
}
174+
}
175+
176+
void main {
177+
std::thread t1 = std::thread();
178+
std::thread t2 = std::thread();
179+
std::thread t3 = std::thread();
180+
181+
t1.run(increment, null);
182+
t2.run(increment, null);
183+
t3.run(increment, null);
184+
185+
t1.join();
186+
t2.join();
187+
t3.join();
188+
189+
mtx.destroy();
190+
191+
std::println("Counter: ", counter);
192+
}

std/pthread.rave

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
1111
int __align;
1212
}
1313

14+
struct mutexattr {
15+
char[40] __data;
16+
}
17+
1418
struct mutex {
1519
char[40] __data;
1620
}
@@ -24,6 +28,10 @@ with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
2428
int __align;
2529
}
2630

31+
struct mutexattr {
32+
char[24] __data;
33+
}
34+
2735
struct mutex {
2836
char[24] __data;
2937
}
@@ -37,4 +45,11 @@ namespace pthread {
3745
extern(linkname: "pthread_exit") void exit(char* retVal);
3846
extern(linkname: "pthread_cancel") int cancel(ulong thread);
3947
extern(linkname: "pthread_detach") int detach(ulong thread);
48+
49+
// Mutex functions
50+
extern(linkname: "pthread_mutex_init") int mutex_init(pthread::mutex* mutex, pthread::mutexattr* attr);
51+
extern(linkname: "pthread_mutex_lock") int mutex_lock(pthread::mutex* mutex);
52+
extern(linkname: "pthread_mutex_unlock") int mutex_unlock(pthread::mutex* mutex);
53+
extern(linkname: "pthread_mutex_destroy") int mutex_destroy(pthread::mutex* mutex);
54+
extern(linkname: "pthread_mutex_trylock") int mutex_trylock(pthread::mutex* mutex);
4055
}

std/thread.rave

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,59 @@ namespace std {
104104

105105
(inline) void unlock => std::thread::spinlock::unlock(this.&value);
106106
}
107+
}
108+
109+
// Blocking mutex implementation (not spinning)
110+
@if (__RAVE_OS != "WINDOWS") {
111+
namespace std {
112+
struct mutex {
113+
pthread::mutex __mutex;
114+
115+
std::mutex this {
116+
pthread::mutex_init(return.&__mutex, cast(pthread::mutexattr*)null);
117+
}
118+
119+
(inline) void lock => pthread::mutex_lock(this.&__mutex);
120+
121+
(inline) void unlock => pthread::mutex_unlock(this.&__mutex);
122+
123+
(inline) int trylock => pthread::mutex_trylock(this.&__mutex);
124+
125+
(inline) void destroy => pthread::mutex_destroy(this.&__mutex);
126+
}
127+
}
128+
}
129+
@else {
130+
namespace std {
131+
// Windows CRITICAL_SECTION provides blocking mutex
132+
namespace thread {
133+
extern(linkname: "InitializeCriticalSection") void __InitCriticalSection(char* cs);
134+
extern(linkname: "EnterCriticalSection") void __EnterCriticalSection(char* cs);
135+
extern(linkname: "LeaveCriticalSection") void __LeaveCriticalSection(char* cs);
136+
extern(linkname: "DeleteCriticalSection") void __DeleteCriticalSection(char* cs);
137+
extern(linkname: "TryEnterCriticalSection") int __TryEnterCriticalSection(char* cs);
138+
}
139+
140+
struct mutex {
141+
// CRITICAL_SECTION structure size (platform-dependent)
142+
@if (__RAVE_PLATFORM == "X86_64") {
143+
char[40] __cs;
144+
}
145+
@else {
146+
char[24] __cs;
147+
}
148+
149+
std::mutex this {
150+
std::thread::__InitCriticalSection(return.&__cs);
151+
}
152+
153+
(inline) void lock => std::thread::__EnterCriticalSection(this.&__cs);
154+
155+
(inline) void unlock => std::thread::__LeaveCriticalSection(this.&__cs);
156+
157+
(inline) int trylock => std::thread::__TryEnterCriticalSection(this.&__cs);
158+
159+
(inline) void destroy => std::thread::__DeleteCriticalSection(this.&__cs);
160+
}
161+
}
107162
}

0 commit comments

Comments
 (0)