void spring_time::sleep(bool forceThreadSleep) { if (forceThreadSleep) { spring::this_thread::sleep_for(chrono::nanoseconds(toNanoSecsi())); return; } // for very short time intervals use a yielding loop (yield is ~5x more accurate than sleep(), check the UnitTest) if (toMicroSecsi() < (avgThreadSleepTimeMicroSecs + avgThreadYieldTimeMicroSecs * 5)) { const spring_time s = gettime(); while ((gettime() - s) < *this) thread_yield(); return; } // expected wakeup time const spring_time t0 = gettime() + *this; spring::this_thread::sleep_for(chrono::nanoseconds(toNanoSecsi())); const spring_time t1 = gettime(); const spring_time dt = t1 - t0; if (t1 >= t0) { // yes, it's not 100% thread correct, but it's okay when 1 of 1 million writes is dropped int avg = avgThreadSleepTimeMicroSecs.load(); int newAvg = mix<float>(avg, dt.toMicroSecsf(), 0.1f); avgThreadSleepTimeMicroSecs.store(newAvg); } }
void spring_time::sleep() { // for very short time intervals use a yielding loop (yield is ~5x more accurate than sleep(), check the UnitTest) if (toMilliSecsf() < (avgSleepErrMs + avgYieldMs * 5.0f)) { const spring_time s = gettime(); while ((gettime() - s) < *this) { thread_yield(); } return; } const spring_time expectedWakeUpTime = gettime() + *this; #if defined(SPRINGTIME_USING_STD_SLEEP) this_thread::sleep_for(chrono::nanoseconds(toNanoSecsi())); #else boost::this_thread::sleep(boost::posix_time::microseconds(std::ceil(toNanoSecsf() * 1e-3))); #endif const float diffMs = (gettime() - expectedWakeUpTime).toMilliSecsf(); avgSleepErrMs = avgSleepErrMs * 0.9f + diffMs * 0.1f; //if (diffMs > 7.0f) { // LOG_L(L_WARNING, "SpringTime: used sleep() function is too inaccurate"); //} }
void spring_time::sleep() { // for very short time intervals use a yielding loop (yield is ~5x more accurate than sleep(), check the UnitTest) if (toMilliSecsf() < (avgThreadSleepTimeMilliSecs + avgThreadYieldTimeMilliSecs * 5.0f)) { const spring_time s = gettime(); while ((gettime() - s) < *this) thread_yield(); return; } // expected wakeup time const spring_time t0 = gettime() + *this; #if defined(SPRINGTIME_USING_STD_SLEEP) this_thread::sleep_for(chrono::nanoseconds(toNanoSecsi())); #else boost::this_thread::sleep(boost::posix_time::microseconds(std::ceil(toNanoSecsf() * 1e-3))); #endif const spring_time t1 = gettime(); const spring_time dt = t1 - t0; if (t1 >= t0) { boost::mutex::scoped_lock lock(sleepTimeMutex); avgThreadSleepTimeMilliSecs = mix(avgThreadSleepTimeMilliSecs, dt.toMilliSecsf(), 0.1f); } }
void spring_time::sleep_until() { #if defined(SPRINGTIME_USING_STD_SLEEP) auto tp = chrono::time_point<chrono::high_resolution_clock, chrono::nanoseconds>(chrono::nanoseconds(toNanoSecsi())); this_thread::sleep_until(tp); #else spring_time napTime = gettime() - *this; if (napTime.toMilliSecsf() < avgYieldMs) { while (napTime.isTime()) { thread_yield(); napTime = gettime() - *this; } return; } napTime.sleep(); #endif }
void spring_time::sleep_until() { auto tp = chrono::time_point<chrono::high_resolution_clock, chrono::nanoseconds>(chrono::nanoseconds(toNanoSecsi())); this_thread::sleep_until(tp); }