void ThreadManager::pushMessage(uint8_t destthread, MessageQueueObject* msg) { { boost::lock_guard<boost::mutex> lLock(*mMutexes[destthread]); mPerThreadMessageQueue[destthread]->push_back(msg); } // release lock now mCondVars[destthread]->notify_one(); }
/*! * \brief Finishes initializing all previously recorded objects * * Submits internal vulkan command buffer */ bool rSceneBase::endInitObject() { if ( !vInitializingObjects ) { eLOG( "beginInitObject was NOT called on secene ", vName_str ); return false; } vkEndCommandBuffer( vInitBuff_vk ); VkSubmitInfo lInfo = {}; lInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; lInfo.pNext = nullptr; lInfo.waitSemaphoreCount = 0; lInfo.pWaitSemaphores = nullptr; lInfo.pWaitDstStageMask = nullptr; lInfo.commandBufferCount = 1; lInfo.pCommandBuffers = &vInitBuff_vk; lInfo.signalSemaphoreCount = 0; lInfo.pSignalSemaphores = nullptr; auto lFence = vWorldPtr->createFence(); VkResult lRes; { std::lock_guard<std::mutex> lLock( vWorldPtr->getInitPtr()->getQueueMutex( vInitQueue_vk ) ); lRes = vkQueueSubmit( vInitQueue_vk, 1, &lInfo, lFence ); } if ( lRes ) { eLOG( "'vkQueueSubmit' returned ", uEnum2Str::toStr( lRes ) ); vInitObjs.clear(); vObjectsInit_MUT.unlock(); return false; } lRes = vkWaitForFences( vWorldPtr->getDevice(), 1, &lFence, VK_TRUE, UINT64_MAX ); if ( lRes ) { eLOG( "'vkQueueSubmit' returned ", uEnum2Str::toStr( lRes ) ); } for ( auto &i : vInitObjs ) i->finishData(); vkDestroyFence( vWorldPtr->getDevice(), lFence, nullptr ); vkFreeCommandBuffers( vWorldPtr->getDevice(), vInitPool_vk, 1, &vInitBuff_vk ); vInitObjs.clear(); vInitializingObjects = false; vObjectsInit_MUT.unlock(); return true; }
long detachStepping(bool & pDetached) { MVTestsPortability::MutexP lLock(&mSteppingL); long const lResult = mStep; if (pDetached) return lResult; pDetached = true; mStepCntReset--; if (0 == --mStepCnt) { InterlockedIncrement(&mStep); mStepCnt = mStepCntReset; } return lResult; }
void nextStep(long pWaitForStep = -1) { long lWaitForStep = pWaitForStep; { MVTestsPortability::MutexP lLock(&mSteppingL); if (0 == --mStepCnt) { InterlockedIncrement(&mStep); mStepCnt = mStepCntReset; } else lWaitForStep = mStep; } while (mStep <= lWaitForStep) MVTestsPortability::threadSleep(100); }
MessageQueueObject* ThreadManager::getNextMessage(bool block, uint8_t thisID) { MessageQueueObject* lRetVal = NULL; std::vector<MessageQueueObject*>::iterator lIter; boost::unique_lock<boost::mutex> lLock(*mMutexes[thisID]); // we only block here if somebody's sending our queue a message, and then not long. if(mPerThreadMessageQueue[thisID]->size() != 0) { lRetVal = mPerThreadMessageQueue[thisID]->front(); lIter = mPerThreadMessageQueue[thisID]->begin(); mPerThreadMessageQueue[thisID]->erase(lIter); return(lRetVal); // should release lock as it goes out of scope } else if(block) { while(mPerThreadMessageQueue[thisID]->size() == 0) { mCondVars[thisID]->wait(lLock); } lRetVal = mPerThreadMessageQueue[thisID]->front(); lIter = mPerThreadMessageQueue[thisID]->begin(); mPerThreadMessageQueue[thisID]->erase(lIter); return(lRetVal); } else { // nothing to get, we're not waiting -- i.e. render thread return(NULL); } }
/** This is a main run cycle thread entry point **/ void threadRunCycle( void * i_args) { AFINFO("ThreadRun::run:") ThreadArgs * a = (ThreadArgs*)i_args; while( AFRunning) { #ifdef _DEBUG printf("...................................\n"); #endif /**/ { // // Lock containers: // AFINFO("ThreadRun::run: Locking containers...") AfContainerLock jLock( a->jobs, AfContainerLock::WRITELOCK); AfContainerLock lLock( a->renders, AfContainerLock::WRITELOCK); AfContainerLock mlock( a->monitors, AfContainerLock::WRITELOCK); AfContainerLock tlock( a->talks, AfContainerLock::WRITELOCK); AfContainerLock ulock( a->users, AfContainerLock::WRITELOCK); // // Messages reaction: // AFINFO("ThreadRun::run: React on incoming messages:") /* Process all messages in our message queue. We do it without waiting so that the job solving below can run just after. NOTE: I think this should be a waiting operation in a different thread. The job solving below should be put asleep using a semaphore and woke up when something changes. We need to avoid the Sleep() function below. */ af::Msg *message; while( message = a->msgQueue->popMsg( af::AfQueue::e_no_wait) ) { threadRunCycleCase( a, message ); } // // Refresh data: // AFINFO("ThreadRun::run: Refreshing data:") a->talks ->refresh( NULL, a->monitors); a->monitors ->refresh( NULL, a->monitors); a->jobs ->refresh( a->renders, a->monitors); a->renders ->refresh( a->jobs, a->monitors); a->users ->refresh( NULL, a->monitors); // // Jobs sloving: // { AFINFO("ThreadRun::run: Solving jobs:") RenderContainerIt rendersIt( a->renders); std::list<int> rIds; { // ask every ready render to produce a task for( RenderAf *render = rendersIt.render(); render != NULL; rendersIt.next(), render = rendersIt.render()) { if( render->isReady()) { // store render Id if it produced a task if( a->users->solve( render, a->monitors)) { rIds.push_back( render->getId()); continue; } } // Render not solved, needed to update render status render->notSolved(); } } // cycle on renders, which produced a task static const int renders_cycle_limit = 100000; int renders_cycle = 0; while( rIds.size()) { renders_cycle++; if( renders_cycle > renders_cycle_limit ) { AFERROR("Renders solve cycles limit reached."); break; } AFINFA("ThreadRun::run: Renders on cycle: %d", int(rIds.size())) std::list<int>::iterator rIt = rIds.begin(); while( rIt != rIds.end()) { RenderAf * render = rendersIt.getRender( *rIt); if( render->isReady()) { if( a->users->solve( render, a->monitors)) { rIt++; continue; } } // delete render id from list if it can't produce a task rIt = rIds.erase( rIt); } } } // // Wake-On-Lan: // { AFINFO("ThreadRun::run: Wake-On-Lan:") RenderContainerIt rendersIt( a->renders); { for( RenderAf *render = rendersIt.render(); render != NULL; rendersIt.next(), render = rendersIt.render()) { if( render->isWOLWakeAble()) { if( a->users->solve( render, a->monitors)) { render->wolWake( a->monitors, std::string("Automatic waking by a job.")); continue; } } } } } // // Dispatch events to monitors: // AFINFO("ThreadRun::run: dispatching monitor events:") a->monitors->dispatch(); // // Free Containers: // AFINFO("ThreadRun::run: deleting zombies:") a->talks ->freeZombies(); a->monitors ->freeZombies(); a->renders ->freeZombies(); a->jobs ->freeZombies(); a->users ->freeZombies(); } // // Sleeping // AFINFO("ThreadRun::run: sleeping...") af::sleep_sec( 1); } }