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
{
foreach (var socket in m_sockets)
socket.Stop();
if (!Block)
{
m_reaper.ForceStop();
}
else if (m_sockets.Count == 0)
m_reaper.Stop();
}
finally
{
Monitor.Exit(m_slotSync);
}
}
if (m_block)
{
// Wait till reaper thread closes all the sockets.
Command command;
var found = m_termMailbox.TryRecv(-1, out command);
Debug.Assert(found);
Debug.Assert(command.CommandType == CommandType.Done);
Monitor.Enter(m_slotSync);
}
else
Monitor.Enter(m_slotSync);
}
Monitor.Exit(m_slotSync);
// Deallocate the resources.
foreach (IOThread it in m_ioThreads)
it.Stop();
foreach (IOThread it in m_ioThreads)
it.Destroy();
if (m_reaper != null)
m_reaper.Destroy();
m_termMailbox.Close();
m_disposed = true;
}