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; }
int pmdEDUMgr::returnEDU(EDUID eduID, bool force, bool* destroyed) { int rc = EDB_OK; EDU_TYPES type = EDU_TYPE_UNKNOWN; pmdEDUCB* eduCB = NULL; std::map<EDUID, pmdEDUCB*>::iterator it; _mutex.get_shared(); if (_runQueue.end() == (it = _runQueue.find(eduID))) { if (_idleQueue.end() == (it = _idleQueue.find(eduID))) { rc = EDB_SYS; *destroyed = false; _mutex.release_shared(); goto error; } } eduCB = (*it).second; if (eduCB) { type = eduCB->getType(); } _mutex.release_shared(); if (!isPoolable(type) || force || isDestroyed() || size() > (unsigned int) pmdGetKRCB()->getMaxPool()) { rc = _destroyEDU(eduID); if (destroyed) { if (EDB_OK == rc || EDB_SYS == rc) { *destroyed = true; } else { *destroyed = false; } } } else { rc = _deactivateEDU(eduID); if (destroyed) { if (EDB_SYS == rc) { *destroyed = true; } else { *destroyed = false; } } } 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 ; }
// release control from a given EDU // EDUMgr should decide whether put the EDU to pool or destroy it // EDU Status must be in waiting or creating int pmdEDUMgr::returnEDU ( EDUID eduID, bool force, bool* destroyed ) { int rc = EDB_OK ; EDU_TYPES type = EDU_TYPE_UNKNOWN ; pmdEDUCB *educb = NULL ; std::map<EDUID, pmdEDUCB*>::iterator it ; // shared critical section _mutex.get_shared () ; if ( _runQueue.end() == ( it = _runQueue.find ( eduID ) ) ) { if ( _idleQueue.end() == ( it = _idleQueue.find ( eduID ) ) ) { rc = EDB_SYS ; *destroyed = false ; _mutex.release_shared () ; goto error ; } } educb = (*it).second ; // if we are trying to destry EDU manager, or enforce destroy, or // if the total number of threads are more than what we need // we need to destroy this EDU // // Currentl we only able to pool agent and coordagent if ( educb ) { type = educb->getType() ; } _mutex.release_shared () ; // if the EDU type can't be pooled, or if we forced, or if the EDU is // destroied, or we exceed max pooled edus, let's destroy it if ( !isPoolable(type) || force || isDestroyed () || size() > (unsigned int)pmdGetKRCB()->getMaxPool () ) { rc = _destroyEDU ( eduID ) ; if ( destroyed ) { // we consider the EDU is destroyed when destroyEDU returns // OK or EDB_SYS (edu can't be found), so that thread can terminate // itself if ( EDB_OK == rc || EDB_SYS == rc ) *destroyed = true ; else *destroyed = false ; } } else { // in this case, we don't need to care whether the EDU is agent or not // as long as we treat EDB_SYS as "destroyed" signal, we should be // safe here rc = _deactivateEDU ( eduID ) ; if ( destroyed ) { // when we try to pool the EDU, destroyed set to true only when // the EDU can't be found in the list if ( EDB_SYS == rc ) *destroyed = true ; else *destroyed = false ; } } done : return rc ; error : goto done ; }