prefix_ void senf::ppi::IOEvent::cb(int, Scheduler::EventId event)
{
- IOEventInfo info = { event };
- callback(info);
+ if ((event & ~events_) != 0) {
+ if (event & Err)
+ throw ErrorException();
+ else if (event & Hup)
+ throw HangupException();
+ else
+ // This cannot happen.
+ BOOST_ASSERT(false);
+ } else {
+ IOEventInfo info = { event };
+ callback(info);
+ }
}
///////////////////////////////cc.e////////////////////////////////////////
An IOEvent is signaled, whenever the FileHandle \a handle becomes readable or writable. The
type of event is specified using the \a events mask with values from EventFlags.
- \fixme Implement error/EOF handling
-
\see IOEventInfo
\ingroup event_group
///////////////////////////////////////////////////////////////////////////
// Types
+ // This is stupid, however there is no way to import the Scheduler::EventId enum together
+ // with the enumeration symbols
+
enum EventFlags { Read = Scheduler::EV_READ,
- Write = Scheduler::EV_WRITE };
+ Prio = Scheduler::EV_PRIO,
+ Write = Scheduler::EV_WRITE,
+ Hup = Scheduler::EV_HUP,
+ Err = Scheduler::EV_ERR };
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@}
///////////////////////////////////////////////////////////////////////////
+ /** \brief Unhandled error condition */
+ struct ErrorException : public std::exception
+ { virtual char const * what() const throw()
+ { return "senf::ppi::IOEvent::ErrorException"; } };
+
+ /** \brief Unhandled hangup condition */
+ struct HangupException : public std::exception
+ { virtual char const * what() const throw()
+ { return "senf::ppi::IOEvent::HangupException"; } };
+
protected:
private:
virtual void v_enable();
- virtual void v_disable();
+ virtual void v_disable();
void cb(int, Scheduler::EventId event);
eventTime_ = ClockService::now();
while (! terminate_) {
+ // Since a callback may have disabled further timers, we need to check for canceled timeouts
+ // again.
+
while (! timerQueue_.empty()) {
TimerMap::iterator i (timerQueue_.top());
if (! i->second.canceled)
// We always run event handlers. This is important, even if a file-descriptor is signaled
// since some descriptors (e.g. real files) will *always* be ready and we still may want to
- // handle timers
+ // handle timers.
+ // Time handlers are run before file events to not delay them unnecessarily.
while (! timerQueue_.empty()) {
TimerMap::iterator i (timerQueue_.top());