private void ProcessCommands(int timeout, bool throttle)
{
bool found;
Command command;
if (timeout != 0)
{
// If we are asked to wait, simply ask mailbox to wait.
found = m_mailbox.TryRecv(timeout, out command);
}
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.
found = m_mailbox.TryRecv(0, out command);
}
// Process all the commands available at the moment.
while (found)
{
command.Destination.ProcessCommand(command);
found = m_mailbox.TryRecv(0, out command);
}
CheckContextTerminated();
}