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 ( ) ; } }
before actual shutdown .