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