Hone logo
Hone
Problems

Implementing a Condition Variable in Rust

Condition variables are essential synchronization primitives for coordinating threads in concurrent programs. They allow threads to wait for a specific condition to become true, efficiently blocking until another thread signals that the condition has been met. This challenge asks you to implement a basic condition variable in Rust, demonstrating your understanding of mutexes and thread synchronization.

Problem Description

You are tasked with implementing a Condvar struct in Rust that provides the core functionality of a condition variable: waiting and signaling. The Condvar should be built upon a Mutex<T> to protect shared state. The Condvar should provide the following methods:

  • new(mutex: Mutex<T>): Creates a new Condvar associated with the given mutex.
  • wait(mutex: &MutexGuard<'_, T>) -> Result<(), PoisonError<T>>: Atomically releases the mutex, waits for a notification, and reacquires the mutex. Returns a PoisonError<T> if the mutex was poisoned.
  • notify_one(mutex: &MutexGuard<'_, T>): Wakes up one waiting thread. If no threads are waiting, this function does nothing.
  • notify_all(mutex: &MutexGuard<'_, T>): Wakes up all waiting threads. If no threads are waiting, this function does nothing.

The wait method is the most crucial and complex. It must atomically release the mutex, put the thread to sleep, and then reacquire the mutex before returning. The notify_one and notify_all methods should wake up waiting threads, but do not need to handle the reacquisition of the mutex.

Examples

Example 1:

Input: Two threads. Thread 1 holds a mutex and calls `wait`. Thread 2 holds the same mutex and calls `notify_one`.
Output: Thread 1 unblocks and reacquires the mutex.
Explanation: Thread 1 waits on the condition variable, releasing the mutex. Thread 2 signals the condition variable, waking up Thread 1. Thread 1 then reacquires the mutex.

Example 2:

Input: Multiple threads waiting on the same condition variable. Thread 1 holds the mutex and calls `notify_all`.
Output: All waiting threads are unblocked.
Explanation: Thread 1 signals the condition variable, waking up all threads currently waiting on it.

Example 3: (Edge Case)

Input: No threads are waiting on the condition variable. Thread 1 holds the mutex and calls `notify_one`.
Output: No threads are unblocked.
Explanation: The `notify_one` function does nothing if no threads are waiting.

Constraints

  • The Condvar must be implemented using the standard library's Mutex and Condvar types. You are not allowed to implement a mutex from scratch.
  • The wait method must atomically release the mutex and reacquire it.
  • The notify_one and notify_all methods should not block.
  • The code should be thread-safe.
  • The solution should compile and run without panics.

Notes

  • Consider using the std::sync::Condvar type internally. Your Condvar struct should wrap a Mutex and a Condvar.
  • The wait method requires careful handling of mutex poisoning. The Result type allows you to propagate the PoisonError.
  • Think about the order of operations in the wait method to ensure atomicity. Releasing the mutex before waiting is crucial.
  • The MutexGuard is a RAII guard that automatically unlocks the mutex when it goes out of scope. This is important for ensuring that the mutex is always released, even if an error occurs.
  • This is a simplified implementation. Real-world condition variables might have additional features, such as timeouts.
Loading editor...
rust