Changeset 57631 in vbox
- Timestamp:
- Sep 4, 2015 1:55:49 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIThreadPool.cpp
r57629 r57631 33 33 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 34 34 35 36 35 /** QThread extension used as worker-thread. 37 36 * Capable of executing COM-related tasks. */ … … 52 51 53 52 /** Returns worker-thread index within the worker-thread pool registry. */ 54 int getIndex() const { return m_iIndex; }53 int index() const { return m_iIndex; } 55 54 56 55 /** Disables sigFinished signal, for optimizing worker-thread pool termination. */ 57 void setNoFinishedSignal() 58 { 59 m_fNoFinishedSignal = true; 60 } 56 void setNoFinishedSignal() { m_fNoFinishedSignal = true; } 61 57 62 58 private: … … 74 70 bool m_fNoFinishedSignal; 75 71 }; 76 77 72 78 73 UIThreadPool::UIThreadPool(ulong cMaxWorkers /* = 3 */, ulong cMsWorkerIdleTimeout /* = 5000 */) … … 81 76 , m_cWorkers(0) 82 77 , m_cIdleWorkers(0) 83 , m_fTerminating(false) /* termination status */78 , m_fTerminating(false) 84 79 { 85 80 } … … 87 82 UIThreadPool::~UIThreadPool() 88 83 { 89 /* Set termination status and alert all idle worker threads: */84 /* Set termination status: */ 90 85 setTerminating(); 91 86 92 m_everythingLocker.lock(); /* paranoia */ 87 /* Lock initially: */ 88 m_everythingLocker.lock(); 93 89 94 90 /* Cleanup all the workers: */ 95 91 for (int idxWorker = 0; idxWorker < m_workers.size(); ++idxWorker) 96 92 { 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: */ 101 99 if (pWorker) 102 100 { 103 m_cWorkers--; 101 /* Decrease the number of workers: */ 102 --m_cWorkers; 103 /* Unlock temporary to let the worker finish: */ 104 104 m_everythingLocker.unlock(); 105 105 /* Wait for the worker to finish: */ 106 106 pWorker->wait(); 107 107 /* Lock again: */ 108 108 m_everythingLocker.lock(); 109 /* Delete the worker finally: */ 109 110 delete pWorker; 110 111 } 111 112 } 112 113 114 /* Unlock finally: */ 113 115 m_everythingLocker.unlock(); 114 116 } … … 116 118 bool UIThreadPool::isTerminating() const 117 119 { 120 /* Lock initially: */ 121 m_everythingLocker.lock(); 122 118 123 /* Acquire termination-flag: */ 119 m_everythingLocker.lock();120 124 bool fTerminating = m_fTerminating; 121 m_everythingLocker.unlock(); 122 125 126 /* Unlock finally: */ 127 m_everythingLocker.unlock(); 128 129 /* Return termination-flag: */ 123 130 return fTerminating; 124 131 } … … 126 133 void UIThreadPool::setTerminating() 127 134 { 128 m_everythingLocker.lock(); 129 130 /* Indicate that we're terminating: */ 135 /* Lock initially: */ 136 m_everythingLocker.lock(); 137 138 /* Assign termination-flag: */ 131 139 m_fTerminating = true; 132 140 … … 134 142 for (int idxWorker = 0; idxWorker < m_workers.size(); ++idxWorker) 135 143 { 136 UIThreadWorker *pWorker = m_workers [idxWorker];144 UIThreadWorker *pWorker = m_workers.at(idxWorker); 137 145 if (pWorker) 138 146 pWorker->setNoFinishedSignal(); … … 142 150 m_taskCondition.wakeAll(); 143 151 152 /* Unlock finally: */ 144 153 m_everythingLocker.unlock(); 145 154 } … … 147 156 void UIThreadPool::enqueueTask(UITask *pTask) 148 157 { 149 Assert(!isTerminating()); 158 /* Do nothing if terminating: */ 159 AssertReturnVoid(!isTerminating()); 150 160 151 161 /* 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: */ 157 169 m_tasks.enqueue(pTask); 158 170 … … 168 180 int idxFirstUnused = m_workers.size(); 169 181 while (idxFirstUnused-- > 0) 170 if (m_workers [idxFirstUnused] == NULL)182 if (m_workers.at(idxFirstUnused) == 0) 171 183 { 172 184 /* Prepare the new worker: */ 173 185 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); 176 188 m_workers[idxFirstUnused] = pWorker; 177 m_cWorkers++;189 ++m_cWorkers; 178 190 179 191 /* And start it: */ … … 182 194 } 183 195 } 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: */ 186 200 m_everythingLocker.unlock(); 187 201 } … … 189 203 UITask* UIThreadPool::dequeueTask(UIThreadWorker *pWorker) 190 204 { 205 /* Lock initially: */ 206 m_everythingLocker.lock(); 207 191 208 /* 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. */ 196 211 bool fIdleTimedOut = false; 197 212 while (!m_fTerminating) 198 213 { 199 Assert(m_workers[pWorker->getIndex()] == pWorker); /* paranoia */ 214 /* Make sure that worker has proper index: */ 215 Assert(m_workers.at(pWorker->index()) == pWorker); 200 216 201 217 /* Dequeue task if there is one: */ … … 205 221 if (pTask) 206 222 { 223 /* Unlock finally: */ 207 224 m_everythingLocker.unlock(); 225 226 /* Return dequeued task: */ 208 227 return pTask; 209 228 } … … 211 230 212 231 /* If we timed out already, then quit the worker thread. To prevent a 213 race between enqueueTask and the queue removal of the thread from214 the workers vector, we remove it here already. (This does not apply215 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.) */ 216 235 if (fIdleTimedOut) 217 236 { 218 m_workers[pWorker-> getIndex()] = NULL;219 m_cWorkers--;237 m_workers[pWorker->index()] = 0; 238 --m_cWorkers; 220 239 break; 221 240 } 222 241 223 /* Wait for a task or timeout .*/224 m_cIdleWorkers++;242 /* Wait for a task or timeout: */ 243 ++m_cIdleWorkers; 225 244 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; 232 253 } 233 254 … … 245 266 { 246 267 /* 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. */ 249 270 pWorker->wait(); 250 271 delete pWorker; 251 272 } 252 273 253 254 274 UITask::UITask(const QVariant &data) 255 275 : m_data(data) … … 261 281 /* Run task: */ 262 282 run(); 263 /* Notify listener : */283 /* Notify listeners: */ 264 284 emit sigComplete(this); 265 285 } 266 267 286 268 287 UIThreadWorker::UIThreadWorker(UIThreadPool *pPool, int iIndex) … … 278 297 COMBase::InitializeCOM(false); 279 298 280 /* Try get a task from the pool queue .*/299 /* Try get a task from the pool queue: */ 281 300 while (UITask *pTask = m_pPool->dequeueTask(this)) 282 301 { … … 290 309 COMBase::CleanupCOM(); 291 310 292 /* Queue a signal tofor the pool to do thread cleanup, unless the pool is311 /* Queue a signal for the pool to do thread cleanup, unless the pool is 293 312 already terminating and doesn't need the signal. */ 294 313 if (!m_fNoFinishedSignal) … … 296 315 } 297 316 298 299 317 #include "UIThreadPool.moc" 300 318
Note:
See TracChangeset
for help on using the changeset viewer.

