docs: public void terminate(boolean delay)
      {
          //  Overload the value specified at pipe creation.
          this.delay = delay;
  
          //  If terminate was already called, we can ignore the duplicit invocation.
          if (state == State.TERM_REQ_SENT_1 || state == State.TERM_REQ_SENT_2) {
              return;
          }
          //  If the pipe is in the final phase of async termination, it's going to
          //  closed anyway. No need to do anything special here.
          else if (state == State.TERM_ACK_SENT) {
              return;
          }
          //  The simple sync termination case. Ask the peer to terminate and wait
          //  for the ack.
          else if (state == State.ACTIVE) {
              sendPipeTerm(peer);
              state = State.TERM_REQ_SENT_1;
          }
          //  There are still pending messages available, but the user calls
          //  'terminate'. We can act as if all the pending messages were read.
          else if (state == State.WAITING_FOR_DELIMITER && !this.delay) {
              outpipe = null;
              sendPipeTermAck(peer);
              state = State.TERM_ACK_SENT;
          }
          //  If there are pending messages still available, do nothing.
          else if (state == State.WAITING_FOR_DELIMITER) {
              // do nothing
          }
          //  We've already got delimiter, but not term command yet. We can ignore
          //  the delimiter and ack synchronously terminate as if we were in
          //  active state.
          else if (state == State.DELIMITER_RECEIVED) {
              sendPipeTerm(peer);
              state = State.TERM_REQ_SENT_1;
          }
          //  There are no other states.
          else {
              assert (false);
          }
  
          //  Stop outbound flow of messages.
          outActive = false;
  
          if (outpipe != null) {
              //  Drop any unfinished outbound messages.
              rollback();
  
              //  Write the delimiter into the pipe. Note that watermarks are not
              //  checked; thus the delimiter can be written even when the pipe is full.
  
              Msg msg = new Msg();
              msg.initDelimiter();
              outpipe.write(msg, false);
              flush();
          }
      }