Example #1
0
        /// <summary> Handles the delimiter read from the pipe. </summary>
        private void Delimit()
        {
            if (m_state == State.Active)
            {
                m_state = State.Delimited;
                return;
            }

            if (m_state == State.Pending)
            {
                m_outboundPipe = null;
                SendPipeTermAck(m_peer);
                m_state = State.Terminating;
                return;
            }

            //  Delimiter in any other state is invalid.
            Debug.Assert(false);
        }
Example #2
0
        /// <summary> Create a pipe pair for bi-directional transfer of messages. </summary>
        /// <param name="parents">The parents.</param>
        /// <param name="highWaterMarks">First HWM is for messages passed from first pipe to the second pipe.
        /// Second HWM is for messages passed from second pipe to the first pipe.</param>
        /// <param name="delays">Delay specifies how the pipe behaves when the peer terminates. If true
        /// pipe receives all the pending messages before terminating, otherwise it
        /// terminates straight away.</param>
        /// <returns>A pipe pair for bi-directional transfer of messages. </returns>
        public static Pipe[] PipePair(ZObject[] parents, int[] highWaterMarks, bool[] delays)
        {
            //   Creates two pipe objects. These objects are connected by two ypipes,
            //   each to pass messages in one direction.

            YPipe <Msg> upipe1 = new YPipe <Msg>(Config.MessagePipeGranularity, "upipe1");
            YPipe <Msg> upipe2 = new YPipe <Msg>(Config.MessagePipeGranularity, "upipe2");

            var pipes = new Pipe[2];

            pipes[0] = new Pipe(parents[0], upipe1, upipe2,
                                highWaterMarks[1], highWaterMarks[0], delays[0]);
            pipes[1] = new Pipe(parents[1], upipe2, upipe1,
                                highWaterMarks[0], highWaterMarks[1], delays[1]);

            pipes[0].SetPeer(pipes[1]);
            pipes[1].SetPeer(pipes[0]);
            return(pipes);
        }
Example #3
0
        /// <summary> Temporarily disconnects the inbound message stream and drops
        ///  all the messages on the fly. Causes 'hiccuped' event to be generated in the peer. </summary>
        public void Hiccup()
        {
            //  If termination is already under way do nothing.
            if (m_state != State.Active)
            {
                return;
            }

            //  We'll drop the pointer to the in-pipe. From now on, the peer is
            //  responsible for deallocating it.
            m_inboundPipe = null;

            //  Create new in-pipe.
            m_inboundPipe = new YPipe <Msg>(Config.MessagePipeGranularity, "inpipe");
            m_inActive    = true;

            //  Notify the peer about the hiccup.
            SendHiccup(m_peer, m_inboundPipe);
        }
Example #4
0
 ///<remarks> Constructor is private as pipe can only be created using <see cref="PipePair"/> method. </remarks>
 private Pipe(ZObject parent, YPipe <Msg> inboundPipe, YPipe <Msg> outboundPipe,
              int inHighWatermark, int outHighWatermark, bool delay)
     : base(parent)
 {
     m_parent                  = parent;
     m_inboundPipe             = inboundPipe;
     m_outboundPipe            = outboundPipe;
     m_inActive                = true;
     m_outActive               = true;
     m_highWatermark           = outHighWatermark;
     m_lowWatermark            = ComputeLowWatermark(inHighWatermark);
     m_numberOfMessagesRead    = 0;
     m_numberOfMessagesWritten = 0;
     m_peersMsgsRead           = 0;
     m_peer  = null;
     m_sink  = null;
     m_state = State.Active;
     m_delay = delay;
 }
Example #5
0
        public Mailbox(String name)
        {
            m_cpipe    = new YPipe <Command>(Config.CommandPipeGranularity, "mailbox");
            m_sync     = new object();
            m_signaler = new Signaler();

            //  Get the pipe into passive state. That way, if the users starts by
            //  polling on the associated file descriptor it will get woken up when
            //  new command is posted.

            Command cmd = new Command();

            bool ok = m_cpipe.Read(ref cmd);

            Debug.Assert(!ok);
            m_active = false;

            m_name = name;
        }
Example #6
0
        public IOThreadMailbox([CanBeNull] string name, [NotNull] Proactor proactor, [NotNull] IMailboxEvent mailboxEvent)
        {
            m_proactor     = proactor;
            m_mailboxEvent = mailboxEvent;

            m_cpipe = new YPipe <Command>(Config.CommandPipeGranularity, "mailbox");
            m_sync  = new object();

            //  Get the pipe into passive state. That way, if the users starts by
            //  polling on the associated file descriptor it will get woken up when
            //  new command is posted.
            var cmd = new Command();

            bool ok = m_cpipe.Read(ref cmd);

            Debug.Assert(!ok);

            m_name = name;

            m_disposed = false;
        }
Example #7
0
        protected override void ProcessHiccup(object pipe)
        {
            //  Destroy old outpipe. Note that the read end of the pipe was already
            //  migrated to this thread.
            Debug.Assert(m_outboundPipe != null);
            m_outboundPipe.Flush();
            while (m_outboundPipe.Read() != null)
            {
            }

            //  Plug in the new outpipe.
            Debug.Assert(pipe != null);
            m_outboundPipe = (YPipe <Msg>)pipe;
            m_outActive    = true;

            //  If appropriate, notify the user about the hiccup.
            if (m_state == State.Active)
            {
                m_sink.Hiccuped(this);
            }
        }
Example #8
0
        protected override void ProcessPipeTermAck()
        {
            //  Notify the user that all the references to the pipe should be dropped.
            Debug.Assert(m_sink != null);
            m_sink.Terminated(this);

            //  In terminating and double_terminated states there's nothing to do.
            //  Simply deallocate the pipe. In terminated state we have to ack the
            //  peer before deallocating this side of the pipe. All the other states
            //  are invalid.
            if (m_state == State.Terminated)
            {
                m_outboundPipe = null;
                SendPipeTermAck(m_peer);
            }
            else
            {
                Debug.Assert(m_state == State.Terminating || m_state == State.DoubleTerminated);
            }

            //  We'll deallocate the inbound pipe, the peer will deallocate the outbound
            //  pipe (which is an inbound pipe from its point of view).
            //  First, delete all the unread messages in the pipe. We have to do it by
            //  hand because msg_t doesn't have automatic destructor. Then deallocate
            //  the ypipe itself.
            var msg = new Msg();

            if (m_inboundPipe != null)
            {
                while (m_inboundPipe.Read(ref msg))
                {
                    msg.Close();
                }
            }

            m_inboundPipe = null;
        }
Example #9
0
        /// <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();
            }
        }