@cmpxchgWeak

@cmpxchgWeak

약한(weak) 원자적 compare-and-exchange(비교-교환) 연산을 수행하는 내장 함수예요. 현재 값이 기대한 값과 같으면 null을 돌려주고, 달라지면 실제 저장된 값을 돌려줘요. 말 그대로 다음 코드를 "원자적(atomic)으로 만들었다"고 보면 돼요 — 다만 이 코드가 다 보여주듯 항상 성공하는 건 아니라는 점이 핵심이에요.

출처: Zig Documentation

본문

@cmpxchgWeak(comptime T: type, ptr: *T, expected_value: T, new_value: T, success_order: AtomicOrder, fail_order: AtomicOrder) ?T

이 함수는 약한 원자적 compare-and-exchange 연산을 수행해요. 현재 값이 주어진 기대값과 같으면 null을 돌려주죠. 다음 코드의 원자적 버전이라고 보면 돼요:

fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_value: T) ?T {
    const old_value = ptr.*;
    if (old_value == expected_value and usuallyTrueButSometimesFalse()) {
        ptr.* = new_value;
        return null;
    } else {
        return old_value;
    }
}

예제의 usuallyTrueButSometimesFalse()가 은근히 중요한데, 이게 "약함"의 정체예요. 실제 값은 기대값과 같아도 가끔은 (드물게) 교환을 안 하고 실패를 돌려줄 수 있어요.

그래서 cmpxchg를 재시도(retry) 루프 안에서 쓴다면, 이 드물게 나는 실패는 전혀 문제가 되지 않아요. 그런 상황에서는 cmpxchgWeak가 더 나은 선택이에요 — 기계어 명령으로 훨씬 효율적으로 구현될 수 있거든요. 다만 더 강한 보장이 필요하다면 @cmpxchgStrong을 쓰세요.

제약 조건:

  • T는 포인터, bool, 정수, enum, 또는 packed struct여야 해요.
  • @typeInfo(@TypeOf(ptr)).pointer.alignment>= @sizeOf(T)여야 해요.
  • AtomicOrder@import("std").lang.AtomicOrder로 찾을 수 있어요.

더 알아보기 (Learn more)