| 274 | } |
| 275 | |
| 276 | void DeterministicTimer::exitFrameBoundary() |
| 277 | { |
| 278 | if (Global::shared_config.debug_state & SharedConfig::DEBUG_UNCONTROLLED_TIME) |
| 279 | return NonDeterministicTimer::get().exitFrameBoundary(); |
| 280 | |
| 281 | LOGTRACE(LCF_TIMEGET); |
| 282 | |
| 283 | /* Reset the counts of each time get function */ |
| 284 | for (int i = 0; i < SharedConfig::TIMETYPE_NUMTRACKEDTYPES; i++) { |
| 285 | main_gettimes[i] = 0; |
| 286 | sec_gettimes[i] = 0; |
| 287 | } |
| 288 | |
| 289 | /* We sleep the right amount of time so that the game runs at normal speed */ |
| 290 | |
| 291 | /* Get the current actual time */ |
| 292 | TimeHolder currentTime = TimeHolder::now(); |
| 293 | |
| 294 | /* If we are not fast forwarding, and not the first frame, |
| 295 | * then we wait the delta amount of time. |
| 296 | */ |
| 297 | if (Global::shared_config.running && !(Global::shared_config.fastforward && (Global::shared_config.fastforward_mode & SharedConfig::FF_SLEEP))) { |
| 298 | PROFILE_SCOPE("Sleep", PROFILER_INFO_FRAME); |
| 299 | PROFILE_PAUSE(PAUSE_ON_SLEEP); |
| 300 | |
| 301 | TimeHolder desiredTime = lastEnterTime + baseTimeIncrement * Global::shared_config.speed_divisor; |
| 302 | |
| 303 | TimeHolder sleepTimee = desiredTime - currentTime; |
| 304 | LOG(LL_DEBUG, LCF_TIMESET, "sleep for %u.%09u", sleepTimee.tv_sec, sleepTimee.tv_nsec); |
| 305 | |
| 306 | /* Call the real nanosleep function */ |
| 307 | perfTimer.switchTimer(PerfTimer::IdleTimer); |
| 308 | #ifdef __unix__ |
| 309 | NATIVECALL(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &desiredTime, NULL)); |
| 310 | #else |
| 311 | /* nanosleep() uses relative time */ |
| 312 | TimeHolder sleepTime = desiredTime - currentTime; |
| 313 | NATIVECALL(nanosleep(&sleepTime, NULL)); |
| 314 | #endif |
| 315 | perfTimer.switchTimer(PerfTimer::FrameTimer); |
| 316 | |
| 317 | /* We try to keep a contant fps, so we set the last enter time to the |
| 318 | * desired time, so that if the sleep time was not perfect, or the frame |
| 319 | * took too long to process, we may compensate on future frames. This |
| 320 | * needs a threshold, otherwise we will constantly try to catch up, and |
| 321 | * no sleep will happen */ |
| 322 | TimeHolder thresholdTime = lastEnterTime + baseTimeIncrement * (Global::shared_config.speed_divisor * 10); // Arbitrary value |
| 323 | |
| 324 | if (currentTime > thresholdTime) { |
| 325 | lastEnterTime = currentTime; |
| 326 | } |
| 327 | else { |
| 328 | lastEnterTime = desiredTime; |
| 329 | } |
| 330 | } |
| 331 | |
| 332 | insideFrameBoundary = false; |
| 333 | frame_mutex.unlock(); |
no test coverage detected