// Copyright 2026 International Digital Economy Academy
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///|
/// Condition variable for thread synchronization.
///
/// Condition variables are used in combination with mutexes to allow threads
/// to wait for certain conditions to be met. A thread can wait on a condition
/// variable while holding a mutex, and other threads can signal or broadcast
/// to wake up waiting threads.
///
/// Condition variables must always be used with mutexes. The typical pattern is:
/// 1. Lock the mutex
/// 2. Check the condition in a loop
/// 3. If condition not met, wait on the condition variable
/// 4. When signaled, the loop continues and rechecks the condition
/// 5. Unlock the mutex when done
type Cond
///|
extern "c" fn uv_cond_make() -> Cond = "moonbit_uv_cond_make"
///|
#owned(cond)
extern "c" fn uv_cond_init(cond : Cond) -> Int = "moonbit_uv_cond_init"
///|
pub fn Cond::new() -> Cond raise Errno {
let cond = uv_cond_make()
let status = uv_cond_init(cond)
if status != 0 {
raise Errno::of_int(status)
}
return cond
}
///|
#owned(cond, other)
extern "c" fn uv_cond_copy(cond : Cond, other : Cond) = "moonbit_uv_cond_copy"
///|
#owned(cond)
extern "c" fn uv_cond_signal(cond : Cond) = "moonbit_uv_cond_signal"
///|
#owned(cond)
extern "c" fn uv_cond_broadcast(cond : Cond) = "moonbit_uv_cond_broadcast"
///|
#owned(cond, mutex)
extern "c" fn uv_cond_wait(cond : Cond, mutex : Mutex) = "moonbit_uv_cond_wait"
///|
#owned(cond, mutex)
extern "c" fn uv_cond_timedwait(
cond : Cond,
mutex : Mutex,
timeout : UInt64,
) -> Int = "moonbit_uv_cond_timedwait"
///|
/// Signal one waiting thread.
///
/// Wake up one thread that is waiting on this condition variable.
/// If no threads are waiting, this call has no effect.
pub fn Cond::signal(self : Cond) -> Unit {
uv_cond_signal(self)
}
///|
/// Broadcast to all waiting threads.
///
/// Wake up all threads that are waiting on this condition variable.
/// If no threads are waiting, this call has no effect.
pub fn Cond::broadcast(self : Cond) -> Unit {
uv_cond_broadcast(self)
}
///|
/// Wait on the condition variable.
///
/// The calling thread will block until another thread calls `signal()` or
/// `broadcast()` on this condition variable. The mutex must be locked by
/// the calling thread prior to calling this function. The mutex will be
/// automatically unlocked while waiting and re-locked before returning.
///
/// # Note
/// This function can experience spurious wakeups. Always use this in a loop
/// that checks the actual condition.
pub fn Cond::wait(self : Cond, mutex : Mutex) -> Unit {
uv_cond_wait(self, mutex)
}
///|
/// Wait on the condition variable with a timeout.
///
/// Similar to `wait()`, but will return after the specified timeout
/// (in nanoseconds) even if no signal was received.
///
/// Returns:
/// - `Ok(())` if signaled before timeout
/// - `Err(ETIMEDOUT)` if timeout occurred
/// - `Err(_)` for other errors
///
/// # Note
/// This function can experience spurious wakeups. Always use this in a loop
/// that checks the actual condition.
pub fn Cond::timedwait(
self : Cond,
mutex : Mutex,
timeout_ns : UInt64,
) -> Unit raise Errno {
let status = uv_cond_timedwait(self, mutex, timeout_ns)
if status < 0 {
raise Errno::of_int(status)
}
}
///|
pub impl Share for Cond with share(self : Cond) -> Cond {
let other = uv_cond_make()
uv_cond_copy(self, other)
return other
}