int pmdEDUMgr::startEDU(EDU_TYPES type, void *arg, EDUID *eduid) { int rc = EDB_OK; EDUID eduID = 0; pmdEDUCB* eduCB = NULL; std::map<EDUID, pmdEDUCB*>::iterator it; if (isQuiesced()) { rc = EDB_QUIESCED; goto done; } _mutex.get(); if (true == _idleQueue.empty() || !isPoolable(type)) { _mutex.release(); rc = _createNewEDU(type, arg, eduid); if (EDB_OK == rc) { goto done; } else { goto error; } } for (it = _idleQueue.begin(); (_idleQueue.end() != it) && (PMD_EDU_IDLE != (*it).second->getStatus()); it++); if (_idleQueue.end() == it) { _mutex.release(); rc = _createNewEDU(type, arg, eduid); if (EDB_OK == rc) { goto done; } else { goto error; } } eduID = (*it).first; eduCB = (*it).second; _idleQueue.erase(eduID); EDB_ASSERT(isPoolable(type), "must be agent."); eduCB->setType(type); eduCB->setStatus(PMD_EDU_WAITING); _runQueue[eduID] = eduCB; *eduid = eduID; _mutex.release(); eduCB->postEvent(pmdEDUEvent(PMD_EDU_EVENT_RESUME, false, arg)); done: 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::_deactivateEDU(EDUID eduID) { int rc = EDB_OK; unsigned int eduStatus = PMD_EDU_CREATING; pmdEDUCB* eduCB = NULL; std::map<EDUID, pmdEDUCB*>::iterator it; _mutex.get(); if (_runQueue.end() == (it = _runQueue.find(eduID))) { if (_idleQueue.end() == (it = _idleQueue.find(eduID))) { goto done; } rc = EDB_SYS; goto error; } eduCB = (*it).second; eduStatus = eduCB->getStatus(); 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; } 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; }
// get an EDU from idle pool, if idle pool is empty, create new one int pmdEDUMgr::startEDU ( EDU_TYPES type, void* arg, EDUID *eduid) { int rc = EDB_OK ; EDUID eduID = 0 ; pmdEDUCB* eduCB = NULL ; std::map<EDUID, pmdEDUCB*>::iterator it ; if ( isQuiesced () ) { rc = EDB_QUIESCED ; goto done ; } /****************** CRITICAL SECTION **********************/ // get exclusive latch, we don't latch the entire function // in order to avoid creating new thread while holding latch _mutex.get () ; // if there's any pooled EDU? // or is the request type can be pooled ? if ( true == _idleQueue.empty () || !isPoolable ( type ) ) { // note that EDU types other than "agent" shouldn't be pooled at all // release latch before calling createNewEDU _mutex.release () ; rc = _createNewEDU ( type, arg, eduid ) ; if ( EDB_OK == rc ) goto done ; goto error ; } // if we can find something in idle queue, let's get the first of it for ( it = _idleQueue.begin () ; ( _idleQueue.end () != it ) && ( PMD_EDU_IDLE != ( *it ).second->getStatus ()) ; it ++ ) ; // if everything in idleQueue are in DESTROY status, we still need to // create a new EDU if ( _idleQueue.end () == it ) { // release latch before calling createNewEDU _mutex.release () ; rc = _createNewEDU ( type, arg, eduid ) ; if ( EDB_OK == rc ) goto done ; goto error ; } // now "it" is pointing to an idle EDU // note that all EDUs in the idleQueue should be AGENT type eduID = ( *it ).first ; eduCB = ( *it ).second ; _idleQueue.erase ( eduID ) ; EDB_ASSERT ( isPoolable ( type ), "must be agent" ) // switch agent type for the EDU ( call different agent entry point ) eduCB->setType ( type ) ; eduCB->setStatus ( PMD_EDU_WAITING ) ; _runQueue [ eduID ] = eduCB ; *eduid = eduID ; _mutex.release () ; /*************** END CRITICAL SECTION **********************/ //The edu is start, need post a resum event eduCB->postEvent( pmdEDUEvent( PMD_EDU_EVENT_RESUME, false, arg ) ) ; done : return rc ; error : goto done ; }