bool AvatarUpdate::process() { PerformanceTimer perfTimer("AvatarUpdate"); quint64 start = usecTimestampNow(); quint64 deltaMicroseconds = start - _lastAvatarUpdate; _lastAvatarUpdate = start; float deltaSeconds = (float) deltaMicroseconds / (float) USECS_PER_SECOND; Application::getInstance()->setAvatarSimrateSample(1.0f / deltaSeconds); QSharedPointer<AvatarManager> manager = DependencyManager::get<AvatarManager>(); MyAvatar* myAvatar = manager->getMyAvatar(); //loop through all the other avatars and simulate them... //gets current lookat data, removes missing avatars, etc. manager->updateOtherAvatars(deltaSeconds); myAvatar->startUpdate(); Application::getInstance()->updateMyAvatarLookAtPosition(); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes manager->updateMyAvatar(deltaSeconds); myAvatar->endUpdate(); if (!isThreaded()) { return true; } int elapsed = (usecTimestampNow() - start); int usecToSleep = _targetInterval - elapsed; if (usecToSleep < 0) { usecToSleep = 1; // always yield } usleep(usecToSleep); return true; }
void AvatarUpdate::synchronousProcess() { // Keep our own updated value, so that our asynchronous code can consult it. _isHMDMode = Application::getInstance()->isHMDMode(); _headPose = Application::getInstance()->getActiveDisplayPlugin()->getHeadPose(); if (_updateBillboard) { Application::getInstance()->getMyAvatar()->doUpdateBillboard(); } if (!isThreaded()) { process(); } }
bool Pipe::_cmdConfigInit( co::ICommand& cmd ) { LB_TS_THREAD( _pipeThread ); co::ObjectICommand command( cmd ); const uint128_t initID = command.get< uint128_t >(); const uint32_t frameNumber = command.get< uint32_t >(); LBLOG( LOG_INIT ) << "Init pipe " << command << " init id " << initID << " frame " << frameNumber << std::endl; if( !isThreaded( )) { _impl->windowSystem = selectWindowSystem(); _setupCommandQueue(); } setError( ERROR_NONE ); Node* node = getNode(); LBASSERT( node ); node->waitInitialized(); bool result = false; if( node->isRunning( )) { _impl->currentFrame = frameNumber; _impl->finishedFrame = frameNumber; _impl->unlockedFrame = frameNumber; _impl->state = STATE_INITIALIZING; result = configInit( initID ); if( result ) _impl->state = STATE_RUNNING; } else setError( ERROR_PIPE_NODE_NOTRUNNING ); LBLOG( LOG_INIT ) << "TASK pipe config init reply result " << result << std::endl; co::NodePtr netNode = command.getNode(); commit(); send( netNode, fabric::CMD_PIPE_CONFIG_INIT_REPLY ) << result; return true; }
bool PacketSender::process() { if (isThreaded()) { return threadedProcess(); } return nonThreadedProcess(); }
bool PacketSender::process() { uint64_t USECS_PER_SECOND = 1000 * 1000; uint64_t SEND_INTERVAL_USECS = (_packetsPerSecond == 0) ? USECS_PER_SECOND : (USECS_PER_SECOND / _packetsPerSecond); // keep track of our process call times, so we have a reliable account of how often our caller calls us uint64_t now = usecTimestampNow(); uint64_t elapsedSinceLastCall = now - _lastProcessCallTime; _lastProcessCallTime = now; _averageProcessCallTime.updateAverage(elapsedSinceLastCall); if (_packets.size() == 0) { if (isThreaded()) { usleep(SEND_INTERVAL_USECS); } else { return isStillRunning(); // in non-threaded mode, if there's nothing to do, just return, keep running till they terminate us } } int packetsPerCall = _packets.size(); // in threaded mode, we just empty this! int packetsThisCall = 0; // if we're in non-threaded mode, then we actually need to determine how many packets to send per call to process // based on how often we get called... We do this by keeping a running average of our call times, and we determine // how many packets to send per call if (!isThreaded()) { int averageCallTime; const int TRUST_AVERAGE_AFTER = AVERAGE_CALL_TIME_SAMPLES * 2; if (_usecsPerProcessCallHint == 0 || _averageProcessCallTime.getSampleCount() > TRUST_AVERAGE_AFTER) { averageCallTime = _averageProcessCallTime.getAverage(); } else { averageCallTime = _usecsPerProcessCallHint; } // we can determine how many packets we need to send per call to achieve our desired // packets per second send rate. int callsPerSecond = USECS_PER_SECOND / averageCallTime; packetsPerCall = ceil(_packetsPerSecond / callsPerSecond); // send at least one packet per call, if we have it if (packetsPerCall < 1) { packetsPerCall = 1; } } int packetsLeft = _packets.size(); bool keepGoing = packetsLeft > 0; while (keepGoing) { NetworkPacket& packet = _packets.front(); // send the packet through the NodeList... UDPSocket* nodeSocket = NodeList::getInstance()->getNodeSocket(); nodeSocket->send(&packet.getAddress(), packet.getData(), packet.getLength()); packetsThisCall++; if (_notify) { _notify->packetSentNotification(packet.getLength()); } lock(); _packets.erase(_packets.begin()); unlock(); packetsLeft = _packets.size(); // in threaded mode, we go till we're empty if (isThreaded()) { keepGoing = packetsLeft > 0; // dynamically sleep until we need to fire off the next set of voxels we only sleep in threaded mode if (keepGoing) { uint64_t elapsed = now - _lastSendTime; int usecToSleep = std::max(SEND_INTERVAL_USECS, SEND_INTERVAL_USECS - elapsed); // we only sleep in non-threaded mode if (usecToSleep > 0) { usleep(usecToSleep); } } } else { // in non-threaded mode, we send as many packets as we need per expected call to process() keepGoing = (packetsThisCall < packetsPerCall) && (packetsLeft > 0); } _lastSendTime = now; } return isStillRunning(); // keep running till they terminate us }
GenericThread::~GenericThread() { // we only need to call terminate() if we're actually threaded and still running if (isStillRunning() && isThreaded()) { terminate(); } }