예제 #1
0
  void PeriodicTaskPrivate::_wrap()
  {
    if (*_state == Task_Stopped)
      qiLogError()  << "PeriodicTask inconsistency: stopped from callback";
    /* To avoid being stuck because of unhandled transition, the rule is
    * that any other thread playing with our state can only do so
    * to stop us, and must eventualy reach the Stopping state
    */
    if (_state.setIfEquals(Task_Stopping, Task_Stopped))
      return;
    /* reschedule() needs to call async() before reseting state from rescheduling
    *  to scheduled, to protect the _task object. So we might still be
    * in rescheduling state here.
    */
    while (*_state == Task_Rescheduling)
      boost::this_thread::yield();
    // order matters! check scheduled state first as the state cannot change
    // from triggering to scheduled but can change in the other way
    if (!_state.setIfEquals(Task_Scheduled, Task_Running) &&
        !_state.setIfEquals(Task_Triggering, Task_Running))
    {
      setState(_state, Task_Stopping, Task_Stopped);
      return;
    }
    bool shouldAbort = false;
    qi::int64_t wall = 0, now=0, delta=0;
    qi::int64_t usr, sys;
    bool compensate = _compensateCallTime; // we don't want that bool to change in the middle
    try
    {
      wall = qi::os::ustime();
      std::pair<qi::int64_t, qi::int64_t> cpu = qi::os::cputime();
      _tid = os::gettid();
      _callback();
      _tid = invalidThreadId;
      now = qi::os::ustime();
      wall = now - wall;
      std::pair<qi::int64_t, qi::int64_t> cpu2 = qi::os::cputime();
      usr = cpu2.first - cpu.first;
      sys = cpu2.second - cpu.second;
      if (compensate)
        delta = wall;
    }
    catch (const std::exception& e)
    {
      qiLogInfo() << "Exception in task " << _name << ": " << e.what();
      shouldAbort = true;
    }
    catch(...)
    {
      qiLogInfo() << "Unknown exception in task callback.";
      shouldAbort = true;
    }
    if (shouldAbort)
    {
      setState(_state, Task_Stopping, Task_Stopped,
                       Task_Running, Task_Stopped);
      return;
    }
    else
    {
      _callStats.push((float)wall / 1e6f, (float)usr / 1e6f, (float)sys / 1e6f);

      if (now - _statsDisplayTime >= 20000000)
      {
        float secTime = float(now - _statsDisplayTime) / 1e6f;
        _statsDisplayTime = now;
        unsigned int count = _callStats.count();
        std::string catName = "stats." + _name;
        qiLogVerbose(catName.c_str())
          << (_callStats.user().cumulatedValue() * 100.0 / secTime)
          << "%  "
          << count
          << "  " << _callStats.wall().asString(count)
          << "  " << _callStats.user().asString(count)
          << "  " << _callStats.system().asString(count)
          ;
        _callStats.reset();
      }

      if (!_state.setIfEquals(Task_Running, Task_Rescheduling))
      { // If we are not in running state anymore, someone switched us
        // to stopping
        setState(_state, Task_Stopping, Task_Stopped);
        return;
      }
      _reschedule(std::max((qi::int64_t)0, _usPeriod - delta));
    }
  }
예제 #2
0
  void PeriodicTaskPrivate::_wrap()
  {
    qiLogDebug() << "callback start";
    {
      boost::mutex::scoped_lock l(_mutex);
      QI_ASSERT(_state != TaskState::Stopped);
      /* To avoid being stuck because of unhandled transition, the rule is
       * that any other thread playing with our state can only do so
       * to stop us, and must eventualy reach the Stopping state
       */
      if (_state == TaskState::Stopping)
      {
        _state = TaskState::Stopped;
        _cond.notify_all();
        return;
      }
      QI_ASSERT(_state == TaskState::Scheduled || _state == TaskState::Triggering);
      _state = TaskState::Running;
      _cond.notify_all();
    }
    bool shouldAbort = false;
    qi::SteadyClockTimePoint now;
    qi::Duration delta;
    qi::int64_t usr, sys;
    bool compensate = _compensateCallTime; // we don't want that bool to change in the middle
    try
    {
      qi::SteadyClockTimePoint start = qi::SteadyClock::now();
      std::pair<qi::int64_t, qi::int64_t> cpu = qi::os::cputime();
      _tid = os::gettid();
      _callback();
      _tid = invalidThreadId;
      now = qi::SteadyClock::now();
      delta = now - start;
      std::pair<qi::int64_t, qi::int64_t> cpu2 = qi::os::cputime();
      usr = cpu2.first - cpu.first;
      sys = cpu2.second - cpu.second;
    }
    catch (const std::exception& e)
    {
      qiLogInfo() << "Exception in task " << _name << ": " << e.what();
      shouldAbort = true;
    }
    catch(...)
    {
      qiLogInfo() << "Unknown exception in task callback.";
      shouldAbort = true;
    }
    if (shouldAbort)
    {
      qiLogDebug() << "should abort, bye";
      boost::mutex::scoped_lock l(_mutex);
      _state = TaskState::Stopped;
      _cond.notify_all();
      return;
    }
    else
    {
      _callStats.push(
          (float)boost::chrono::duration_cast<qi::MicroSeconds>(delta).count() / 1e6f,
          (float)usr / 1e6f,
          (float)sys / 1e6f);

      if (now - _statsDisplayTime >= qi::Seconds(20))
      {
        float secTime = float(boost::chrono::duration_cast<qi::MicroSeconds>(now - _statsDisplayTime).count()) / 1e6f;
        _statsDisplayTime = now;
        unsigned int count = _callStats.count();
        std::string catName = "stats." + _name;
        qiLogVerbose(catName.c_str())
          << (_callStats.user().cumulatedValue() * 100.0 / secTime)
          << "%  "
          << count
          << "  " << _callStats.wall().asString(count)
          << "  " << _callStats.user().asString(count)
          << "  " << _callStats.system().asString(count)
          ;
        _callStats.reset();
      }

      qiLogDebug() << "continuing";
      {
        boost::mutex::scoped_lock l(_mutex);
        if (_state != TaskState::Running)
        {
          qiLogDebug() << "continuing " << static_cast<int>(_state);
          QI_ASSERT(_state == TaskState::Stopping);
          _state = TaskState::Stopped;
          _cond.notify_all();
          return;
        }
        _reschedule(std::max(qi::Duration(0), _period - (compensate ? delta : qi::Duration(0))));
      }
    }
  }