int pmdEDUMgr::waitEDU(EDUID eduID) { int rc = EDB_OK; pmdEDUCB* eduCB = NULL; unsigned int eduStatus = PMD_EDU_CREATING; std::map<EDUID, pmdEDUCB*>::iterator it; _mutex.get_shared(); if (_runQueue.end() == (it = _runQueue.find(eduID))) { rc = EDB_SYS; goto error; } eduCB = (*it).second; eduStatus = eduCB->getStatus(); if (PMD_IS_EDU_WAITING(eduStatus)) { goto done; } if (!PMD_IS_EDU_RUNNING(eduStatus)) { rc = EDB_EDU_INVAL_STATUS; goto error; } eduCB->setStatus(PMD_EDU_WAITING); done: _mutex.release_shared(); return rc; error: goto done; }
int pmdEDUMgr::activateEDU ( EDUID eduID ) { int rc = EDB_OK ; unsigned int eduStatus = PMD_EDU_CREATING ; pmdEDUCB* eduCB = NULL; std::map<EDUID, pmdEDUCB*>::iterator it ; /************** CRITICAL SECTION ***********/ // we should lock the entire function in order to avoid // eduCB is deleted after we getting (*it).second _mutex.get() ; if ( _idleQueue.end () == ( it = _idleQueue.find ( eduID )) ) { if ( _runQueue.end () == ( it = _runQueue.find ( eduID )) ) { // we can't find EDU in idle list nor runqueue rc = EDB_SYS ; goto error ; } eduCB = ( *it ).second ; // in runqueue we may have creating/waiting status eduStatus = eduCB->getStatus () ; if ( PMD_IS_EDU_RUNNING ( eduStatus ) ) goto done ; if ( !PMD_IS_EDU_WAITING ( eduStatus ) && !PMD_IS_EDU_CREATING ( eduStatus ) ) { rc = EDB_EDU_INVAL_STATUS ; goto error ; } eduCB->setStatus ( PMD_EDU_RUNNING ) ; goto done ; } eduCB = ( *it ).second ; eduStatus = eduCB->getStatus () ; if ( PMD_IS_EDU_RUNNING ( eduStatus ) ) goto done ; // in idleQueue if ( !PMD_IS_EDU_IDLE ( eduStatus ) ) { rc = EDB_EDU_INVAL_STATUS ; goto error ; } // now the EDU status is idle, let's bring it to RUNNING _idleQueue.erase ( eduID ) ; eduCB->setStatus ( PMD_EDU_RUNNING ) ; _runQueue [ eduID ] = eduCB ; done : _mutex.release () ; return rc ; error : goto done ; }
int pmdEDUMgr::_destroyEDU(EDUID eduID) { int rc = EDB_OK; pmdEDUCB* eduCB = NULL; unsigned int eduStatus = PMD_EDU_CREATING; std::map<EDUID, pmdEDUCB*>::iterator it; std::map<unsigned int, EDUID>::iterator it1; _mutex.get(); if (_runQueue.end() == (it = _runQueue.find(eduID))) { if (_idleQueue.end() == (it = _idleQueue.find(eduID))) { rc = EDB_SYS; goto error; } eduCB = (*it).second; if (!PMD_IS_EDU_IDLE(eduCB->getStatus())) { rc = EDB_EDU_INVAL_STATUS; goto error; } eduCB->setStatus(PMD_EDU_DESTROY); _idleQueue.erase(eduID); } else { eduCB = (*it).second; eduStatus = eduCB->getStatus(); if (!PMD_IS_EDU_WAITING(eduStatus) && !PMD_IS_EDU_CREATING(eduStatus)) { rc = EDB_EDU_INVAL_STATUS; goto error; } eduCB->setStatus(PMD_EDU_DESTROY); _runQueue.erase(eduID); } // clean up tid/eduid map for (it1 = _tid_eduid_map.begin(); it1 != _tid_eduid_map.end(); ++it1) { if ((*it1).second == eduID) { _tid_eduid_map.erase(it1); break; } } if (eduCB) { delete(eduCB); } done: _mutex.release(); return rc; error: goto done; }
// creating/waiting status edu can be deactivated (pooled) // deactivateEDU supposed only happened to AGENT EDUs // any EDUs other than AGENT will be destroyed and EDB_SYS will be returned int pmdEDUMgr::_deactivateEDU ( EDUID eduID ) { int rc = EDB_OK ; unsigned int eduStatus = PMD_EDU_CREATING ; pmdEDUCB* eduCB = NULL ; std::map<EDUID, pmdEDUCB*>::iterator it ; // cross queue operation, need X lock _mutex.get() ; if ( _runQueue.end () == ( it = _runQueue.find ( eduID )) ) { // if it's not in run queue, then is it in idle queue? // if it's already idle, we don't need to do anything if ( _idleQueue.end() != _idleQueue.find ( eduID ) ) { goto done ; } // we can't find EDU in run queue rc = EDB_SYS ; goto error ; } eduCB = ( *it ).second ; eduStatus = eduCB->getStatus () ; // if it's already idle, let's get out of here if ( PMD_IS_EDU_IDLE ( eduStatus ) ) goto done ; if ( !PMD_IS_EDU_WAITING ( eduStatus ) && !PMD_IS_EDU_CREATING ( eduStatus ) ) { rc = EDB_EDU_INVAL_STATUS ; goto error ; } // only Agent can be deactivated (pooled), other system // EDUs can only be destroyed EDB_ASSERT ( isPoolable ( eduCB->getType() ), "Only agent can be pooled" ) _runQueue.erase ( eduID ) ; eduCB->setStatus ( PMD_EDU_IDLE ) ; _idleQueue [ eduID ] = eduCB ; done : _mutex.release () ; return rc ; error : goto done ; }
int pmdEDUMgr::activateEDU(EDUID eduID) { int rc = EDB_OK; unsigned int eduStatus = PMD_EDU_CREATING; pmdEDUCB* eduCB = NULL; std::map<EDUID, pmdEDUCB*>::iterator it; _mutex.get(); if (_idleQueue.end() == (it = _idleQueue.find(eduID))) { if (_runQueue.end() == (it = _runQueue.find(eduID))) { rc = EDB_SYS; goto error; } eduCB = (*it).second; eduStatus = eduCB->getStatus(); if (PMD_IS_EDU_RUNNING(eduStatus)) { goto done; } if (!PMD_IS_EDU_WAITING(eduStatus) && !PMD_IS_EDU_CREATING(eduStatus)) { rc = EDB_EDU_INVAL_STATUS; goto error; } eduCB->setStatus(PMD_EDU_RUNNING); goto done; } eduCB = (*it).second; eduStatus = eduCB->getStatus(); if (PMD_IS_EDU_RUNNING(eduStatus)) { goto done; } if (!PMD_IS_EDU_IDLE(eduStatus)) { rc = EDB_EDU_INVAL_STATUS; goto error; } _idleQueue.erase(eduID); eduCB->setStatus(PMD_EDU_RUNNING); _runQueue[eduID] = eduCB; done: _mutex.release(); return rc; error: goto done; }
// change edu status from running to waiting int pmdEDUMgr::waitEDU ( EDUID eduID ) { int rc = EDB_OK ; pmdEDUCB* eduCB = NULL ; unsigned int eduStatus = PMD_EDU_CREATING ; std::map<EDUID, pmdEDUCB*>::iterator it ; /************** CRITICAL SECTION ***********/ // we should lock the entire function in order to avoid // eduCB is deleted after we getting (*it).second _mutex.get_shared () ; if ( _runQueue.end () == ( it = _runQueue.find ( eduID )) ) { // we can't find EDU in run queue rc = EDB_SYS ; goto error ; } eduCB = ( *it ).second ; eduStatus = eduCB->getStatus () ; // if it's already waiting, let's do nothing if ( PMD_IS_EDU_WAITING ( eduStatus ) ) goto done ; if ( !PMD_IS_EDU_RUNNING ( eduStatus ) ) { // if it's not running status rc = EDB_EDU_INVAL_STATUS ; goto error ; } eduCB->setStatus ( PMD_EDU_WAITING ) ; done : _mutex.release_shared () ; /************* END CRITICAL SECTION **************/ return rc ; error : goto done ; }
// this function must be called against a thread that // in either EDB_EDU_WAITING or EDB_EDU_IDLE status // return: EDB_OK -- success // EDB_EDU_INVAL_STATUS -- edu status is not destroy int pmdEDUMgr::_destroyEDU ( EDUID eduID ) { int rc = EDB_OK ; pmdEDUCB* eduCB = NULL ; unsigned int eduStatus = PMD_EDU_CREATING ; std::map<EDUID, pmdEDUCB*>::iterator it ; std::map<unsigned int, EDUID>::iterator it1 ; _mutex.get() ; // try to find the edu id in runqueue // Since this is private function, no latch is needed if ( _runQueue.end () == ( it = _runQueue.find ( eduID )) ) { // if we cannot find it in runqueue, we search for idle queue // note that during the time, we already have EDUMgr locked, // so thread cannot change queue from idle to run // that means we are safe to exame both queues if ( _idleQueue.end () == ( it = _idleQueue.find ( eduID )) ) { // we can't find edu id anywhere rc = EDB_SYS ; goto error ; } eduCB = ( *it ).second ; // if we find in idle queue, we expect idle status if ( !PMD_IS_EDU_IDLE ( eduCB->getStatus ()) ) { // if the status is not destroy rc = EDB_EDU_INVAL_STATUS ; goto error ; } // set the status to destroy eduCB->setStatus ( PMD_EDU_DESTROY ) ; _idleQueue.erase ( eduID ) ; } // if we find in run queue, we expect waiting status else { eduCB = ( *it ).second ; eduStatus = eduCB->getStatus () ; if ( !PMD_IS_EDU_WAITING ( eduStatus ) && !PMD_IS_EDU_CREATING ( eduStatus ) ) { // if the status is not destroy // we should return error indicating bad status rc = EDB_EDU_INVAL_STATUS ; goto error ; } eduCB->setStatus ( PMD_EDU_DESTROY ) ; _runQueue.erase ( eduID ) ; } // clean up tid/eduid map for ( it1 = _tid_eduid_map.begin(); it1 != _tid_eduid_map.end(); ++it1 ) { if ( (*it1).second == eduID ) { _tid_eduid_map.erase ( it1 ) ; break ; } } if ( eduCB ) delete ( eduCB ) ; done : _mutex.release () ; return rc ; error : goto done ; }