VirtualBox

Changeset 57631 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
Sep 4, 2015 1:55:49 PM (9 years ago)
Author:
vboxsync
Message:

FE/Qt: Thread-pool: Cleanup/rework.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIThreadPool.cpp

    r57629 r57631  
    3333#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
    3434
    35 
    3635/** QThread extension used as worker-thread.
    3736  * Capable of executing COM-related tasks. */
     
    5251
    5352    /** Returns worker-thread index within the worker-thread pool registry. */
    54     int getIndex() const { return m_iIndex; }
     53    int index() const { return m_iIndex; }
    5554
    5655    /** Disables sigFinished signal, for optimizing worker-thread pool termination. */
    57     void setNoFinishedSignal()
    58     {
    59         m_fNoFinishedSignal = true;
    60     }
     56    void setNoFinishedSignal() { m_fNoFinishedSignal = true; }
    6157
    6258private:
     
    7470    bool m_fNoFinishedSignal;
    7571};
    76 
    7772
    7873UIThreadPool::UIThreadPool(ulong cMaxWorkers /* = 3 */, ulong cMsWorkerIdleTimeout /* = 5000 */)
     
    8176    , m_cWorkers(0)
    8277    , m_cIdleWorkers(0)
    83     , m_fTerminating(false) /* termination status */
     78    , m_fTerminating(false)
    8479{
    8580}
     
    8782UIThreadPool::~UIThreadPool()
    8883{
    89     /* Set termination status and alert all idle worker threads: */
     84    /* Set termination status: */
    9085    setTerminating();
    9186
    92     m_everythingLocker.lock(); /* paranoia */
     87    /* Lock initially: */
     88    m_everythingLocker.lock();
    9389
    9490    /* Cleanup all the workers: */
    9591    for (int idxWorker = 0; idxWorker < m_workers.size(); ++idxWorker)
    9692    {
    97         UIThreadWorker *pWorker = m_workers[idxWorker];
    98         m_workers[idxWorker] = NULL;
    99 
    100         /* Clean up the worker, if there was one. */
     93        /* Acquire the worker: */
     94        UIThreadWorker *pWorker = m_workers.at(idxWorker);
     95        /* Remove it from the registry: */
     96        m_workers[idxWorker] = 0;
     97
     98        /* Clean up the worker, if there was one: */
    10199        if (pWorker)
    102100        {
    103             m_cWorkers--;
     101            /* Decrease the number of workers: */
     102            --m_cWorkers;
     103            /* Unlock temporary to let the worker finish: */
    104104            m_everythingLocker.unlock();
    105 
     105            /* Wait for the worker to finish: */
    106106            pWorker->wait();
    107 
     107            /* Lock again: */
    108108            m_everythingLocker.lock();
     109            /* Delete the worker finally: */
    109110            delete pWorker;
    110111        }
    111112    }
    112113
     114    /* Unlock finally: */
    113115    m_everythingLocker.unlock();
    114116}
     
    116118bool UIThreadPool::isTerminating() const
    117119{
     120    /* Lock initially: */
     121    m_everythingLocker.lock();
     122
    118123    /* Acquire termination-flag: */
    119     m_everythingLocker.lock();
    120124    bool fTerminating = m_fTerminating;
    121     m_everythingLocker.unlock();
    122 
     125
     126    /* Unlock finally: */
     127    m_everythingLocker.unlock();
     128
     129    /* Return termination-flag: */
    123130    return fTerminating;
    124131}
     
    126133void UIThreadPool::setTerminating()
    127134{
    128     m_everythingLocker.lock();
    129 
    130     /* Indicate that we're terminating: */
     135    /* Lock initially: */
     136    m_everythingLocker.lock();
     137
     138    /* Assign termination-flag: */
    131139    m_fTerminating = true;
    132140
     
    134142    for (int idxWorker = 0; idxWorker < m_workers.size(); ++idxWorker)
    135143    {
    136         UIThreadWorker *pWorker = m_workers[idxWorker];
     144        UIThreadWorker *pWorker = m_workers.at(idxWorker);
    137145        if (pWorker)
    138146            pWorker->setNoFinishedSignal();
     
    142150    m_taskCondition.wakeAll();
    143151
     152    /* Unlock finally: */
    144153    m_everythingLocker.unlock();
    145154}
     
    147156void UIThreadPool::enqueueTask(UITask *pTask)
    148157{
    149     Assert(!isTerminating());
     158    /* Do nothing if terminating: */
     159    AssertReturnVoid(!isTerminating());
    150160
    151161    /* Prepare task: */
    152     connect(pTask, SIGNAL(sigComplete(UITask*)), this, SLOT(sltHandleTaskComplete(UITask*)), Qt::QueuedConnection);
    153 
    154     m_everythingLocker.lock();
    155 
    156     /* Put the task onto the queue: */
     162    connect(pTask, SIGNAL(sigComplete(UITask*)),
     163            this, SLOT(sltHandleTaskComplete(UITask*)), Qt::QueuedConnection);
     164
     165    /* Lock initially: */
     166    m_everythingLocker.lock();
     167
     168    /* Put the task into the queue: */
    157169    m_tasks.enqueue(pTask);
    158170
     
    168180        int idxFirstUnused = m_workers.size();
    169181        while (idxFirstUnused-- > 0)
    170             if (m_workers[idxFirstUnused] == NULL)
     182            if (m_workers.at(idxFirstUnused) == 0)
    171183            {
    172184                /* Prepare the new worker: */
    173185                UIThreadWorker *pWorker = new UIThreadWorker(this, idxFirstUnused);
    174                 connect(pWorker, SIGNAL(sigFinished(UIThreadWorker*)), this,
    175                         SLOT(sltHandleWorkerFinished(UIThreadWorker*)), Qt::QueuedConnection);
     186                connect(pWorker, SIGNAL(sigFinished(UIThreadWorker*)),
     187                        this, SLOT(sltHandleWorkerFinished(UIThreadWorker*)), Qt::QueuedConnection);
    176188                m_workers[idxFirstUnused] = pWorker;
    177                 m_cWorkers++;
     189                ++m_cWorkers;
    178190
    179191                /* And start it: */
     
    182194            }
    183195    }
    184     /* else: wait for some worker to complete whatever it's busy with and jump to it. */
    185 
     196    /* else: wait for some worker to complete
     197     * whatever it's busy with and jump to it. */
     198
     199    /* Unlock finally: */
    186200    m_everythingLocker.unlock();
    187201}
     
    189203UITask* UIThreadPool::dequeueTask(UIThreadWorker *pWorker)
    190204{
     205    /* Lock initially: */
     206    m_everythingLocker.lock();
     207
    191208    /* Dequeue a task, watching out for terminations.
    192      * For opimal efficiency in enqueueTask() we keep count of idle threads.
    193      * If the wait times out, we'll return NULL and terminate the thread. */
    194     m_everythingLocker.lock();
    195 
     209     * For optimal efficiency in enqueueTask() we keep count of idle threads.
     210     * If the wait times out, we'll return 0 and terminate the thread. */
    196211    bool fIdleTimedOut = false;
    197212    while (!m_fTerminating)
    198213    {
    199         Assert(m_workers[pWorker->getIndex()] == pWorker); /* paranoia */
     214        /* Make sure that worker has proper index: */
     215        Assert(m_workers.at(pWorker->index()) == pWorker);
    200216
    201217        /* Dequeue task if there is one: */
     
    205221            if (pTask)
    206222            {
     223                /* Unlock finally: */
    207224                m_everythingLocker.unlock();
     225
     226                /* Return dequeued task: */
    208227                return pTask;
    209228            }
     
    211230
    212231        /* If we timed out already, then quit the worker thread. To prevent a
    213            race between enqueueTask and the queue removal of the thread from
    214            the workers vector, we remove it here already. (This does not apply
    215            to the termination scenario.) */
     232         * race between enqueueTask and the queue removal of the thread from
     233         * the workers vector, we remove it here already. (This does not apply
     234         * to the termination scenario.) */
    216235        if (fIdleTimedOut)
    217236        {
    218             m_workers[pWorker->getIndex()] = NULL;
    219             m_cWorkers--;
     237            m_workers[pWorker->index()] = 0;
     238            --m_cWorkers;
    220239            break;
    221240        }
    222241
    223         /* Wait for a task or timeout.*/
    224         m_cIdleWorkers++;
     242        /* Wait for a task or timeout: */
     243        ++m_cIdleWorkers;
    225244        fIdleTimedOut = !m_taskCondition.wait(&m_everythingLocker, m_cMsIdleTimeout);
    226         m_cIdleWorkers--;
    227     }
    228 
    229     m_everythingLocker.unlock();
    230 
    231     return NULL;
     245        --m_cIdleWorkers;
     246    }
     247
     248    /* Unlock finally: */
     249    m_everythingLocker.unlock();
     250
     251    /* Return 0 by default: */
     252    return 0;
    232253}
    233254
     
    245266{
    246267    /* Wait for the thread to finish completely, then delete the thread
    247        object. We have already removed the thread from the workers vector.
    248        Note! We don't want to use 'this' here, in case it's invalid. */
     268     * object. We have already removed the thread from the workers vector.
     269     * Note! We don't want to use 'this' here, in case it's invalid. */
    249270    pWorker->wait();
    250271    delete pWorker;
    251272}
    252273
    253 
    254274UITask::UITask(const QVariant &data)
    255275    : m_data(data)
     
    261281    /* Run task: */
    262282    run();
    263     /* Notify listener: */
     283    /* Notify listeners: */
    264284    emit sigComplete(this);
    265285}
    266 
    267286
    268287UIThreadWorker::UIThreadWorker(UIThreadPool *pPool, int iIndex)
     
    278297    COMBase::InitializeCOM(false);
    279298
    280     /* Try get a task from the pool queue. */
     299    /* Try get a task from the pool queue: */
    281300    while (UITask *pTask = m_pPool->dequeueTask(this))
    282301    {
     
    290309    COMBase::CleanupCOM();
    291310
    292     /* Queue a signal to for the pool to do thread cleanup, unless the pool is
     311    /* Queue a signal for the pool to do thread cleanup, unless the pool is
    293312       already terminating and doesn't need the signal. */
    294313    if (!m_fNoFinishedSignal)
     
    296315}
    297316
    298 
    299317#include "UIThreadPool.moc"
    300318
Note: See TracChangeset for help on using the changeset viewer.

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