void Ext::DefaultCpuDispatcher::submitTask(PxBaseTask& task) { if(!mNumThreads) { // no worker threads, run directly task.runProfiled(); task.release(); return; } Ps::Thread::Id currentThread = Ps::Thread::getId(); // TODO: Could use TLS to make this more efficient for(PxU32 i = 0; i < mNumThreads; ++i) { if(mWorkerThreads[i].tryAcceptJobToLocalQueue(task, currentThread)) return mWorkReady.set(); } SharedQueueEntry* entry = mQueueEntryPool.getEntry(&task); if (entry) { mJobList.push(*entry); mWorkReady.set(); } }
void Ext::CpuWorkerThread::execute() { mThreadId = getId(); while (!quitIsSignalled()) { mOwner->resetWakeSignal(); PxBaseTask* task = TaskQueueHelper::fetchTask(mLocalJobList, mQueueEntryPool); if(!task) task = mOwner->fetchNextTask(); if (task) { mOwner->runTask(*task); task->release(); } else { mOwner->waitForWork(); } } quit(); }
void Ext::DefaultCpuDispatcher::runTask(PxBaseTask& task) { #ifdef PX_PROFILE task.runProfiled(); #else task.run(); #endif }
virtual void release() { // We used to do Task::release(); here before fixing DE1106 (xbox pure virtual crash) // Release in turn causes the dependent tasks to start running // The problem was that between the time release was called and by the time we got to the destructor // The task chain would get all the way to scene finalization code which would reset the allocation pool // And a new task would get allocated at the same address, then we would invoke the destructor on that freshly created task // This could potentially cause any number of other problems, it is suprising that it only manifested itself // as a pure virtual crash PxBaseTask* saveContinuation = mCont; this->~PxsCMUpdateTask(); if (saveContinuation) saveContinuation->removeReference(); }
void CpuWorkerThread::execute() { mThreadId = getId(); while (!quitIsSignalled()) { mOwner->resetWakeSignal(); PxBaseTask* task = TaskQueueHelper::fetchTask(mLocalJobList, mQueueEntryPool); if (!task) { task = mOwner->getJob(); } if (!task) { task = mOwner->stealJob(); } if (task) { #if PHYSX_PROFILE_SDK if (mPvdBinding!=NULL) { task->runProfiled(); } else { task->run(); } #else task->run(); #endif task->release(); } else { mOwner->waitForWork(); } } quit(); };
/* * \brief Called by dispatcher after Task has been run. * * If you re-implement this method, you must call this base class * version before returning. */ void FetchResultsTask::release() { PxTask::release(); // copy mFollowingTask into local variable, because it might be overwritten // as soon as mFetchResultsReady.set() is called (and before removeReference() is called on it) PxBaseTask* followingTask = mFollowingTask; mFollowingTask = NULL; // Allow ApexScene::fetchResults() to run (potentially unblocking game thread) mScene->mFetchResultsReady.set(); // remove reference to the scene completion task submitted in Scene::simulate // this must be done after the scene's mFetchResultsReady event is set so that the // app's completion task can be assured that fetchResults is ready to run if (followingTask) { followingTask->removeReference(); } }
void FPhysXCPUDispatcherSingleThread::submitTask( PxBaseTask& Task ) { SCOPE_CYCLE_COUNTER(STAT_PhysXSingleThread); check(IsInGameThread()); TaskStack.Push(&Task); if (TaskStack.Num() > 1) { return; } Task.run(); Task.release(); while (TaskStack.Num() > 1) { PxBaseTask& ChildTask = *TaskStack.Pop(); ChildTask.run(); ChildTask.release(); } verify(&Task == TaskStack.Pop() && !TaskStack.Num()); }
void PxTaskMgr::emitStopEvent(PxBaseTask& basetask, uint32_t threadId) { PxBaseTask* tmp = &basetask; PX_UNUSED(tmp); PX_UNUSED(threadId); /* This does not need a lock! */ #if PX_SUPPORT_PXTASK_PROFILING //PX_COMPILE_TIME_ASSERT(sizeof(PxProfileEventId::mEventId) == sizeof(PxBaseTask::mEventID)); PX_PROFILE_STOP_CROSSTHREAD(basetask.getName(),0); #endif }