public bool TryRecv(ref Msg msg, TimeSpan timeout)
{
CheckContextTerminated();
// Check whether message passed to the function is valid.
if (!msg.IsInitialised)
throw new FaultException("SocketBase.Recv passed an uninitialised Msg.");
// Get the message.
bool isMessageAvailable = XRecv(ref msg);
// Once every Config.InboundPollRate messages check for signals and process
// incoming commands. This happens only if we are not polling altogether
// because there are messages available all the time. If poll occurs,
// ticks is set to zero and thus we avoid this code.
//
// Note that 'recv' uses different command throttling algorithm (the one
// described above) from the one used by 'send'. This is because counting
// ticks is more efficient than doing RDTSC all the time.
if (++m_ticks == Config.InboundPollRate)
{
ProcessCommands(0, false);
m_ticks = 0;
}
// If we have the message, return immediately.
if (isMessageAvailable)
{
ExtractFlags(ref msg);
return true;
}
// If the message cannot be fetched immediately, there are two scenarios.
// For non-blocking recv, commands are processed in case there's an
// activate_reader command already waiting in a command pipe.
// If it's not, return false.
if (timeout == TimeSpan.Zero)
{
ProcessCommands(0, false);
m_ticks = 0;
isMessageAvailable = XRecv(ref msg);
if (!isMessageAvailable)
return false;
ExtractFlags(ref msg);
return true;
}
// Compute the time when the timeout should occur.
// If the timeout is infinite (negative), don't care.
int timeoutMillis = (int)timeout.TotalMilliseconds;
long end = timeoutMillis < 0 ? 0L : Clock.NowMs() + timeoutMillis;
// In blocking scenario, commands are processed over and over again until
// we are able to fetch a message.
bool block = m_ticks != 0;
while (true)
{
ProcessCommands(block ? timeoutMillis : 0, false);
isMessageAvailable = XRecv(ref msg);
if (isMessageAvailable)
{
m_ticks = 0;
break;
}
block = true;
if (timeoutMillis > 0)
{
timeoutMillis = (int)(end - Clock.NowMs());
if (timeoutMillis <= 0)
return false;
}
}
ExtractFlags(ref msg);
return true;
}