/// <summary> /// Ask pipe to terminate. The termination will happen asynchronously /// and user will be notified about actual deallocation by 'terminated' /// event. /// </summary> /// <param name="delay">if set to <c>true</c>, the pending messages will be processed /// before actual shutdown. </param> public void Terminate(bool delay) { // Overload the value specified at pipe creation. m_delay = delay; // If terminate was already called, we can ignore the duplicate invocation. if (m_state == State.Terminated || m_state == State.DoubleTerminated) { return; } // If the pipe is in the phase of async termination, it's going to // closed anyway. No need to do anything special here. if (m_state == State.Terminating) { return; } if (m_state == State.Active) { // The simple sync termination case. Ask the peer to terminate and wait // for the ack. SendPipeTerm(m_peer); m_state = State.Terminated; } else if (m_state == State.Pending && !m_delay) { // There are still pending messages available, but the user calls // 'terminate'. We can act as if all the pending messages were read. m_outboundPipe = null; SendPipeTermAck(m_peer); m_state = State.Terminating; } else if (m_state == State.Pending) { // If there are pending messages still available, do nothing. } else if (m_state == State.Delimited) { // 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. SendPipeTerm(m_peer); m_state = State.Terminated; } else { // There are no other states. Debug.Assert(false); } // Stop outbound flow of messages. m_outActive = false; if (m_outboundPipe != 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. var msg = new Msg(); msg.InitDelimiter(); m_outboundPipe.Write(ref msg, false); Flush(); } }
// Ask pipe to terminate. The termination will happen asynchronously // and user will be notified about actual deallocation by 'terminated' // event. If delay is true, the pending messages will be processed // before actual shutdown. public void Terminate(bool delay) { // Overload the value specified at pipe creation. m_delay = delay; // If terminate was already called, we can ignore the duplicit invocation. if (m_state == State.Terminated || m_state == State.DoubleTerminated) return; // If the pipe is in the phase of async termination, it's going to // closed anyway. No need to do anything special here. else if (m_state == State.Terminating) return; // The simple sync termination case. Ask the peer to terminate and wait // for the ack. else if (m_state == State.Active) { SendPipeTerm (m_peer); m_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 (m_state == State.Pending && !m_delay) { m_outpipe = null; SendPipeTermAck (m_peer); m_state = State.Terminating; } // If there are pending messages still availabe, do nothing. else if (m_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 (m_state == State.Delimited) { SendPipeTerm (m_peer); m_state = State.Terminated; } // There are no other states. else Debug.Assert(false); // Stop outbound flow of messages. m_outActive = false; if (m_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 (); m_outpipe.Write (msg, false); Flush (); } }