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; }
// 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 ; }