/** * Creates a new game according to the settings the user made. * * @param factory Player factory to use to create the players. * @return New game. */ QSharedPointer< ::Game::Game> NewGame::createGame(::Game::Players::Factory& factory) const { QSharedPointer< ::GameLogic::FourInALine::Game> fourInALine; QSharedPointer< ::Game::Game> game; auto firstPlayer = this->createFirstPlayer(factory); auto secondPlayer = this->createSecondPlayer(factory); auto boardConfigurationWidget = this->gameSetupWidget->getBoardConfigurationWidget(); auto timeLimitConfigurationWidget = this->gameSetupWidget->getTimeLimitConfigurationWidget(); auto gameConfigurationWidget = this->gameSetupWidget->getGameConfigurationWidget(); unsigned int nRows = boardConfigurationWidget->getNumberOfRows(); unsigned int nColumns = boardConfigurationWidget->getNumberOfColumns(); unsigned int firstMove = gameConfigurationWidget->getFirstMove(); fourInALine.reset(new ::GameLogic::FourInALine::Game(nRows, nColumns, firstMove)); if (timeLimitConfigurationWidget->hasTimeLimit()) { fourInALine->setTimeLimit(timeLimitConfigurationWidget->getTimeLimit()); fourInALine->setTimeoutAction(timeLimitConfigurationWidget->getTimeoutAction()); } game = QSharedPointer< ::Game::Game>(new ::Game::Game(fourInALine, firstPlayer, secondPlayer)); game->setAllowHint(gameConfigurationWidget->isAllowHintEnabled() && gameConfigurationWidget->getAllowHint()); game->setAllowUndo(gameConfigurationWidget->isAllowUndoEnabled() && gameConfigurationWidget->getAllowUndo()); game->setSaveHighscore(gameConfigurationWidget->isSaveHighscoreEnabled() && gameConfigurationWidget->getSaveHighscore()); return game; }
void Watchdog::enteredVM() { m_hasEnteredVM = true; if (hasTimeLimit()) { LockHolder locker(m_lock); startTimer(locker, m_timeLimit); } }
bool Watchdog::didFireSlow(ExecState* exec) { { LockHolder locker(m_lock); ASSERT(m_timerDidFire); m_timerDidFire = false; if (currentWallClockTime() < m_wallClockDeadline) return false; // Just a stale timer firing. Nothing to do. // Set m_wallClockDeadline to noTimeLimit here so that we can reject all future // spurious wakes. m_wallClockDeadline = noTimeLimit; auto cpuTime = currentCPUTime(); if (cpuTime < m_cpuDeadline) { auto remainingCPUTime = m_cpuDeadline - cpuTime; startTimer(locker, remainingCPUTime); return false; } } // Note: we should not be holding the lock while calling the callbacks. The callbacks may // call setTimeLimit() which will try to lock as well. // If m_callback is not set, then we terminate by default. // Else, we let m_callback decide if we should terminate or not. bool needsTermination = !m_callback || m_callback(exec, m_callbackData1, m_callbackData2); if (needsTermination) return true; { LockHolder locker(m_lock); // If we get here, then the callback above did not want to terminate execution. As a // result, the callback may have done one of the following: // 1. cleared the time limit (i.e. watchdog is disabled), // 2. set a new time limit via Watchdog::setTimeLimit(), or // 3. did nothing (i.e. allow another cycle of the current time limit). // // In the case of 1, we don't have to do anything. // In the case of 2, Watchdog::setTimeLimit() would already have started the timer. // In the case of 3, we need to re-start the timer here. ASSERT(m_hasEnteredVM); bool callbackAlreadyStartedTimer = (m_cpuDeadline != noTimeLimit); if (hasTimeLimit() && !callbackAlreadyStartedTimer) startTimer(locker, m_timeLimit); } return false; }
void Watchdog::setTimeLimit(std::chrono::microseconds limit, ShouldTerminateCallback callback, void* data1, void* data2) { LockHolder locker(m_lock); m_timeLimit = limit; m_callback = callback; m_callbackData1 = data1; m_callbackData2 = data2; if (m_hasEnteredVM && hasTimeLimit()) startTimer(locker, m_timeLimit); }
void Watchdog::startTimer(LockHolder&, std::chrono::microseconds timeLimit) { ASSERT(m_hasEnteredVM); ASSERT(hasTimeLimit()); ASSERT(timeLimit <= m_timeLimit); m_cpuDeadline = currentCPUTime() + timeLimit; auto wallClockTime = currentWallClockTime(); auto wallClockDeadline = wallClockTime + timeLimit; if ((wallClockTime < m_wallClockDeadline) && (m_wallClockDeadline <= wallClockDeadline)) return; // Wait for the current active timer to expire before starting a new one. // Else, the current active timer won't fire soon enough. So, start a new timer. this->ref(); // m_timerHandler will deref to match later. m_wallClockDeadline = wallClockDeadline; m_timerQueue->dispatchAfter(std::chrono::nanoseconds(timeLimit), m_timerHandler); }