public void start()
{
/* Starts the I/O loop.
The loop will run until one of the I/O handlers calls stop(), which
will make the loop stop after the current event iteration completes.
*/
if(_stopped)
{
_stopped = false;
return;
}
_thread_ident = thread.get_ident();
_running = true;
while(true)
{
double poll_timeout = 3600.0;
// Prevent IO event starvation by delaying new callbacks
// to the next iteration of the event loop.
lock(_callback_lock)
{
callbacks = _callbacks;
_callbacks = new List<Action>();
}
foreach(var callback in callbacks)
_run_callback(callback);
if(_timeouts.Any())
{
var now = DateTime.Now;
while(_timeouts.Any())
{
var timeout = _timeouts.First().Value;
if(timeout.callback == null)
{
// the timeout was cancelled
_timeouts.RemoveAt(0);
}
else if(timeout.deadline <= now)
{
_timeouts.RemoveAt(0);
_run_callback(timeout.callback);
}
else
{
var seconds = (timeout.deadline - now).Seconds;
poll_timeout = Math.Min(seconds, poll_timeout);
}
}
}
if(_callbacks.Any())
{
// If any callbacks or timeouts called add_callback,
// we don't want to wait in poll() before we run them.
poll_timeout = 0.0;
}
if(!_running)
break;
if(_blocking_signal_threshold != null)
{
// clear alarm so it doesn't fire while poll is waiting for
// events.
//todo signal.setitimer(signal.ITIMER_REAL, 0, 0)
}
Dictionary<int, int> event_pairs = null;
try
{
event_pairs = _impl.poll(poll_timeout);
}
catch(Exception ex)
{
//todo
// Depending on python version and IOLoop implementation,
// different exception types may be thrown and there are
// two ways EINTR might be signaled:
// * e.errno == errno.EINTR
// * e.args is like (errno.EINTR, 'Interrupted system call')
/*if (getattr(e, 'errno', None) == errno.EINTR or
(isinstance(getattr(e, 'args', None), tuple) and
len(e.args) == 2 and e.args[0] == errno.EINTR)):
continue
else:
raise*/
}
if(_blocking_signal_threshold != null)
{
//todo signal.setitimer(signal.ITIMER_REAL,
// self._blocking_signal_threshold, 0)
}
// Pop one fd at a time from the set of pending fds and run
// its handler. Since that handler may perform actions on
// other file descriptors, there may be reentrant calls to
// this IOLoop that update self._events
_events.update(event_pairs);
while(_events.Any())
{
// fd, events = self._events.popitem()
var lastEvent = _events.popitem();
int fd = lastEvent.Key;
int events = lastEvent.Value;
try
{
_handlers[fd](fd, events);
}
catch(SocketException ex) //except (OSError, IOError), e:
{
if (ex.SocketErrorCode == SocketError.ConnectionAborted) // if e.args[0] == errno.EPIPE:
// Happens when the client closes the connection
continue;
else
logging.error(string.Format("Exception in I/O handler for fd {0}", fd), ex);
}
catch(Exception ex)
{
logging.error(string.Format("Exception in I/O handler for fd {0}", fd), ex);
}
}
}
// reset the stopped flag so another start/stop pair can be issued
_stopped = false;
if(_blocking_signal_threshold != null)
;//todo signal.setitimer(signal.ITIMER_REAL, 0, 0)
}