method private writer =
try
while true do
(* Wait for the reader to read the block we fancy, or for shutdown. *)
Mutex.lock wait_m ;
if state <> `Tired &&
read <> write && write mod nb_blocks = read mod nb_blocks
then
Condition.wait wait_c wait_m ;
Mutex.unlock wait_m ;
(* Exit or... *)
if state = `Tired then raise Exit ;
(* ...write a block. *)
self#pull_block buffer.(write mod nb_blocks) ;
Mutex.lock wait_m ;
write <- (write + 1) mod (2*nb_blocks) ;
Mutex.unlock wait_m ;
Condition.signal wait_c
done
with
| Exit ->
self#close
| e ->
(* We crashed. Let's attempt to leave things in a decent state.
* Note that the exception should only come from #pull_lock,
* which is performed outside of critical section, so there's
* not need to unlock. *)
self#close ;
(* It is possible that the reader is waiting for us,
* hence blocking the streaming thread, and consequently
* the possibility of going to sleep peacefully.
* Let's resume it, even though he'll get an arbitrary block. *)
Mutex.lock wait_m ;
write <- (write + 1) mod (2*nb_blocks) ;
state <- `Crashed ;
Mutex.unlock wait_m ;
Condition.signal wait_c ;
raise e