public void read_reply (RequestOutputStream out) {

    // When reading a reply, the calling thread must hold a lock on both
    // the input and the output stream, otherwise we might end up doing
    // nasty stuff.

    assert Thread.holdsLock (this);
    assert Thread.holdsLock (out);


    // Flush the current request.
    // DON'T use plain send() because this could trigger a round-trip check
    // which would mess up with the reply.
    out.send_impl();
    out.flush();

    int exp_seq_no = out.seq_number;

    // Fetch all events and errors that may come before the reply.
    int code = -1;
    do {
      try {
        mark (1);
        code = read_int8 ();
        reset ();
      } catch (IOException ex) {
        handle_exception (ex);
      }
      if (code == 0) // Error.
        read_error ();
      else if (code > 1) { // Event.
        Event ev = read_event_from_stream ();
        if (ev != null)
          events.addLast (ev);
      }// else // Reply or Exception.
    } while (code != 1);
    // Check reply header, especially make sure that the sequence codes match.
    try {
      mark (4);
      int reply = read_int8 ();
      assert reply == 1 : "Reply code must be 1 but is: " + reply;
      skip (1);
      int seq_no = read_int16 ();
      assert (exp_seq_no == seq_no) : "expected sequence number: " + exp_seq_no
                                      + " got sequence number: " + seq_no;
      reset ();
    } catch (IOException ex) {
      handle_exception (ex);
    }

    // Now the calling thread can safely read the reply.
  }