public void terminate (boolean delay_)
    {
        //  Overload the value specified at pipe creation.
        delay = delay_;

        //  If terminate was already called, we can ignore the duplicit invocation.
        if (state == State.terminated || state == State.double_terminated)
            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.terminating)
            return;

        //  The simple sync termination case. Ask the peer to terminate and wait
        //  for the ack.
        else if (state == State.active) {
            send_pipe_term (peer);
            state = State.terminated;
        }

        //  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.pending && !delay) {
            outpipe = null;
            send_pipe_term_ack (peer);
            state = State.terminating;
        }

        //  If there are pending messages still availabe, do nothing.
        else if (state == State.pending) {
        }

        //  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.delimited) {
            send_pipe_term (peer);
            state = State.terminated;
        }

        //  There are no other states.
        else
            assert (false);

        //  Stop outbound flow of messages.
        out_active = 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.init_delimiter ();
            outpipe.write (msg, false);
            flush ();
            
        }
    }