33 #include <IceUtil/Time.h> 
   34 #include <IceUtil/Timer.h> 
   53         virtual public IceUtil::TimerTask,
 
   54         virtual public Logging,
 
   55         virtual protected PeriodicTaskIceBase
 
   63         typedef void (
T::*method_type)(void);
 
   84                      method_type periodicFn,
 
   86                      bool assureMeanInterval = 
false,
 
   87                      std::string name = 
"",
 
   88                      bool forceSystemTime = 
true)
 
   92             functionExecuting = 
false;
 
   93             this->assureMeanInterval = assureMeanInterval;
 
   95             last_cpu_total_time = 0;
 
   96             this->periodicFn = periodicFn;
 
   97             this->parent = parent;
 
  101                 char* demangled = 
nullptr;
 
  103                 demangled = abi::__cxa_demangle(
typeid(
T).name(), 
nullptr, 
nullptr, &
status);
 
  112             intervalMs = periodMs;
 
  113             interval = IceUtil::Time::milliSeconds(periodMs);
 
  115             delayWarningTolerance = IceUtil::Time::milliSeconds(5);
 
  117             workloadList.resize(100, 0.f);
 
  118             setTag(
"PeriodicTask" + this->name);
 
  120             if (customThreadList)
 
  122                 customThreadList->addPeriodicTask(
this);
 
  129                 appThreadList->addPeriodicTask(
this);
 
  141                 appThreadList->removePeriodicTask(
this);
 
  144             if (customThreadList)
 
  146                 customThreadList->removePeriodicTask(
this);
 
  167             this->customThreadList = threadList;
 
  171                 threadList->addPeriodicTask(
this);
 
  181             std::unique_lock lock(dataMutex);
 
  183             if (app && app->getForbidThreadCreation())
 
  185                 throw LocalException()
 
  186                     << 
"Thread creation is now allowed in this application at the point in time! " 
  187                        "Use Application::getInstance()->getThreadPool() instead.";
 
  192                 cycleStart = logTime = __now();
 
  193                 startTime = logTime.toMicroSeconds();
 
  194                 timeExceeded = 
false;
 
  195                 timer->schedule(
this, IceUtil::Time::milliSeconds(0));
 
  217             delayWarningTolerance = IceUtil::Time::milliSeconds(newToleranceInMilliSeconds);
 
  230             std::unique_lock lock(dataMutex);
 
  232             if (
interval.toMilliSeconds() == intervalInMs)
 
  237             intervalMs = intervalInMs;
 
  238             interval = IceUtil::Time::milliSeconds(intervalInMs);
 
  251             std::unique_lock lock(dataMutex);
 
  284             std::unique_lock lock(mutexFunctionExecuting);
 
  285             return functionExecuting;
 
  291         const PeriodicTaskIceBase&
 
  294             const PeriodicTaskIceBase* base = 
dynamic_cast<const PeriodicTaskIceBase*
>(
this);
 
  300         runTimerTask()
 override 
  303                 std::unique_lock lock(mutexFunctionExecuting);
 
  304                 functionExecuting = 
true;
 
  308                 std::unique_lock lock(dataMutex);
 
  311                 idleDuration = __now() - cycleStart - cycleDuration;
 
  312                 cycleStart = __now();
 
  313                 lastCycleStartTime = cycleStart.toMicroSeconds();
 
  319                 (parent->*periodicFn)();
 
  327                 std::unique_lock lock2(dataMutex);
 
  328                 std::unique_lock lock(mutexFunctionExecuting);
 
  330                 cycleDuration = __now() - cycleStart;
 
  331                 lastCycleDuration = cycleDuration.toMicroSeconds();
 
  332                 __checkTimeslotUsage();
 
  333                 __getCPULoad(idleDuration);
 
  335                 functionExecuting = 
false;
 
  342             std::unique_lock lock(mutexFunctionExecuting);
 
  343             startTime = __now().toMicroSeconds();
 
  344             executionCounter = 0;
 
  346             if (functionExecuting)
 
  355                            << 
" ms." << std::endl;
 
  366                 if (assureMeanInterval)
 
  368                     newInterval = IceUtil::Time::microSeconds(
 
  369                                       startTime + 
interval.toMicroSeconds() * executionCounter) -
 
  374                     newInterval = 
interval - IceUtil::Time::microSeconds(lastCycleDuration);
 
  377                 if (newInterval.toMicroSeconds() < 0)
 
  379                     newInterval = IceUtil::Time::microSeconds(0);
 
  384                     timer->schedule(
this, newInterval);
 
  390         __checkTimeslotUsage()
 
  392             if (
interval + delayWarningTolerance < cycleDuration)
 
  395                 executionTime = cycleDuration.toMilliSeconds();
 
  398             float logInterval = 10.0f;
 
  403                                  << 
"' took " << executionTime << 
" [ms] instead of the requested " 
  405                                  << 
" [ms] (this message is only posted every " << logInterval
 
  407                 timeExceeded = 
false;
 
  414             double threadCPUUsage = -1;
 
  418             if (clock_gettime(CLOCK_REALTIME, &st) != -1 &&
 
  419                 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &usage) != -1)
 
  421                 double current_cpu_thread_time = 
static_cast<double>(usage.tv_sec) +
 
  422                                                  static_cast<double>(usage.tv_nsec) / 1
'000'000
'000; 
  423                 double current_cpu_total_time = static_cast<double>(st.tv_sec) + 
  424                                                 static_cast<double>(st.tv_nsec) / 1'000
'000'000;
 
  426                 if (last_cpu_total_time != 0)
 
  428                     threadCPUUsage = (current_cpu_thread_time - last_cpu_thread_time) /
 
  429                                      (current_cpu_total_time - last_cpu_total_time);
 
  432                 last_cpu_total_time = current_cpu_total_time;
 
  433                 last_cpu_thread_time = current_cpu_thread_time;
 
  438                 threadCPUUsage = 
static_cast<double>(lastCycleDuration) /
 
  439                                  (lastCycleDuration + idleDuration.toMicroSeconds());
 
  442             if (threadCPUUsage > 0)
 
  444                 workloadList.push_back(threadCPUUsage);
 
  446                 if (workloadList.size() > 100.f * 1.5f)
 
  448                     workloadList.erase(workloadList.begin(), workloadList.begin() + 50);
 
  456             if (timer->getUseSystemTime())
 
  458                 return IceUtil::Time::now();
 
  468         method_type periodicFn;
 
  476         IceUtil::Int64 executionTime;
 
  477         IceUtil::Int64 executionCounter;
 
  483         double last_cpu_total_time;
 
  484         double last_cpu_thread_time;
 
  488         bool assureMeanInterval;
 
  490         mutable std::mutex mutexFunctionExecuting;
 
  491         bool functionExecuting;
 
  492         mutable std::mutex dataMutex;