///|
/// Owns one native wait registration, including its memory descriptor lease.
/// Dropping the object cancels its registration; explicit cancellation is
/// idempotent. Creation requires a checked, aligned shared-memory address.
pub type NativeAtomicWait

///|
#borrow(descriptor)
extern "c" fn atomic_wait_new(
  descriptor : MemoryDescriptor,
  offset : Int64,
  width : Int32,
  expected : Int64,
  timeout : Int64,
) -> NativeAtomicWait = "wasmoon_atomic_wait_managed"

///|
#borrow(self)
extern "c" fn NativeAtomicWait::allocated(self : NativeAtomicWait) -> Bool = "wasmoon_atomic_wait_managed_allocated"

///|
/// Returns -1 while pending, or the Wasm wait result 0/1/2. After cancellation
/// returns 3. Polling never blocks the embedding thread.
#borrow(self)
pub extern "c" fn NativeAtomicWait::poll(self : NativeAtomicWait) -> Int32 = "wasmoon_atomic_wait_managed_poll"

///|
#borrow(self)
pub extern "c" fn NativeAtomicWait::cancel(self : NativeAtomicWait) -> Unit = "wasmoon_atomic_wait_managed_cancel"

///|
/// Request a one-millisecond sleep when the registration is still pending.
/// Cooperative schedulers use poll instead.
#borrow(self)
pub extern "c" fn NativeAtomicWait::pause(self : NativeAtomicWait) -> Unit = "wasmoon_atomic_wait_pause"

///|
pub fn atomic_wait_begin(
  descriptor : MemoryDescriptor,
  offset : Int64,
  width : Int32,
  expected : Int64,
  timeout : Int64,
) -> NativeAtomicWait? {
  let waiter = atomic_wait_new(descriptor, offset, width, expected, timeout)
  if waiter.allocated() {
    Some(waiter)
  } else {
    None
  }
}

///|
#borrow(descriptor)
pub extern "c" fn atomic_notify(
  descriptor : MemoryDescriptor,
  offset : Int64,
  count : Int32,
) -> Int32 = "wasmoon_atomic_notify"

///|
/// Briefly sleep an idle cooperative scheduler while only waits remain.
pub extern "c" fn cooperative_idle() -> Unit = "wasmoon_cooperative_idle"