Changeset 82998 in vbox for trunk/src/VBox/Frontends/VirtualBox
- Timestamp:
- Feb 5, 2020 7:14:36 PM (5 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 6 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r82995 r82998 825 825 src/globals/UIProgressEventHandler.h \ 826 826 src/globals/UIShortcutPool.h \ 827 src/globals/UITask.h \ 827 828 src/globals/UIThreadPool.h \ 828 829 src/globals/UITextTable.h \ … … 1324 1325 src/globals/UIShortcutPool.cpp \ 1325 1326 src/globals/UITextTable.cpp \ 1327 src/globals/UITask.cpp \ 1326 1328 src/globals/UIThreadPool.cpp \ 1327 1329 src/globals/UIVersion.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UITask.cpp
r82974 r82998 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIT hreadPool and UITask classes implementation.3 * VBox Qt GUI - UITask class implementation. 4 4 */ 5 5 … … 16 16 */ 17 17 18 /* Qt includes: */19 #include <QThread>20 21 18 /* GUI includes: */ 22 #include "COMDefs.h" 23 #include "UIDefs.h" 24 #include "UIThreadPool.h" 25 26 /* Other VBox includes: */ 27 #include <iprt/assert.h> 28 29 30 /** QThread extension used as worker-thread. 31 * Capable of executing COM-related tasks. */ 32 class UIThreadWorker : public QThread 33 { 34 Q_OBJECT; 35 36 signals: 37 38 /** Notifies listeners about @a pWorker finished. */ 39 void sigFinished(UIThreadWorker *pWorker); 40 41 public: 42 43 /** Constructs worker-thread for parent worker-thread @a pPool. 44 * @param iIndex Brings worker-thread index within the worker-thread pool registry. */ 45 UIThreadWorker(UIThreadPool *pPool, int iIndex); 46 47 /** Returns worker-thread index within the worker-thread pool registry. */ 48 int index() const { return m_iIndex; } 49 50 /** Disables sigFinished signal, for optimizing worker-thread pool termination. */ 51 void setNoFinishedSignal() { m_fNoFinishedSignal = true; } 52 53 private: 54 55 /** Contains the worker-thread body. */ 56 void run(); 57 58 /** Holds the worker-thread pool reference. */ 59 UIThreadPool *m_pPool; 60 61 /** Holds the worker-thread index within the worker-thread pool registry. */ 62 int m_iIndex; 63 64 /** Holds whether sigFinished signal should be emitted or not. */ 65 bool m_fNoFinishedSignal; 66 }; 67 68 69 /********************************************************************************************************************************* 70 * Class UIThreadPool implementation. * 71 *********************************************************************************************************************************/ 72 73 UIThreadPool::UIThreadPool(ulong cMaxWorkers /* = 3 */, ulong cMsWorkerIdleTimeout /* = 5000 */) 74 : m_cMsIdleTimeout(cMsWorkerIdleTimeout) 75 , m_workers(cMaxWorkers) 76 , m_cWorkers(0) 77 , m_cIdleWorkers(0) 78 , m_fTerminating(false) 79 { 80 } 81 82 UIThreadPool::~UIThreadPool() 83 { 84 /* Set termination status: */ 85 setTerminating(); 86 87 /* Lock initially: */ 88 m_everythingLocker.lock(); 89 90 /* Cleanup all the workers: */ 91 for (int idxWorker = 0; idxWorker < m_workers.size(); ++idxWorker) 92 { 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: */ 99 if (pWorker) 100 { 101 /* Decrease the number of workers: */ 102 --m_cWorkers; 103 /* Unlock temporary to let the worker finish: */ 104 m_everythingLocker.unlock(); 105 /* Wait for the worker to finish: */ 106 pWorker->wait(); 107 /* Lock again: */ 108 m_everythingLocker.lock(); 109 /* Delete the worker finally: */ 110 delete pWorker; 111 } 112 } 113 114 /* Cleanup all the tasks: */ 115 qDeleteAll(m_pendingTasks); 116 qDeleteAll(m_executingTasks); 117 m_pendingTasks.clear(); 118 m_executingTasks.clear(); 119 120 /* Unlock finally: */ 121 m_everythingLocker.unlock(); 122 } 123 124 bool UIThreadPool::isTerminating() const 125 { 126 /* Lock initially: */ 127 m_everythingLocker.lock(); 128 129 /* Acquire termination-flag: */ 130 bool fTerminating = m_fTerminating; 131 132 /* Unlock finally: */ 133 m_everythingLocker.unlock(); 134 135 /* Return termination-flag: */ 136 return fTerminating; 137 } 138 139 void UIThreadPool::setTerminating() 140 { 141 /* Lock initially: */ 142 m_everythingLocker.lock(); 143 144 /* Assign termination-flag: */ 145 m_fTerminating = true; 146 147 /* Tell all threads to NOT queue any termination signals: */ 148 for (int idxWorker = 0; idxWorker < m_workers.size(); ++idxWorker) 149 { 150 UIThreadWorker *pWorker = m_workers.at(idxWorker); 151 if (pWorker) 152 pWorker->setNoFinishedSignal(); 153 } 154 155 /* Wake up all idle worker threads: */ 156 m_taskCondition.wakeAll(); 157 158 /* Unlock finally: */ 159 m_everythingLocker.unlock(); 160 } 161 162 void UIThreadPool::enqueueTask(UITask *pTask) 163 { 164 /* Do nothing if terminating: */ 165 AssertReturnVoid(!isTerminating()); 166 167 /* Prepare task: */ 168 connect(pTask, &UITask::sigComplete, 169 this, &UIThreadPool::sltHandleTaskComplete, Qt::QueuedConnection); 170 171 /* Lock initially: */ 172 m_everythingLocker.lock(); 173 174 /* Put the task into the queue: */ 175 m_pendingTasks.enqueue(pTask); 176 177 /* Wake up an idle worker if we got one: */ 178 if (m_cIdleWorkers > 0) 179 { 180 m_taskCondition.wakeOne(); 181 } 182 /* No idle worker threads, should we create a new one? */ 183 else if (m_cWorkers < m_workers.size()) 184 { 185 /* Find free slot: */ 186 int idxFirstUnused = m_workers.size(); 187 while (idxFirstUnused-- > 0) 188 if (m_workers.at(idxFirstUnused) == 0) 189 { 190 /* Prepare the new worker: */ 191 UIThreadWorker *pWorker = new UIThreadWorker(this, idxFirstUnused); 192 connect(pWorker, &UIThreadWorker::sigFinished, 193 this, &UIThreadPool::sltHandleWorkerFinished, Qt::QueuedConnection); 194 m_workers[idxFirstUnused] = pWorker; 195 ++m_cWorkers; 196 197 /* And start it: */ 198 pWorker->start(); 199 break; 200 } 201 } 202 /* else: wait for some worker to complete 203 * whatever it's busy with and jump to it. */ 204 205 /* Unlock finally: */ 206 m_everythingLocker.unlock(); 207 } 208 209 UITask *UIThreadPool::dequeueTask(UIThreadWorker *pWorker) 210 { 211 /* Lock initially: */ 212 m_everythingLocker.lock(); 213 214 /* Dequeue a task, watching out for terminations. 215 * For optimal efficiency in enqueueTask() we keep count of idle threads. 216 * If the wait times out, we'll return 0 and terminate the thread. */ 217 bool fIdleTimedOut = false; 218 while (!m_fTerminating) 219 { 220 /* Make sure that worker has proper index: */ 221 Assert(m_workers.at(pWorker->index()) == pWorker); 222 223 /* Dequeue task if there is one: */ 224 if (!m_pendingTasks.isEmpty()) 225 { 226 UITask *pTask = m_pendingTasks.dequeue(); 227 if (pTask) 228 { 229 /* Put into the set of executing tasks: */ 230 m_executingTasks << pTask; 231 232 /* Unlock finally: */ 233 m_everythingLocker.unlock(); 234 235 /* Return dequeued task: */ 236 return pTask; 237 } 238 } 239 240 /* If we timed out already, then quit the worker thread. To prevent a 241 * race between enqueueTask and the queue removal of the thread from 242 * the workers vector, we remove it here already. (This does not apply 243 * to the termination scenario.) */ 244 if (fIdleTimedOut) 245 { 246 m_workers[pWorker->index()] = 0; 247 --m_cWorkers; 248 break; 249 } 250 251 /* Wait for a task or timeout: */ 252 ++m_cIdleWorkers; 253 fIdleTimedOut = !m_taskCondition.wait(&m_everythingLocker, m_cMsIdleTimeout); 254 --m_cIdleWorkers; 255 } 256 257 /* Unlock finally: */ 258 m_everythingLocker.unlock(); 259 260 /* Return 0 by default: */ 261 return 0; 262 } 263 264 void UIThreadPool::sltHandleTaskComplete(UITask *pTask) 265 { 266 /* Skip on termination: */ 267 if (isTerminating()) 268 return; 269 270 /* Notify listeners: */ 271 emit sigTaskComplete(pTask); 272 273 /* Lock initially: */ 274 m_everythingLocker.lock(); 275 276 /* Delete task finally: */ 277 if ( !m_executingTasks.contains(pTask) 278 || !m_executingTasks.remove(pTask)) 279 AssertMsgFailed(("Unable to find or remove complete task!")); 280 delete pTask; 281 282 /* Unlock finally: */ 283 m_everythingLocker.unlock(); 284 } 285 286 void UIThreadPool::sltHandleWorkerFinished(UIThreadWorker *pWorker) 287 { 288 /* Wait for the thread to finish completely, then delete the thread 289 * object. We have already removed the thread from the workers vector. 290 * Note! We don't want to use 'this' here, in case it's invalid. */ 291 pWorker->wait(); 292 delete pWorker; 293 } 19 #include "UITask.h" 294 20 295 21 void UITask::start() … … 300 26 emit sigComplete(this); 301 27 } 302 303 304 /*********************************************************************************************************************************305 * Class UIThreadWorker implementation. *306 *********************************************************************************************************************************/307 308 UIThreadWorker::UIThreadWorker(UIThreadPool *pPool, int iIndex)309 : m_pPool(pPool)310 , m_iIndex(iIndex)311 , m_fNoFinishedSignal(false)312 {313 }314 315 void UIThreadWorker::run()316 {317 /* Initialize COM: */318 COMBase::InitializeCOM(false);319 320 /* Try get a task from the pool queue: */321 while (UITask *pTask = m_pPool->dequeueTask(this))322 {323 /* Process the task if we are not terminating.324 * Please take into account tasks are cleared by the UIThreadPool325 * after all listeners notified about task is complete and handled it. */326 if (!m_pPool->isTerminating())327 pTask->start();328 }329 330 /* Cleanup COM: */331 COMBase::CleanupCOM();332 333 /* Queue a signal for the pool to do thread cleanup, unless the pool is334 already terminating and doesn't need the signal. */335 if (!m_fNoFinishedSignal)336 emit sigFinished(this);337 }338 339 340 #include "UIThreadPool.moc"341 -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UITask.h
r82974 r82998 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIT hreadPool and UITask classes declaration.3 * VBox Qt GUI - UITask class declaration. 4 4 */ 5 5 … … 16 16 */ 17 17 18 #ifndef FEQT_INCLUDED_SRC_globals_UIT hreadPool_h19 #define FEQT_INCLUDED_SRC_globals_UIT hreadPool_h18 #ifndef FEQT_INCLUDED_SRC_globals_UITask_h 19 #define FEQT_INCLUDED_SRC_globals_UITask_h 20 20 #ifndef RT_WITHOUT_PRAGMA_ONCE 21 21 # pragma once … … 23 23 24 24 /* Qt includes: */ 25 #include <QMutex>26 25 #include <QObject> 27 #include <QQueue>28 #include <QSet>29 #include <QVariant>30 #include <QVector>31 #include <QWaitCondition>32 26 33 27 /* GUI includes: */ 34 28 #include "UILibraryDefs.h" 35 29 36 /* Forward declarations: */37 class UITask;38 class UIThreadWorker;39 40 41 /** QObject extension used as worker-thread pool.42 * Schedules COM-related GUI tasks to multiple worker-threads. */43 class SHARED_LIBRARY_STUFF UIThreadPool : public QObject44 {45 Q_OBJECT;46 47 signals:48 49 /** Notifies listeners about @a pTask complete. */50 void sigTaskComplete(UITask *pTask);51 52 public:53 54 /** Constructs worker-thread pool.55 * @param cMaxWorkers Brings the maximum amount of worker-threads.56 * @param cMsWorkerIdleTimeout Brings the maximum amount of time (in ms) which57 * pool will wait for the worker-thread on cleanup. */58 UIThreadPool(ulong cMaxWorkers = 3, ulong cMsWorkerIdleTimeout = 5000);59 /** Destructs worker-thread pool. */60 ~UIThreadPool();61 62 /** Returns whether the 'termination sequence' is started. */63 bool isTerminating() const;64 /** Defines that the 'termination sequence' is started. */65 void setTerminating();66 67 /** Enqueues @a pTask into the task-queue. */68 void enqueueTask(UITask *pTask);69 /** Returns dequeued top-most task from the task-queue. */70 UITask *dequeueTask(UIThreadWorker *pWorker);71 72 private slots:73 74 /** Handles @a pTask complete signal. */75 void sltHandleTaskComplete(UITask *pTask);76 77 /** Handles @a pWorker finished signal. */78 void sltHandleWorkerFinished(UIThreadWorker *pWorker);79 80 private:81 82 /** @name Worker-thread stuff.83 * @{ */84 /** Holds the maximum amount of time (in ms) which85 * pool will wait for the worker-thread on cleanup. */86 const ulong m_cMsIdleTimeout;87 /** Holds the vector of worker-threads. */88 QVector<UIThreadWorker*> m_workers;89 /** Holds the number of worker-threads.90 * @remarks We cannot use the vector size since it may contain 0 pointers. */91 int m_cWorkers;92 /** Holds the number of idle worker-threads. */93 int m_cIdleWorkers;94 /** Holds whether the 'termination sequence' is started95 * and all worker-threads should terminate ASAP. */96 bool m_fTerminating;97 /** @} */98 99 /** @name Task stuff100 * @{ */101 /** Holds the queue of pending tasks. */102 QQueue<UITask*> m_pendingTasks;103 /** Holds the set of executing tasks. */104 QSet<UITask*> m_executingTasks;105 /** Holds the condition variable that gets signalled when106 * queuing a new task and there are idle worker threads around.107 * @remarks Idle threads sits in dequeueTask waiting for this.108 * Thus on thermination, setTerminating() will send a109 * broadcast signal to wake up all workers (after110 * setting m_fTerminating of course). */111 QWaitCondition m_taskCondition;112 /** @} */113 114 /** Holds the guard mutex object protecting115 * all the inter-thread variables. */116 mutable QMutex m_everythingLocker;117 };118 119 120 30 /** QObject extension used as worker-thread task interface. 121 * Describes task to be executed by the UIThreadWorkerobject. */31 * Describes task to be handled by the UIThreadPool object. */ 122 32 class SHARED_LIBRARY_STUFF UITask : public QObject 123 33 { … … 155 65 156 66 /** Holds the type of the task. */ 157 const UITask::Type m_enmType;67 const UITask::Type m_enmType; 158 68 }; 159 69 160 161 #endif /* !FEQT_INCLUDED_SRC_globals_UIThreadPool_h */ 162 70 #endif /* !FEQT_INCLUDED_SRC_globals_UITask_h */ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIThreadPool.cpp
r82968 r82998 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIThreadPool and UITask classes implementation.3 * VBox Qt GUI - UIThreadPool class implementation. 4 4 */ 5 5 … … 22 22 #include "COMDefs.h" 23 23 #include "UIDefs.h" 24 #include "UITask.h" 24 25 #include "UIThreadPool.h" 25 26 … … 60 61 61 62 /** Holds the worker-thread index within the worker-thread pool registry. */ 62 int m_iIndex;63 int m_iIndex; 63 64 64 65 /** Holds whether sigFinished signal should be emitted or not. */ 65 bool m_fNoFinishedSignal;66 bool m_fNoFinishedSignal; 66 67 }; 67 68 … … 293 294 } 294 295 295 void UITask::start()296 {297 /* Run task: */298 run();299 /* Notify listeners: */300 emit sigComplete(this);301 }302 303 296 304 297 /********************************************************************************************************************************* … … 339 332 340 333 #include "UIThreadPool.moc" 341 -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIThreadPool.h
r82968 r82998 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIThreadPool and UITask classes declaration.3 * VBox Qt GUI - UIThreadPool class declaration. 4 4 */ 5 5 … … 27 27 #include <QQueue> 28 28 #include <QSet> 29 #include <QVariant>30 29 #include <QVector> 31 30 #include <QWaitCondition> … … 37 36 class UITask; 38 37 class UIThreadWorker; 39 40 38 41 39 /** QObject extension used as worker-thread pool. … … 58 56 UIThreadPool(ulong cMaxWorkers = 3, ulong cMsWorkerIdleTimeout = 5000); 59 57 /** Destructs worker-thread pool. */ 60 ~UIThreadPool();58 virtual ~UIThreadPool() /* override */; 61 59 62 60 /** Returns whether the 'termination sequence' is started. */ … … 114 112 /** Holds the guard mutex object protecting 115 113 * all the inter-thread variables. */ 116 mutable QMutex m_everythingLocker;114 mutable QMutex m_everythingLocker; 117 115 }; 118 116 119 120 /** QObject extension used as worker-thread task interface.121 * Describes task to be executed by the UIThreadWorker object. */122 class SHARED_LIBRARY_STUFF UITask : public QObject123 {124 Q_OBJECT;125 126 signals:127 128 /** Notifies listeners about @a pTask complete. */129 void sigComplete(UITask *pTask);130 131 public:132 133 /** Task types. */134 enum Type135 {136 Type_MediumEnumeration = 1,137 Type_DetailsPopulation = 2,138 };139 140 /** Constructs the task of passed @a enmType. */141 UITask(UITask::Type enmType) : m_enmType(enmType) {}142 143 /** Returns the type of the task. */144 UITask::Type type() const { return m_enmType; }145 146 /** Starts the task. */147 void start();148 149 protected:150 151 /** Contains the abstract task body. */152 virtual void run() = 0;153 154 private:155 156 /** Holds the type of the task. */157 const UITask::Type m_enmType;158 };159 160 161 117 #endif /* !FEQT_INCLUDED_SRC_globals_UIThreadPool_h */ 162 -
trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsElements.cpp
r82968 r82998 18 18 /* Qt includes: */ 19 19 #include <QDir> 20 #include <QGraphicsLinearLayout> 20 21 #include <QTimer> 21 #include <QGraphicsLinearLayout>22 22 23 23 /* GUI includes: */ 24 #include "UICommon.h" 25 #include "UIConverter.h" 24 26 #include "UIDetailsElements.h" 25 27 #include "UIDetailsGenerator.h" 26 28 #include "UIDetailsModel.h" 29 #include "UIErrorString.h" 30 #include "UIGraphicsRotatorButton.h" 31 #include "UIGraphicsTextPane.h" 32 #include "UIIconPool.h" 27 33 #include "UIMachinePreview.h" 28 #include "UIGraphicsRotatorButton.h" 29 #include "UICommon.h" 30 #include "UIIconPool.h" 31 #include "UIConverter.h" 32 #include "UIGraphicsTextPane.h" 33 #include "UIErrorString.h" 34 #include "UIThreadPool.h" 34 35 35 36 /* COM includes: */ 36 37 #include "COMEnums.h" 38 #include "CAudioAdapter.h" 37 39 #include "CMachine.h" 40 #include "CMedium.h" 41 #include "CMediumAttachment.h" 42 #include "CNetworkAdapter.h" 43 #include "CRecordingScreenSettings.h" 44 #include "CRecordingSettings.h" 45 #include "CSerialPort.h" 46 #include "CSharedFolder.h" 47 #include "CStorageController.h" 38 48 #include "CSystemProperties.h" 49 #include "CUSBController.h" 50 #include "CUSBDeviceFilter.h" 51 #include "CUSBDeviceFilters.h" 39 52 #include "CVRDEServer.h" 40 #include "CStorageController.h"41 #include "CMediumAttachment.h"42 #include "CAudioAdapter.h"43 #include "CRecordingSettings.h"44 #include "CRecordingScreenSettings.h"45 #include "CNetworkAdapter.h"46 #include "CSerialPort.h"47 #include "CUSBController.h"48 #include "CUSBDeviceFilters.h"49 #include "CUSBDeviceFilter.h"50 #include "CSharedFolder.h"51 #include "CMedium.h"52 53 53 54 UIDetailsUpdateTask::UIDetailsUpdateTask(const CMachine &machine) -
trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsElements.h
r82968 r82998 23 23 24 24 /* GUI includes: */ 25 #include "UIThreadPool.h"26 25 #include "UIDetailsElement.h" 26 #include "UITask.h" 27 27 28 28 /* Forward declarations: */ -
trunk/src/VBox/Frontends/VirtualBox/src/medium/UIMediumEnumerator.cpp
r82968 r82998 23 23 #include "UIMediumEnumerator.h" 24 24 #include "UIMessageCenter.h" 25 #include "UITask.h" 25 26 #include "UIThreadPool.h" 26 27 #include "UIVirtualBoxEventHandler.h"
Note:
See TracChangeset
for help on using the changeset viewer.