예제 #1
0
bool
CEventQueue::getEvent(CEvent& event, double timeout)
{
	CStopwatch timer(true);
retry:
	// if no events are waiting then handle timers and then wait
	while (m_buffer->isEmpty()) {
		// handle timers first
		if (hasTimerExpired(event)) {
			return true;
		}

		// get time remaining in timeout
		double timeLeft = timeout - timer.getTime();
		if (timeout >= 0.0 && timeLeft <= 0.0) {
			return false;
		}

		// get time until next timer expires.  if there is a timer
		// and it'll expire before the client's timeout then use
		// that duration for our timeout instead.
		double timerTimeout = getNextTimerTimeout();
		if (timeout < 0.0 || (timerTimeout >= 0.0 && timerTimeout < timeLeft)) {
			timeLeft = timerTimeout;
		}

		// wait for an event
		m_buffer->waitForEvent(timeLeft);
	}

	// get the event
	UInt32 dataID;
	IEventQueueBuffer::Type type = m_buffer->getEvent(event, dataID);
	switch (type) {
	case IEventQueueBuffer::kNone:
		if (timeout < 0.0 || timeout <= timer.getTime()) {
			// don't want to fail if client isn't expecting that
			// so if getEvent() fails with an infinite timeout
			// then just try getting another event.
			goto retry;
		}
		return false;

	case IEventQueueBuffer::kSystem:
		return true;

	case IEventQueueBuffer::kUser:
		{
			CArchMutexLock lock(m_mutex);
			event = removeEvent(dataID);
			return true;
		}

	default:
		assert(0 && "invalid event type");
		return false;
	}
}
예제 #2
0
bool
EventQueue::isEmpty() const
{
    return (m_buffer->isEmpty() && getNextTimerTimeout() != 0.0);
}
예제 #3
0
  bool SchedulerBase::Run()
  {
    uint32_t iter=0;
    TimeSpec timeout;
    TimeSpec immediate;
    bool gotEvents;

    if (!LogVerify(IsMainThread()))
      return false;

    m_isStarted = true;

    // Start with a quick event check.
    timeout = immediate;
    while (true)
    {
      iter++;

      if (m_wantsShutdown)
        break;

      // 
      //  Get event, or timeout. 
      // 
      gLog.Optional(Log::TimerDetail, "checking events (%u)", iter);
      gotEvents = waitForEvents(timeout);

      // By default the next event check is immediately.
      timeout = immediate;  

      // 
      // High priority timers, if any, get handled now 
      // 
      while (!m_wantsShutdown && expireTimer(Timer::Priority::Hi))
      { //nothing
      }

      if (m_wantsShutdown)
        break;

      // 
      //  Handle any events.
      // 
      if (gotEvents)
      {
        int socketId;

        gLog.Optional(Log::TimerDetail, "Handling events (%u)", iter);


        while (-1 != (socketId = getNextSocketEvent()))
        {
          // we have a socket event .. is it a socket or a signal?

          SocketItemHashMap::iterator foundSocket;
          SignalItemHashMap::iterator foundSignal;

          if (m_sockets.end() != (foundSocket = m_sockets.find(socketId)))
          {
            if (LogVerify(foundSocket->second.callback != NULL))
              foundSocket->second.callback(socketId, foundSocket->second.userdata);
          }
          else if (m_signals.end() != (foundSignal = m_signals.find(socketId)))
          {
            if (LogVerify(foundSignal->second.callback != NULL))
            {
              // 'Drain' the pipe.
              char drain[128];
              int result;
              size_t reads = 0;

              while ( 0 < (result = ::read(socketId, drain, sizeof(drain))))
                reads++;

              if (reads == 0 && result < 0)
                gLog.LogError("Failed to read from pipe %d: %s", socketId, strerror(errno));
              else if (result == 0)
                gLog.LogError("Signaling pipe write end for %d closed", socketId);

              foundSignal->second.callback(foundSignal->second.fdWrite, foundSignal->second.userdata);
            }
          }
          else
          {
            gLog.Optional(Log::TimerDetail, "Socket (%d) signaled with no handler (%u).", socketId, iter);
          }

          if (m_wantsShutdown)
            break;
        }

        if (m_wantsShutdown)
          break;
      }

      // 
      //  Handle a low priority timer if there are no events.
      //  TODO: starvation is a potential problem for low priority timers.
      // 
      if (!gotEvents && !expireTimer(Timer::Priority::Low))
      {
        // No events and no more timers, so we are ready to sleep again. 
        timeout = getNextTimerTimeout();
      }

      if (m_wantsShutdown)
        break;
    } // while true

    return true;
  }