VirtualBox

Changeset 30075 in vbox for trunk


Ignore:
Timestamp:
Jun 7, 2010 2:10:25 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
62447
Message:

Guest Control: Use maps instead of lists; should boost performance a bit.

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/GuestImpl.cpp

    r30071 r30075  
    124124   
    125125        /* Clean up callback data. */
    126         CallbackListIter it;
    127         for (it = mCallbackList.begin(); it != mCallbackList.end(); it++)
     126        CallbackMapIter it;
     127        for (it = mCallbackMap.begin(); it != mCallbackMap.end(); it++)
    128128            destroyCtrlCallbackContext(it);
    129129   
    130         /* Clear process list. */
    131         mGuestProcessList.clear();
     130        /* Clear process map. */
     131        mGuestProcessMap.clear();
    132132    }
    133133#endif
     
    550550
    551551    AssertPtr(pData);
    552     CallbackListIter it = getCtrlCallbackContextByID(pData->hdr.u32ContextID);
     552    CallbackMapIter it = getCtrlCallbackContextByID(pData->hdr.u32ContextID);
    553553
    554554    /* Callback can be called several times. */
    555     if (it != mCallbackList.end())
    556     {
    557         PCALLBACKDATAEXECSTATUS pCBData = (PCALLBACKDATAEXECSTATUS)it->pvData;
     555    if (it != mCallbackMap.end())
     556    {
     557        PCALLBACKDATAEXECSTATUS pCBData = (PCALLBACKDATAEXECSTATUS)it->second.pvData;
    558558        AssertPtr(pCBData);
    559559
     
    565565        /* Was progress canceled before? */
    566566        BOOL fCanceled;
    567         ComAssert(it->pProgress.isNotNull());
    568         it->pProgress->COMGETTER(Canceled)(&fCanceled);
     567        ComAssert(it->second.pProgress.isNotNull());
     568        it->second.pProgress->COMGETTER(Canceled)(&fCanceled);
    569569
    570570        Utf8Str errMsg;
     
    575575            {
    576576                case PROC_STS_STARTED:
    577                     rc = it->pProgress->SetNextOperation(BstrFmt(tr("Waiting for process to exit ...")), 1 /* Weight */);
     577                    rc = it->second.pProgress->SetNextOperation(BstrFmt(tr("Waiting for process to exit ...")), 1 /* Weight */);
    578578                    if (FAILED(rc))
    579579                        errMsg = Utf8StrFmt(Guest::tr("Cannot enter waiting for process exit stage! rc=%u"),
     
    582582   
    583583                case PROC_STS_TEN: /* Terminated normally. */
    584                     it->pProgress->notifyComplete(S_OK);
     584                    it->second.pProgress->notifyComplete(S_OK);
    585585                    LogFlowFunc(("Proccess (context ID=%u, status=%u) terminated successfully\n",
    586586                                 pData->hdr.u32ContextID, pData->u32Status));
     
    617617            }
    618618           
    619             /* Handle process list. */
     619            /* Handle process map. */
    620620            /** @todo What happens on/deal with PID reuse? */
    621621            /** @todo How to deal with multiple updates at once? */
    622622            if (pCBData->u32PID > 0)
    623623            {
    624                 GuestProcessIter it_proc = getProcessByPID(pCBData->u32PID);
    625                 if (it_proc == mGuestProcessList.end())
     624                GuestProcessMapIter it_proc = getProcessByPID(pCBData->u32PID);
     625                if (it_proc == mGuestProcessMap.end())
    626626                {
    627                     /* Not found, add to list. */
    628                     GuestProcess p;
    629                     p.mPID = pCBData->u32PID;
    630                     p.mStatus = pCBData->u32Status;
    631                     p.mExitCode = pCBData->u32Flags; /* Contains exit code. */
    632                     p.mFlags = 0;
     627                    /* Not found, add to map. */
     628                    GuestProcess newProcess;
     629                    newProcess.mStatus = pCBData->u32Status;
     630                    newProcess.mExitCode = pCBData->u32Flags; /* Contains exit code. */
     631                    newProcess.mFlags = 0;
    633632       
    634                     mGuestProcessList.push_back(p);
     633                    mGuestProcessMap[pCBData->u32PID] = newProcess;
    635634                }
    636                 else /* Update list. */
     635                else /* Update map. */
    637636                {
    638                     it_proc->mStatus = pCBData->u32Status;
    639                     it_proc->mExitCode = pCBData->u32Flags; /* Contains exit code. */
    640                     it_proc->mFlags = 0;
     637                    it_proc->second.mStatus = pCBData->u32Status;
     638                    it_proc->second.mExitCode = pCBData->u32Flags; /* Contains exit code. */
     639                    it_proc->second.mFlags = 0;
    641640                }
    642641            }
     
    645644            errMsg = Utf8StrFmt(Guest::tr("Process execution canceled"));
    646645       
    647         if (!it->pProgress->getCompleted())
     646        if (!it->second.pProgress->getCompleted())
    648647        {
    649648            if (   errMsg.length()
    650649                || fCanceled) /* If cancelled we have to report E_FAIL! */
    651650            {
    652                 it->pProgress->notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest),
     651                it->second.pProgress->notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest),
    653652                                              (CBSTR)Guest::getComponentName(), errMsg.c_str());
    654653                LogFlowFunc(("Process (context ID=%u, status=%u) reported error: %s\n",
     
    671670
    672671    AssertPtr(pData);
    673     CallbackListIter it = getCtrlCallbackContextByID(pData->hdr.u32ContextID);
    674     if (it != mCallbackList.end())
    675     {
    676         PCALLBACKDATAEXECOUT pCBData = (CALLBACKDATAEXECOUT*)it->pvData;
     672    CallbackMapIter it = getCtrlCallbackContextByID(pData->hdr.u32ContextID);
     673    if (it != mCallbackMap.end())
     674    {
     675        PCALLBACKDATAEXECOUT pCBData = (CALLBACKDATAEXECOUT*)it->second.pvData;
    677676        AssertPtr(pCBData);
    678677
     
    700699        /* Was progress canceled before? */
    701700        BOOL fCanceled;
    702         ComAssert(it->pProgress.isNotNull());
    703         it->pProgress->COMGETTER(Canceled)(&fCanceled);
     701        ComAssert(it->second.pProgress.isNotNull());
     702        it->second.pProgress->COMGETTER(Canceled)(&fCanceled);
    704703
    705704        if (!fCanceled)
    706             it->pProgress->notifyComplete(S_OK);
     705            it->second.pProgress->notifyComplete(S_OK);
    707706        else
    708             it->pProgress->notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest),
     707            it->second.pProgress->notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest),
    709708                                          (CBSTR)Guest::getComponentName(), Guest::tr("The output operation was cancelled"));
    710709    }
     
    720719
    721720    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    722 
    723     /** @todo Maybe use a map instead of list for fast context lookup. */
    724     CallbackListIter it;
    725     for (it = mCallbackList.begin(); it != mCallbackList.end(); it++)
    726     {
    727         if (it->mContextID == pData->hdr.u32ContextID)
    728         {
    729             LogFlowFunc(("Client with context ID=%u disconnected\n", it->mContextID));
    730             destroyCtrlCallbackContext(it);
    731         }
     721    CallbackMapIter it = getCtrlCallbackContextByID(pData->hdr.u32ContextID);
     722    if (it != mCallbackMap.end())
     723    {
     724        LogFlowFunc(("Client with context ID=%u disconnected\n", it->first));
     725        destroyCtrlCallbackContext(it);
    732726    }
    733727    return rc;
    734728}
    735729
    736 Guest::CallbackListIter Guest::getCtrlCallbackContextByID(uint32_t u32ContextID)
     730Guest::CallbackMapIter Guest::getCtrlCallbackContextByID(uint32_t u32ContextID)
     731{
     732    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 
     733    return mCallbackMap.find(u32ContextID);
     734}
     735
     736Guest::GuestProcessMapIter Guest::getProcessByPID(uint32_t u32PID)
    737737{
    738738    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    739 
    740     /** @todo Maybe use a map instead of list for fast context lookup. */
    741     CallbackListIter it;
    742     for (it = mCallbackList.begin(); it != mCallbackList.end(); it++)
    743     {
    744         if (it->mContextID == u32ContextID)
    745             return (it);
    746     }
    747     return it;
    748 }
    749 
    750 Guest::GuestProcessIter Guest::getProcessByPID(uint32_t u32PID)
    751 {
    752     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    753 
    754     /** @todo Maybe use a map instead of list for fast context lookup. */
    755     GuestProcessIter it;
    756     for (it = mGuestProcessList.begin(); it != mGuestProcessList.end(); it++)
    757     {
    758         if (it->mPID == u32PID)
    759             return (it);
    760     }
    761     return it;
     739    return mGuestProcessMap.find(u32PID);
    762740}
    763741
    764742/* No locking here; */
    765 void Guest::destroyCtrlCallbackContext(Guest::CallbackListIter it)
    766 {
    767     if (it->pvData)
    768     {
    769         LogFlowFunc(("Destroying callback with context ID=%u ...\n", it->mContextID));
    770 
    771         RTMemFree(it->pvData);
    772         it->pvData = NULL;
    773         it->cbData = 0;
     743void Guest::destroyCtrlCallbackContext(Guest::CallbackMapIter it)
     744{
     745    if (it->second.pvData)
     746    {
     747        LogFlowFunc(("Destroying callback with context ID=%u ...\n", it->first));
     748
     749        RTMemFree(it->second.pvData);
     750        it->second.pvData = NULL;
     751        it->second.cbData = 0;
    774752    }
    775753
    776754    /* Notify outstanding waits for progress ... */
    777     if (it->pProgress && it->pProgress.isNotNull())
    778     {
    779         LogFlowFunc(("Handling progress of context ID=%u ...\n", it->mContextID));
     755    if (it->second.pProgress && it->second.pProgress.isNotNull())
     756    {
     757        LogFlowFunc(("Handling progress of context ID=%u ...\n", it->first));
    780758
    781759        BOOL fCompleted;
    782         it->pProgress->COMGETTER(Completed)(&fCompleted);
     760        it->second.pProgress->COMGETTER(Completed)(&fCompleted);
    783761        if (!fCompleted)
    784762        {
    785763            /* Only cancel if not canceled before! */
    786764            BOOL fCanceled;
    787             if (SUCCEEDED(it->pProgress->COMGETTER(Canceled)(&fCanceled)) && !fCanceled)
    788                 it->pProgress->Cancel();       
     765            if (SUCCEEDED(it->second.pProgress->COMGETTER(Canceled)(&fCanceled)) && !fCanceled)
     766                it->second.pProgress->Cancel();       
    789767
    790768            /* To get waitForCompletion notified we have to notify it if necessary. */
    791             it->pProgress->notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest),
     769            it->second.pProgress->notifyComplete(VBOX_E_IPRT_ERROR, COM_IIDOF(IGuest),
    792770                                          (CBSTR)Guest::getComponentName(), Guest::tr("The operation was canceled during shutdown"));
    793771        }       
     
    800778
    801779/* Adds a callback with a user provided data block and an optional progress object
    802  * to the callback list. A callback is identified by a unique context ID which is used
     780 * to the callback map. A callback is identified by a unique context ID which is used
    803781 * to identify a callback from the guest side. */
    804782uint32_t Guest::addCtrlCallbackContext(eVBoxGuestCtrlCallbackType enmType, void *pvData, uint32_t cbData, Progress *pProgress)
     
    814792
    815793    /* Create a new context ID and assign it. */
    816     CallbackListIter it;
     794    CallbackMapIter it;
    817795    uint32_t uNewContext = 0;
    818796    do
     
    824802        /* Is the context ID already used? */
    825803        it = getCtrlCallbackContextByID(uNewContext);       
    826     } while(it != mCallbackList.end());
     804    } while(it != mCallbackMap.end());
    827805
    828806    uint32_t nCallbacks = 0;
    829     if (   it == mCallbackList.end()
     807    if (   it == mCallbackMap.end()
    830808        && uNewContext > 0)
    831809    {
    832810        /* We apparently got an unused context ID, let's use it! */
    833         context.mContextID = uNewContext;
    834811        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    835         mCallbackList.push_back(context);
    836         nCallbacks = mCallbackList.size();
     812        mCallbackMap[uNewContext] = context;
     813        nCallbacks = mCallbackMap.size();
    837814    }
    838815    else
     
    841818        {
    842819            AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    843             nCallbacks = mCallbackList.size();
     820            nCallbacks = mCallbackMap.size();
    844821        }
    845822        AssertReleaseMsg(uNewContext, ("No free context ID found! uNewContext=%u, nCallbacks=%u", uNewContext, nCallbacks));
     
    1021998                 * get the PID.
    1022999                 */
    1023                 CallbackListIter it = getCtrlCallbackContextByID(uContextID);
     1000                CallbackMapIter it = getCtrlCallbackContextByID(uContextID);
    10241001                BOOL fCanceled = FALSE;
    1025                 if (it != mCallbackList.end())
     1002                if (it != mCallbackMap.end())
    10261003                {
    1027                     ComAssert(it->pProgress.isNotNull());
     1004                    ComAssert(it->second.pProgress.isNotNull());
    10281005
    10291006                    /*
     
    10311008                     */
    10321009                    PCALLBACKDATAEXECSTATUS pData = NULL;
    1033                     rc = it->pProgress->WaitForOperationCompletion(0, aTimeoutMS);
     1010                    rc = it->second.pProgress->WaitForOperationCompletion(0, aTimeoutMS);
    10341011                    if (SUCCEEDED(rc))
    10351012                    {
    10361013                        /* Was the operation canceled by one of the parties? */
    1037                         rc = it->pProgress->COMGETTER(Canceled)(&fCanceled);
     1014                        rc = it->second.pProgress->COMGETTER(Canceled)(&fCanceled);
    10381015                        if (FAILED(rc)) throw rc;
    10391016
     
    10421019                            AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    10431020   
    1044                             pData = (PCALLBACKDATAEXECSTATUS)it->pvData;
    1045                             Assert(it->cbData == sizeof(CALLBACKDATAEXECSTATUS));
     1021                            pData = (PCALLBACKDATAEXECSTATUS)it->second.pvData;
     1022                            Assert(it->second.cbData == sizeof(CALLBACKDATAEXECSTATUS));
    10461023                            AssertPtr(pData);
    10471024   
     
    11461123                }
    11471124                else /* Callback context not found; should never happen! */
    1148                     AssertMsg(it != mCallbackList.end(), ("Callback context with ID %u not found!", uContextID));
     1125                    AssertMsg(it != mCallbackMap.end(), ("Callback context with ID %u not found!", uContextID));
    11491126            }
    11501127            else /* HGCM related error codes .*/
     
    12701247             * get the PID.
    12711248             */
    1272             CallbackListIter it = getCtrlCallbackContextByID(uContextID);
     1249            CallbackMapIter it = getCtrlCallbackContextByID(uContextID);
    12731250            BOOL fCanceled = FALSE;
    1274             if (it != mCallbackList.end())
     1251            if (it != mCallbackMap.end())
    12751252            {
    1276                 ComAssert(it->pProgress.isNotNull());
     1253                ComAssert(it->second.pProgress.isNotNull());
    12771254
    12781255                /* Wait until operation completed. */
    1279                 rc = it->pProgress->WaitForCompletion(aTimeoutMS);
     1256                rc = it->second.pProgress->WaitForCompletion(aTimeoutMS);
    12801257                if (FAILED(rc)) throw rc;
    12811258               
    12821259                /* Was the operation canceled by one of the parties? */
    1283                 rc = it->pProgress->COMGETTER(Canceled)(&fCanceled);
     1260                rc = it->second.pProgress->COMGETTER(Canceled)(&fCanceled);
    12841261                if (FAILED(rc)) throw rc;
    12851262
     
    12871264                {
    12881265                    BOOL fCompleted;
    1289                     if (   SUCCEEDED(it->pProgress->COMGETTER(Completed)(&fCompleted))
     1266                    if (   SUCCEEDED(it->second.pProgress->COMGETTER(Completed)(&fCompleted))
    12901267                        && fCompleted)
    12911268                    {
     
    12931270
    12941271                        /* Did we get some output? */
    1295                         pData = (PCALLBACKDATAEXECOUT)it->pvData;
    1296                         Assert(it->cbData == sizeof(CALLBACKDATAEXECOUT));
     1272                        pData = (PCALLBACKDATAEXECOUT)it->second.pvData;
     1273                        Assert(it->second.cbData == sizeof(CALLBACKDATAEXECOUT));
    12971274                        AssertPtr(pData);
    12981275
     
    13481325
    13491326                /* Remove callback context (not used anymore). */
    1350                 mCallbackList.erase(it);
     1327                mCallbackMap.erase(it);
    13511328            }
    13521329            else /* PID lookup failed. */
     
    13921369        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    13931370
    1394         GuestProcessIterConst it;
    1395         for (it = mGuestProcessList.begin(); it != mGuestProcessList.end(); it++)
    1396         {
    1397             if (it->mPID == aPID)
    1398                 break;
    1399         }
    1400 
    1401         if (it != mGuestProcessList.end())
    1402         {
    1403             *aExitCode = it->mExitCode;
    1404             *aFlags = it->mFlags;
    1405             *aStatus = it->mStatus;
     1371        GuestProcessMapIterConst it = getProcessByPID(aPID);
     1372        if (it != mGuestProcessMap.end())
     1373        {
     1374            *aExitCode = it->second.mExitCode;
     1375            *aFlags = it->second.mFlags;
     1376            *aStatus = it->second.mStatus;
    14061377        }
    14071378        else
  • trunk/src/VBox/Main/include/GuestImpl.h

    r30020 r30075  
    122122    struct CallbackContext
    123123    {
    124         /** Associated context ID. */
    125         uint32_t                    mContextID;
    126124        eVBoxGuestCtrlCallbackType  mType;
    127125        /** Pointer to user-supplied data. */       
     
    132130        ComObjPtr<Progress>         pProgress;
    133131    };
    134     typedef std::list< CallbackContext > CallbackList;
    135     typedef std::list< CallbackContext >::iterator CallbackListIter;
    136     typedef std::list< CallbackContext >::const_iterator CallbackListIterConst;
     132    /*
     133     * The map key is the context ID.
     134     */
     135    typedef std::map< uint32_t, CallbackContext > CallbackMap;
     136    typedef std::map< uint32_t, CallbackContext >::iterator CallbackMapIter;
     137    typedef std::map< uint32_t, CallbackContext >::const_iterator CallbackMapIterConst;
    137138
    138139    struct GuestProcess
    139140    {
    140         uint32_t                    mPID;
    141141        uint32_t                    mStatus;
    142142        uint32_t                    mFlags;
    143143        uint32_t                    mExitCode;
    144144    };
    145     typedef std::list< GuestProcess > GuestProcessList;
    146     typedef std::list< GuestProcess >::iterator GuestProcessIter;
    147     typedef std::list< GuestProcess >::const_iterator GuestProcessIterConst;
     145    /*
     146     * The map key is the PID (process identifier).
     147     */
     148    typedef std::map< uint32_t, GuestProcess > GuestProcessMap;
     149    typedef std::map< uint32_t, GuestProcess >::iterator GuestProcessMapIter;
     150    typedef std::map< uint32_t, GuestProcess >::const_iterator GuestProcessMapIterConst;
    148151
    149152    int prepareExecuteEnv(const char *pszEnv, void **ppvList, uint32_t *pcbList, uint32_t *pcEnv);
     
    152155    int notifyCtrlExecStatus(uint32_t u32Function, PCALLBACKDATAEXECSTATUS pData);
    153156    int notifyCtrlExecOut(uint32_t u32Function, PCALLBACKDATAEXECOUT pData);
    154     CallbackListIter getCtrlCallbackContextByID(uint32_t u32ContextID);
    155     GuestProcessIter getProcessByPID(uint32_t u32PID);
    156     void destroyCtrlCallbackContext(CallbackListIter it);
     157    CallbackMapIter getCtrlCallbackContextByID(uint32_t u32ContextID);
     158    GuestProcessMapIter getProcessByPID(uint32_t u32PID);
     159    void destroyCtrlCallbackContext(CallbackMapIter it);
    157160    uint32_t addCtrlCallbackContext(eVBoxGuestCtrlCallbackType enmType, void *pvData, uint32_t cbData, Progress* pProgress);
    158161# endif
     
    183186
    184187    volatile uint32_t mNextContextID;
    185     CallbackList mCallbackList;
    186     GuestProcessList mGuestProcessList;
     188    CallbackMap mCallbackMap;
     189    GuestProcessMap mGuestProcessMap;
    187190# endif
    188191};
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette