exception Timeout type t = {mutex : Mutex.t; condition_lock : Condition.t; mutable value : int} let create initial_value = assert (0 <= initial_value); {mutex = Mutex.create (); condition_lock = Condition.create (); value = initial_value} let up semaphore = Mutex.lock semaphore.mutex; semaphore.value <- succ semaphore.value; Mutex.unlock semaphore.mutex; Condition.signal semaphore.condition_lock let down semaphore = Mutex.lock semaphore.mutex; assert (0 <= semaphore.value); while semaphore.value = 0 do Condition.wait semaphore.condition_lock semaphore.mutex done; semaphore.value <- pred semaphore.value; Mutex.unlock semaphore.mutex (* If it is possible to decrement the semaphore, do it and return "true". Otherwise return "false". *) let try_down semaphore = Mutex.lock semaphore.mutex; if 0 < semaphore.value then begin semaphore.value <- pred semaphore.value; Mutex.unlock semaphore.mutex; true end else begin Mutex.unlock semaphore.mutex; false end