From d0de9c2abfa3785d29fdb66a97e0e2e57d4ff33c Mon Sep 17 00:00:00 2001 From: dimgigov Date: Fri, 5 Jun 2026 22:30:44 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20Std::Sync=20=E2=80=94=20Mutex=20and=20R?= =?UTF-8?q?wLock=20primitives?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add bux_mutex_* and bux_rwlock_* C runtime functions - Add library/std/Sync.bux with Mutex and RwLock wrappers - Add examples/sync.bux — threaded counter with Mutex - Update docs/Stdlib.md with Sync section and example - Update README.md feature table --- README.md | 4 +-- docs/Stdlib.md | 66 ++++++++++++++++++++++++++++++++++++ examples/sync.bux | 35 ++++++++++++++++++++ library/runtime/runtime.c | 70 +++++++++++++++++++++++++++++++++++++++ library/std/Sync.bux | 58 ++++++++++++++++++++++++++++++++ 5 files changed, 231 insertions(+), 2 deletions(-) create mode 100644 examples/sync.bux create mode 100644 library/std/Sync.bux diff --git a/README.md b/README.md index 8e13aed..45221fc 100644 --- a/README.md +++ b/README.md @@ -188,12 +188,12 @@ func Main() -> int { | **Methods** | `extend` blocks for struct methods | | **Interfaces** | `interface` + `extend` for trait-like behavior | | **Error Handling** | `Result`, `Option`, and the `?` operator | -| **Standard Library** | `Io`, `Array`, `String`, `Map`, `Fs`, `Mem`, `Set`, `Path`, `Math`, `Task`, `Channel`, `Os`, `Time`, `Process` | +| **Standard Library** | `Io`, `Array`, `String`, `Map`, `Fs`, `Mem`, `Set`, `Path`, `Math`, `Task`, `Channel`, `Sync`, `Os`, `Time`, `Process` | | **Backend** | C transpiler (self-hosting + bootstrap) | | **Strings** | Raw multi-line backtick strings (`...`), C-string interop | | **Gradual Ownership** | `@[Checked]` + `&T`/`&mut T` borrow checking | | **Async/Await** | `async func`, `spawn`, `.await` with stackful coroutines | -| **Concurrency** | `Task`/`Channel` (pthread-based), `bux_async_yield`/`spawn` | +| **Concurrency** | `Task`/`Channel`/`Sync` (pthread-based), `bux_async_yield`/`spawn` | | **CTFE** | `const func` — compile-time function execution | | **Trait Bounds** | `func Max(a: T, b: T) -> T` | | **Package Manager** | `bux add`, `bux install`, `bux.lock`, path + git deps | diff --git a/docs/Stdlib.md b/docs/Stdlib.md index 28287d8..71e7e5a 100644 --- a/docs/Stdlib.md +++ b/docs/Stdlib.md @@ -447,6 +447,72 @@ func Main() -> int { --- +## Std::Sync + +Synchronization primitives: `Mutex` and `RwLock`. + +### Types +```bux +struct Mutex { + handle: *void; +} + +struct RwLock { + handle: *void; +} +``` + +### Functions + +| Function | Signature | Description | +|----------|-----------|-------------| +| `Mutex_New` | `func Mutex_New() -> Mutex` | Create a new mutex | +| `Mutex_Lock` | `func Mutex_Lock(m: *Mutex)` | Acquire lock (blocks) | +| `Mutex_Unlock` | `func Mutex_Unlock(m: *Mutex)` | Release lock | +| `Mutex_Free` | `func Mutex_Free(m: *Mutex)` | Destroy mutex | +| `RwLock_New` | `func RwLock_New() -> RwLock` | Create a new read-write lock | +| `RwLock_ReadLock` | `func RwLock_ReadLock(rw: *RwLock)` | Acquire read lock (shared) | +| `RwLock_WriteLock` | `func RwLock_WriteLock(rw: *RwLock)` | Acquire write lock (exclusive) | +| `RwLock_Unlock` | `func RwLock_Unlock(rw: *RwLock)` | Release read or write lock | +| `RwLock_Free` | `func RwLock_Free(rw: *RwLock)` | Destroy rwlock | + +### Example +```bux +import Std::Io::{PrintLine, PrintInt}; +import Std::Task::{Task_Join, TaskHandle}; +import Std::Sync::{Mutex, Mutex_New, Mutex_Lock, Mutex_Unlock}; + +struct Counter { + value: int; + mtx: Mutex; +} + +func Incrementer(arg: *void) -> *void { + let c: *Counter = arg as *Counter; + var i: int = 0; + while i < 100000 { + Mutex_Lock(&c.mtx); + c.value = c.value + 1; + Mutex_Unlock(&c.mtx); + i = i + 1; + } + return null; +} + +func Main() -> int { + var counter: Counter = Counter { value: 0, mtx: Mutex_New() }; + let a: *void = spawn Incrementer(&counter); + let b: *void = spawn Incrementer(&counter); + Task_Join(TaskHandle { handle: a }); + Task_Join(TaskHandle { handle: b }); + PrintLine("Counter:"); + PrintInt(counter.value); + return 0; +} +``` + +--- + ## Std::Channel Generic channel for thread communication over pthread mutex/cond. diff --git a/examples/sync.bux b/examples/sync.bux new file mode 100644 index 0000000..265ff26 --- /dev/null +++ b/examples/sync.bux @@ -0,0 +1,35 @@ +import Std::Io::{PrintLine, PrintInt}; +import Std::Task::{Task_Join, TaskHandle}; +import Std::Sync::{Mutex, Mutex_New, Mutex_Lock, Mutex_Unlock}; + +struct Counter { + value: int; + mtx: Mutex; +} + +func Incrementer(arg: *void) -> *void { + let c: *Counter = arg as *Counter; + var i: int = 0; + while i < 100000 { + Mutex_Lock(&c.mtx); + c.value = c.value + 1; + Mutex_Unlock(&c.mtx); + i = i + 1; + } + return null; +} + +func Main() -> int { + var counter: Counter = Counter { value: 0, mtx: Mutex_New() }; + + let a: *void = spawn Incrementer(&counter); + let b: *void = spawn Incrementer(&counter); + + Task_Join(TaskHandle { handle: a }); + Task_Join(TaskHandle { handle: b }); + + PrintLine("Counter:"); + PrintInt(counter.value); + PrintLine(""); + return 0; +} diff --git a/library/runtime/runtime.c b/library/runtime/runtime.c index 4213a89..1da07e3 100644 --- a/library/runtime/runtime.c +++ b/library/runtime/runtime.c @@ -876,6 +876,76 @@ void bux_channel_free(void* handle) { free(ch); } +/* ============================================================================ + * Synchronization primitives (Mutex, RwLock) + * ============================================================================ */ + +typedef struct bux_mutex { + pthread_mutex_t mtx; +} bux_mutex_t; + +typedef struct bux_rwlock { + pthread_rwlock_t rwl; +} bux_rwlock_t; + +void* bux_mutex_new(void) { + bux_mutex_t* m = (bux_mutex_t*)malloc(sizeof(bux_mutex_t)); + if (!m) return NULL; + pthread_mutex_init(&m->mtx, NULL); + return m; +} + +void bux_mutex_lock(void* handle) { + if (!handle) return; + bux_mutex_t* m = (bux_mutex_t*)handle; + pthread_mutex_lock(&m->mtx); +} + +void bux_mutex_unlock(void* handle) { + if (!handle) return; + bux_mutex_t* m = (bux_mutex_t*)handle; + pthread_mutex_unlock(&m->mtx); +} + +void bux_mutex_free(void* handle) { + if (!handle) return; + bux_mutex_t* m = (bux_mutex_t*)handle; + pthread_mutex_destroy(&m->mtx); + free(m); +} + +void* bux_rwlock_new(void) { + bux_rwlock_t* rw = (bux_rwlock_t*)malloc(sizeof(bux_rwlock_t)); + if (!rw) return NULL; + pthread_rwlock_init(&rw->rwl, NULL); + return rw; +} + +void bux_rwlock_rdlock(void* handle) { + if (!handle) return; + bux_rwlock_t* rw = (bux_rwlock_t*)handle; + pthread_rwlock_rdlock(&rw->rwl); +} + +void bux_rwlock_wrlock(void* handle) { + if (!handle) return; + bux_rwlock_t* rw = (bux_rwlock_t*)handle; + pthread_rwlock_wrlock(&rw->rwl); +} + +void bux_rwlock_unlock(void* handle) { + if (!handle) return; + bux_rwlock_t* rw = (bux_rwlock_t*)handle; + pthread_rwlock_unlock(&rw->rwl); +} + +void bux_rwlock_free(void* handle) { + if (!handle) return; + bux_rwlock_t* rw = (bux_rwlock_t*)handle; + pthread_rwlock_destroy(&rw->rwl); + free(rw); +} + /* ============================================================================ * Stackful Coroutines + Async Scheduler (Phase 8.3 true async) * ============================================================================ */ diff --git a/library/std/Sync.bux b/library/std/Sync.bux new file mode 100644 index 0000000..22c935c --- /dev/null +++ b/library/std/Sync.bux @@ -0,0 +1,58 @@ +module Std::Sync { + +extern func bux_mutex_new() -> *void; +extern func bux_mutex_lock(handle: *void); +extern func bux_mutex_unlock(handle: *void); +extern func bux_mutex_free(handle: *void); + +extern func bux_rwlock_new() -> *void; +extern func bux_rwlock_rdlock(handle: *void); +extern func bux_rwlock_wrlock(handle: *void); +extern func bux_rwlock_unlock(handle: *void); +extern func bux_rwlock_free(handle: *void); + +struct Mutex { + handle: *void; +} + +struct RwLock { + handle: *void; +} + +func Mutex_New() -> Mutex { + return Mutex { handle: bux_mutex_new() }; +} + +func Mutex_Lock(m: *Mutex) { + bux_mutex_lock(m.handle); +} + +func Mutex_Unlock(m: *Mutex) { + bux_mutex_unlock(m.handle); +} + +func Mutex_Free(m: *Mutex) { + bux_mutex_free(m.handle); +} + +func RwLock_New() -> RwLock { + return RwLock { handle: bux_rwlock_new() }; +} + +func RwLock_ReadLock(rw: *RwLock) { + bux_rwlock_rdlock(rw.handle); +} + +func RwLock_WriteLock(rw: *RwLock) { + bux_rwlock_wrlock(rw.handle); +} + +func RwLock_Unlock(rw: *RwLock) { + bux_rwlock_unlock(rw.handle); +} + +func RwLock_Free(rw: *RwLock) { + bux_rwlock_free(rw.handle); +} + +}