// Processes commands sent to this socket (if any). If timeout is -1, // returns only after at least one command was processed. // If throttle argument is true, commands are processed at most once // in a predefined time period. private void ProcessCommands(int timeout, bool throttle) { Command cmd; if (timeout != 0) { // If we are asked to wait, simply ask mailbox to wait. cmd = m_mailbox.Recv(timeout); } else { // If we are asked not to wait, check whether we haven't processed // commands recently, so that we can throttle the new commands. // Get the CPU's tick counter. If 0, the counter is not available. long tsc = Clock.Rdtsc(); // Optimised version of command processing - it doesn't have to check // for incoming commands each time. It does so only if certain time // elapsed since last command processing. Command delay varies // depending on CPU speed: It's ~1ms on 3GHz CPU, ~2ms on 1.5GHz CPU // etc. The optimisation makes sense only on platforms where getting // a timestamp is a very cheap operation (tens of nanoseconds). if (tsc != 0 && throttle) { // Check whether TSC haven't jumped backwards (in case of migration // between CPU cores) and whether certain time have elapsed since // last command processing. If it didn't do nothing. if (tsc >= m_lastTsc && tsc - m_lastTsc <= Config.MaxCommandDelay) { return; } m_lastTsc = tsc; } // Check whether there are any commands pending for this thread. cmd = m_mailbox.Recv(0); } // Process all the commands available at the moment. while (true) { if (cmd == null) { break; } cmd.Destination.ProcessCommand(cmd); cmd = m_mailbox.Recv(0); } if (m_ctxTerminated) { throw TerminatingException.Create(); } }
/// <summary> /// This function is called when user invokes zmq_term. If there are /// no more sockets open it'll cause all the infrastructure to be shut /// down. If there are open sockets still, the deallocation happens /// after the last one is closed. /// </summary> public void Terminate() { m_disposed = true; Monitor.Enter(m_slotSync); if (!m_starting) { // Check whether termination was already underway, but interrupted and now // restarted. bool restarted = m_terminating; m_terminating = true; Monitor.Exit(m_slotSync); // First attempt to terminate the context. if (!restarted) { // First send stop command to sockets so that any blocking calls // can be interrupted. If there are no sockets we can ask reaper // thread to stop. Monitor.Enter(m_slotSync); try { for (int i = 0; i != m_sockets.Count; i++) { m_sockets[i].Stop(); } if (m_sockets.Count == 0) { m_reaper.Stop(); } } finally { Monitor.Exit(m_slotSync); } } // Wait till reaper thread closes all the sockets. Command cmd = m_termMailbox.Recv(-1); Debug.Assert(cmd != null); Debug.Assert(cmd.CommandType == CommandType.Done); Monitor.Enter(m_slotSync); Debug.Assert(m_sockets.Count == 0); } Monitor.Exit(m_slotSync); // Deallocate the resources. Destroy(); }
public void InEvent() { while (true) { // Get the next command. If there is none, exit. Command cmd = mailbox.Recv(0); if (cmd == null) { break; } // Process the command. cmd.Destination.ProcessCommand(cmd); } }
public void InEvent() { // TODO: Do we want to limit number of commands I/O thread can // process in a single go? while (true) { // Get the next command. If there is none, exit. Command cmd = m_mailbox.Recv(0); if (cmd == null) { break; } // Process the command. cmd.Destination.ProcessCommand(cmd); } }