Пример #1
0
void Application::UpdateFrame()
{
    // Don't pump the QEvents to QApplication if we are exiting
    // also don't process our mainloop frames.
    if (framework->IsExiting())
        return;

    try
    {
        const tick_t frameStartTime = GetCurrentClockTime();

        QApplication::processEvents(QEventLoop::AllEvents, 1);
        QApplication::sendPostedEvents();

        framework->ProcessOneFrame();

        tick_t timeNow = GetCurrentClockTime();

        static tick_t timerFrequency = GetCurrentClockFreq();

        double msecsSpentInFrame = (double)(timeNow - frameStartTime) * 1000.0 / timerFrequency;

        const double msecsPerFrame = 1000.0 / (targetFpsLimit <= 1.0 ? 1000.0 : targetFpsLimit);
        double msecsPerFrameWhenInactive = 1000.0 / (targetFpsLimitWhenInactive <= 1.0 ? 1000.0 : targetFpsLimitWhenInactive);

        ///\note Ideally we should sleep 0 msecs when running at a high fps rate,
        /// but need to avoid QTimer::start() with 0 msecs, since that will cause the timer to immediately fire,
        /// which can cause the Win32 message loop inside Qt to starve. (Qt keeps spinning the timer.start(0) loop for Tundra mainloop and neglects Win32 API).
        double msecsToSleep = std::min(std::max(1.0, msecsPerFrame - msecsSpentInFrame), msecsPerFrame);
        double msecsToSleepWhenInactive = std::min(std::max(1.0, msecsPerFrameWhenInactive - msecsSpentInFrame), msecsPerFrameWhenInactive);

        // Reduce frame rate when unfocused
        if (!frameUpdateTimer.isActive())
        {
            if (appActivated || framework->IsHeadless())
                frameUpdateTimer.start((int)msecsToSleep);
            else
                frameUpdateTimer.start((int)(msecsToSleepWhenInactive)); // Cap FPS when window is inactive
        }
    }
    catch(const std::exception &e)
    {
        std::string error("Application::UpdateFrame caught an exception: " + std::string(e.what() ? e.what() : "(null)"));
        std::cout << error << std::endl;
        LogError(error);
        throw;
    }
    catch(...)
    {
        std::string error("Application::UpdateFrame caught an unknown exception!");
        std::cout << error << std::endl;
        LogError(error);
        throw;
    }
}
Пример #2
0
    /// Polls the inbound socket until the message queue is empty. Also resends any timed out reliable messages.
    void NetMessageManager::ProcessMessages()
    {
        PROFILE (NetMessageManager_ProcessMessages);
        if (!connection)
            return;

        if (!ResendQueueIsEmpty())
            ProcessResendQueue();

        // Process network messages for max. 0.1 seconds, to prevent lack of rendering/mainloop execution during heavy processing
        static const double MAX_PROCESS_TIME = 0.1;
        boost::timer timer;

        PROFILE(NetMessageManager_WhilePacketsAvailable);
        while(connection->PacketsAvailable() && timer.elapsed() < MAX_PROCESS_TIME)
        {
            const int cMaxPayload = 2048;
            std::vector<uint8_t> data(cMaxPayload, 0);
            int numBytes = connection->ReceiveBytes(&data[0], cMaxPayload);
            if (numBytes == 0)
                break;

            data.resize(numBytes);

            tick_t now = GetCurrentClockTime();
            lastHeardSince = (double)(now - lastHeardSinceTick) / GetCurrentClockFreq() * 1000;
            lastHeardSinceTick = now;

#ifdef PROTOCOL_STRESS_TEST
            const int numDuplications = 10;
            const double bitErrorRate = 0.05;
            for(int i = 0; i < numDuplications; ++i)
            {
#endif
                HandleInboundBytes(data);
#ifdef PROTOCOL_STRESS_TEST
                FlipBits(data, (int)ceil(data.size() * bitErrorRate));
            }
#endif
        }
        if (!connection->Open())
            connection.reset();

        // To keep memory footprint down and to defend against memory attacks, keep the list of seen sequence numbers to a fixed size.
        const size_t cMaxSeqNumMemorySize = 300;
        while(receivedSequenceNumbers.size() > cMaxSeqNumMemorySize)
            receivedSequenceNumbers.erase(receivedSequenceNumbers.begin()); // We remove from the front to guarantee the smallest(oldest) are removed first.

        // Acknowledge all the new accumulated packets that the server sent as reliable.
        SendPendingACKs();

        ManagePingSends();
    }
Пример #3
0
    void NetMessageManager::HandleCompletePingCheck(NetInMessage *msg)
    {
        msg->ResetReading();
        uint8_t id = msg->ReadU8();

        std::map<uint8_t, tick_t>::iterator it = pendingPings.find(id);
        if (it == pendingPings.end())
        {
            std::cout << "Reveiced CompletePingCheck with false ID" << std::endl;
            return;
        }

        tick_t timeNow = GetCurrentClockTime();
        lastRoundTripTime = (double)(timeNow - it->second) / GetCurrentClockFreq() * 1000;

        const float alpha = 3.f/4.f;
        smoothenedRoundTripTime = smoothenedRoundTripTime * alpha + (1.f - alpha) * lastRoundTripTime;

        pendingPings.erase(it);
    }