compare_exchange/_weak wired end-to-end except LLVM emission (bails loudly;
A.2b makes it real). New IR op atomic_cmpxchg + AtomicCmpxchg{ptr, cmp, new,
val_ty, success_ordering, failure_ordering, weak}; result type = ?T (null =
SUCCESS, failure carries the actual value for retry). print arm; emit dispatch
-> emitAtomicCmpxchg (BAILS). comptime_vm arm does real single-thread CAS (read
actual / compare / store-on-equal / build ?T: success->none, failure->some;
weak == strong at comptime). Recognizer extended (atomic_cmpxchg/_weak, 6 args)
-- CAS restricted to INTEGER T (loud reject); BOTH orderings resolved via
atomicOrderingFromNode; dual-ordering validation (failure may not be
release/acq_rel nor stronger than success, via atomicOrderingRank). Methods
compare_exchange/_weak on Atomic($T) with comptime $success/$failure: Ordering.
examples/1702 locked to the bail; examples/1186 locks a rejected ordering pair.
Suite green (718/0).
35 lines
1.3 KiB
Plaintext
35 lines
1.3 KiB
Plaintext
// Atomic($T) compare-exchange: compare_exchange / compare_exchange_weak → LLVM
|
|
// cmpxchg. Result is `?T` — null = SUCCESS; a present value is the ACTUAL current
|
|
// value on failure (for a retry loop). Stream A (atomics) A.2. Single-thread.
|
|
#import "modules/std.sx";
|
|
#import "modules/std/atomic.sx";
|
|
|
|
main :: () {
|
|
// Successful CAS: 10 == 10 → store 20, returns null.
|
|
a := Atomic(i64).init(10);
|
|
got := a.compare_exchange(10, 20, .acq_rel, .acquire);
|
|
if got == null {
|
|
print("cas ok, now: {}\n", a.load(.acquire)); // 20
|
|
} else {
|
|
print("cas unexpected fail: {}\n", got!);
|
|
}
|
|
|
|
// Failing CAS: 99 != 20 → no store, returns the actual value (20), unchanged.
|
|
got2 := a.compare_exchange(99, 0, .seq_cst, .seq_cst);
|
|
if got2 == null {
|
|
print("cas unexpected ok\n");
|
|
} else {
|
|
print("cas failed, actual: {}, still: {}\n", got2!, a.load(.seq_cst)); // 20, 20
|
|
}
|
|
|
|
// Retry loop with the weak variant: increment a counter by 5.
|
|
counter := Atomic(i64).init(100);
|
|
cur := counter.load(.relaxed);
|
|
while true {
|
|
r := counter.compare_exchange_weak(cur, cur + 5, .acq_rel, .acquire);
|
|
if r == null { break; }
|
|
cur = r!; // retry with the observed value
|
|
}
|
|
print("after loop: {}\n", counter.load(.seq_cst)); // 105
|
|
}
|