From f1fe41854314186419190896199809eb319b71ae Mon Sep 17 00:00:00 2001 From: mertcandav Date: Sun, 19 Jan 2025 02:02:25 +0300 Subject: [PATCH] std/sync/atomic: rehandle atomics --- std/runtime/atomic.jule | 49 ++++- std/sync/atomic/atomic.jule | 347 +++++++++++++++++++++++++++++++----- 2 files changed, 344 insertions(+), 52 deletions(-) diff --git a/std/runtime/atomic.jule b/std/runtime/atomic.jule index a8a381a8f..d96997a7b 100644 --- a/std/runtime/atomic.jule +++ b/std/runtime/atomic.jule @@ -28,14 +28,44 @@ cpp unsafe fn __atomic_fetch_add[T](*unsafe, T, atomicMemoryOrder): T // Atomically stores new value to p with memory order mo, and returns the old value. fn atomicSwap[T](mut &p: T, new: T, mo: atomicMemoryOrder): (old: T) { - let mut tmp: T - unsafe { cpp.__atomic_exchange[T](&p, &new, &tmp, mo) } - ret tmp + ret atomicSwapZ(p, new, mo) } // Atomically reads value of the p with memory order mo and returns. fn atomicLoad[T](&p: T, mo: atomicMemoryOrder): T { - let mut tmp: T + ret atomicLoadZ[T, T](p, mo) +} + +// Atomically reads value of the p and compares it with old. +// If comparison results with true, it atomically stores new value into p. +// In every case, it will use memory order mo. +// Reports whether swap succeeded. +fn atomicCompareAndSwap[T](mut &p: T, old: T, new: T, mo: atomicMemoryOrder): (swapped: bool) { + ret atomicCompareAndSwapZ(p, old, new, mo) +} + +// Atomically adds delta to p with memory order mo and returns the new value. +fn atomicAdd[T](mut &p: T, delta: T, mo: atomicMemoryOrder): (new: T) { + ret atomicAddZ(p, delta, mo) +} + +// Atomically stores new value to p with memory order mo. +fn atomicStore[T](mut &p: T, val: T, mo: atomicMemoryOrder) { + atomicStoreZ(p, val, mo) +} + +// Atomically stores new value to p with memory order mo, and returns the old value. +// T1 is a base pointer type, T2 is the output type. +fn atomicSwapZ[T1, T2](mut &p: T1, new: T2, mo: atomicMemoryOrder): (old: T2) { + let mut tmp: T2 + unsafe { cpp.__atomic_exchange[T2](&p, &new, &tmp, mo) } + ret tmp +} + +// Atomically reads value of the p with memory order mo and returns. +// T1 is a base pointer type, T2 is the output type. +fn atomicLoadZ[T1, T2](&p: T1, mo: atomicMemoryOrder): T2 { + let mut tmp: T2 unsafe { cpp.__atomic_load(&p, &tmp, mo) } ret tmp } @@ -44,17 +74,20 @@ fn atomicLoad[T](&p: T, mo: atomicMemoryOrder): T { // If comparison results with true, it atomically stores new value into p. // In every case, it will use memory order mo. // Reports whether swap succeeded. -fn atomicCompareAndSwap[T](mut &p: T, old: T, new: T, mo: atomicMemoryOrder): (swapped: bool) { +// T1 is a base pointer type, T2 is the output type. +fn atomicCompareAndSwapZ[T1, T2](mut &p: T1, old: T2, new: T2, mo: atomicMemoryOrder): (swapped: bool) { const Strong = 0 // strong atomicity ret unsafe { cpp.__atomic_compare_exchange(&p, &old, &new, Strong, mo, mo) } } // Atomically adds delta to p with memory order mo and returns the new value. -fn atomicAdd[T](mut &p: T, delta: T, mo: atomicMemoryOrder): (new: T) { - ret unsafe { cpp.__atomic_fetch_add[T](&p, delta, mo) } + delta +// T1 is a base pointer type, T2 is the output type. +fn atomicAddZ[T1, T2](mut &p: T1, delta: T2, mo: atomicMemoryOrder): (new: T2) { + ret unsafe { cpp.__atomic_fetch_add[T2](&p, delta, mo) } + delta } // Atomically stores new value to p with memory order mo. -fn atomicStore[T](mut &p: T, val: T, mo: atomicMemoryOrder) { +// T1 is a base pointer type, T2 is the output type. +fn atomicStoreZ[T1, T2](mut &p: T1, val: T2, mo: atomicMemoryOrder) { unsafe { cpp.__atomic_store(&p, &val, mo) } } \ No newline at end of file diff --git a/std/sync/atomic/atomic.jule b/std/sync/atomic/atomic.jule index 532e365d5..9ee93697c 100644 --- a/std/sync/atomic/atomic.jule +++ b/std/sync/atomic/atomic.jule @@ -36,103 +36,362 @@ const AcqRel = memoryOrder(runtime::atomicAcqRel) // Operations are sequenced consistently. const SeqCst = memoryOrder(runtime::atomicSeqCst) -struct number[T] { - n: T +// The atomic box for i8 type. +type I8: i8 + +impl I8 { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: i8, order: memoryOrder): (old: i8) { + ret runtime::atomicSwapZ(self, new, order) + } + + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: i8, new: i8, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } + + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: i8, order: memoryOrder): (new: i8) { + ret runtime::atomicAddZ(self, delta, order) + } + + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): i8 { + ret runtime::atomicLoadZ[I8, i8](self, order) + } + + // Atomically assigns to value. + fn Store(mut self, val: i8, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) + } } -impl number { +// The atomic box for i16 type. +type I16: i16 + +impl I16 { // Atomically stores new value and returns the previous value. - fn Swap(mut self, new: T, order: memoryOrder): (old: T) { - ret runtime::atomicSwap[T](self.n, new, order) + fn Swap(mut self, new: i16, order: memoryOrder): (old: i16) { + ret runtime::atomicSwapZ(self, new, order) } // Executes the compare-and-swap operation. - fn CompareAndSwap(mut self, old: T, new: T, order: memoryOrder): (swapped: bool) { - ret runtime::atomicCompareAndSwap[T](self.n, old, new, order) + fn CompareAndSwap(mut self, old: i16, new: i16, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) } // Atomically adds delta to value and returns the new value. - fn Add(mut self, delta: T, order: memoryOrder): (new: T) { - ret runtime::atomicAdd[T](self.n, delta, order) + fn Add(mut self, delta: i16, order: memoryOrder): (new: i16) { + ret runtime::atomicAddZ(self, delta, order) } // Atomically reads and returns value. - fn Load(self, order: memoryOrder): T { - ret runtime::atomicLoad[T](self.n, order) + fn Load(self, order: memoryOrder): i16 { + ret runtime::atomicLoadZ[I16, i16](self, order) } // Atomically assigns to value. - fn Store(mut self, val: T, order: memoryOrder) { - runtime::atomicStore[T](self.n, val, order) + fn Store(mut self, val: i16, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) } } -impl number { - // Returns new atomic instance for type with initializer value. - static fn New(n: T): number[T] { - ret number[T]{n: n} +// The atomic box for i32 type. +type I32: i32 + +impl I32 { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: i32, order: memoryOrder): (old: i32) { + ret runtime::atomicSwapZ(self, new, order) + } + + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: i32, new: i32, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } + + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: i32, order: memoryOrder): (new: i32) { + ret runtime::atomicAddZ(self, delta, order) + } + + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): i32 { + ret runtime::atomicLoadZ[I32, i32](self, order) + } + + // Atomically assigns to value. + fn Store(mut self, val: i32, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) + } +} + +// The atomic box for i64 type. +type I64: i64 + +impl I64 { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: i64, order: memoryOrder): (old: i64) { + ret runtime::atomicSwapZ(self, new, order) + } + + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: i64, new: i64, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } + + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: i64, order: memoryOrder): (new: i64) { + ret runtime::atomicAddZ(self, delta, order) + } + + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): i64 { + ret runtime::atomicLoadZ[I64, i64](self, order) + } + + // Atomically assigns to value. + fn Store(mut self, val: i64, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) } } -// Type alias for private wrapper structure for i8 type. -type I8 = number[i8] +// The atomic box for int type. +type Int: int -// Type alias for private wrapper structure for i16 type. -type I16 = number[i16] +impl Int { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: int, order: memoryOrder): (old: int) { + ret runtime::atomicSwapZ(self, new, order) + } -// Type alias for private wrapper structure for i32 type. -type I32 = number[i32] + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: int, new: int, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } -// Type alias for private wrapper structure for i64 type. -type I64 = number[i64] + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: int, order: memoryOrder): (new: int) { + ret runtime::atomicAddZ(self, delta, order) + } -// Type alias for private wrapper structure for int type. -type Int = number[int] + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): int { + ret runtime::atomicLoadZ[Int, int](self, order) + } -// Type alias for private wrapper structure for u8 type. -type U8 = number[u8] + // Atomically assigns to value. + fn Store(mut self, val: int, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) + } +} -// Type alias for private wrapper structure for u16 type. -type U16 = number[u16] +// The atomic box for u8 type. +type U8: u8 -// Type alias for private wrapper structure for u32 type. -type U32 = number[u32] +impl U8 { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: u8, order: memoryOrder): (old: u8) { + ret runtime::atomicSwapZ(self, new, order) + } + + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: u8, new: u8, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } + + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: u8, order: memoryOrder): (new: u8) { + ret runtime::atomicAddZ(self, delta, order) + } -// Type alias for private wrapper structure for u64 type. -type U64 = number[u64] + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): u8 { + ret runtime::atomicLoadZ[U8, u8](self, order) + } -// Type alias for private wrapper structure for uint type. -type Uint = number[uint] + // Atomically assigns to value. + fn Store(mut self, val: u8, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) + } +} + +// The atomic box for u16 type. +type U16: u16 + +impl U16 { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: u16, order: memoryOrder): (old: u16) { + ret runtime::atomicSwapZ(self, new, order) + } + + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: u16, new: u16, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } -// Type aliases for private wrapper structure for uintptr type. -type Uintptr = number[uintptr] + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: u16, order: memoryOrder): (new: u16) { + ret runtime::atomicAddZ(self, delta, order) + } + + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): u16 { + ret runtime::atomicLoadZ[U16, u16](self, order) + } + + // Atomically assigns to value. + fn Store(mut self, val: u16, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) + } +} + +// The atomic box for u32 type. +type U32: u32 + +impl U32 { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: u32, order: memoryOrder): (old: u32) { + ret runtime::atomicSwapZ(self, new, order) + } + + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: u32, new: u32, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } + + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: u32, order: memoryOrder): (new: u32) { + ret runtime::atomicAddZ(self, delta, order) + } + + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): u32 { + ret runtime::atomicLoadZ[U32, u32](self, order) + } + + // Atomically assigns to value. + fn Store(mut self, val: u32, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) + } +} + +// The atomic box for u64 type. +type U64: u64 + +impl U64 { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: u64, order: memoryOrder): (old: u64) { + ret runtime::atomicSwapZ(self, new, order) + } + + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: u64, new: u64, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } + + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: u64, order: memoryOrder): (new: u64) { + ret runtime::atomicAddZ(self, delta, order) + } + + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): u64 { + ret runtime::atomicLoadZ[U64, u64](self, order) + } + + // Atomically assigns to value. + fn Store(mut self, val: u64, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) + } +} + +// The atomic box for uint type. +type Uint: uint + +impl Uint { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: uint, order: memoryOrder): (old: uint) { + ret runtime::atomicSwapZ(self, new, order) + } + + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: uint, new: uint, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } + + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: uint, order: memoryOrder): (new: uint) { + ret runtime::atomicAddZ(self, delta, order) + } + + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): uint { + ret runtime::atomicLoadZ[Uint, uint](self, order) + } + + // Atomically assigns to value. + fn Store(mut self, val: uint, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) + } +} + +// The atomic box for uintptr type. +type Uintptr: uintptr + +impl Uintptr { + // Atomically stores new value and returns the previous value. + fn Swap(mut self, new: uintptr, order: memoryOrder): (old: uintptr) { + ret runtime::atomicSwapZ(self, new, order) + } + + // Executes the compare-and-swap operation. + fn CompareAndSwap(mut self, old: uintptr, new: uintptr, order: memoryOrder): (swapped: bool) { + ret runtime::atomicCompareAndSwapZ(self, old, new, order) + } + + // Atomically adds delta to value and returns the new value. + fn Add(mut self, delta: uintptr, order: memoryOrder): (new: uintptr) { + ret runtime::atomicAddZ(self, delta, order) + } + + // Atomically reads and returns value. + fn Load(self, order: memoryOrder): uintptr { + ret runtime::atomicLoadZ[Uintptr, uintptr](self, order) + } + + // Atomically assigns to value. + fn Store(mut self, val: uintptr, order: memoryOrder) { + runtime::atomicStoreZ(self, val, order) + } +} // Atomically stores new into addr and returns the previous addr value. // Only integer types are supported. fn Swap[T: int | uint | i8 | i16 | i32 | i64 | u8 | u16 | u32 | u64 | uintptr](mut &addr: T, new: T, order: memoryOrder): (old: T) { - ret runtime::atomicSwap[T](addr, new, order) + ret runtime::atomicSwap(addr, new, order) } // Executes the compare-and-swap operation for value. // Only integer types are supported. fn CompareAndSwap[T: int | uint | i8 | i16 | i32 | i64 | u8 | u16 | u32 | u64 | uintptr](mut &addr: T, old: T, new: T, order: memoryOrder): (swapped: bool) { - ret runtime::atomicCompareAndSwap[T](addr, old, new, order) + ret runtime::atomicCompareAndSwap(addr, old, new, order) } // Atomically adds delta to addr and returns the new addr value. // Only integer types are supported. fn Add[T: int | uint | i8 | i16 | i32 | i64 | u8 | u16 | u32 | u64 | uintptr](mut &addr: T, delta: T, order: memoryOrder): (new: T) { - ret runtime::atomicAdd[T](addr, delta, order) + ret runtime::atomicAdd(addr, delta, order) } // Atomically loads addr. // Only integer types are supported. fn Load[T: int | uint | i8 | i16 | i32 | i64 | u8 | u16 | u32 | u64 | uintptr](&addr: T, order: memoryOrder): T { - ret runtime::atomicLoad[T](addr, order) + ret runtime::atomicLoad(addr, order) } // Atomically stores val into addr. // Only integer types are supported. fn Store[T: int | uint | i8 | i16 | i32 | i64 | u8 | u16 | u32 | u64 | uintptr](mut &addr: T, val: T, order: memoryOrder) { - runtime::atomicStore[T](addr, val, order) + runtime::atomicStore(addr, val, order) } \ No newline at end of file