void ThreadPool::executeParallelAsync( RC::Handle<LogCollector> const &logCollector, size_t count, void (*callback)( void *userdata, size_t index ), void *userdata, size_t flags, void (*finishedCallback)( void *finishedUserdata ), void *finishedUserdata ) { if ( count == 0 ) finishedCallback( finishedUserdata ); else { Task *task = new Task( true, logCollector, count, callback, userdata, finishedCallback, finishedUserdata ); m_stateMutex.acquire(); if ( (flags & MainThreadOnly) ) m_mainThreadTasks.push_back( task ); else if ( (flags & Idle) ) m_idleTasks.push_back( task ); else m_tasks.push_back( task ); // [pzion 20101108] Must wake waiter because there is work to do m_stateCond.broadcast(); m_stateMutex.release(); } }
void ThreadPool::executeOneTaskIfPossible_CRITICAL_SECTION() { if ( m_tasks.empty() && m_idleTasks.empty() && (!m_isMainThread.get() || m_mainThreadTasks.empty()) ) m_stateCond.wait( m_stateMutex ); else { std::vector<Task *> *taskQueue; if ( m_isMainThread.get() && !m_mainThreadTasks.empty() ) taskQueue = &m_mainThreadTasks; else if ( !m_tasks.empty() ) taskQueue = &m_tasks; else taskQueue = &m_idleTasks; Task *task = taskQueue->back(); size_t index; bool keep; task->preExecute_CRITICAL_SECTION( index, keep ); if ( !keep ) taskQueue->pop_back(); m_stateMutex.release(); try { task->execute( index ); } catch ( Exception e ) { Util::SimpleString prefixedException = "Exception: " + e.getDesc(); RC::Handle<LogCollector> logCollector = task->getLogCollector(); if ( logCollector ) logCollector->add( prefixedException.data(), prefixedException.length() ); } catch ( ... ) { static Util::SimpleString const genericException = "Exception (unknown)"; RC::Handle<LogCollector> logCollector = task->getLogCollector(); if ( logCollector ) logCollector->add( genericException.data(), genericException.length() ); } m_stateMutex.acquire(); task->postExecute_CRITICAL_SECTION(); if ( task->completed_CRITICAL_SECTION() ) { void (*finishedCallback)( void * ) = task->getFinishedCallback(); if ( finishedCallback ) finishedCallback( task->getFinishedUserdata() ); task->dispose(); // [pzion 20101108] Must wake waiter because they might be // waiting on the task completion m_stateCond.broadcast(); } } }
void IORequest::NotifyFinished() { TRACE("IORequest::NotifyFinished(): request: %p\n", this); MutexLocker locker(fLock); if (fStatus == B_OK && !fPartialTransfer && RemainingBytes() > 0) { // The request is not really done yet. If it has an iteration callback, // call it. if (fIterationCallback != NULL) { ResetStatus(); locker.Unlock(); bool partialTransfer = false; status_t error = fIterationCallback(fIterationCookie, this, &partialTransfer); if (error == B_OK && !partialTransfer) return; // Iteration failed, which means we're responsible for notifying the // requests finished. locker.Lock(); fStatus = error; fPartialTransfer = true; } } ASSERT(fPendingChildren == 0); ASSERT(fChildren.IsEmpty() || dynamic_cast<IOOperation*>(fChildren.Head()) == NULL); // unlock the memory if (fBuffer->IsMemoryLocked()) fBuffer->UnlockMemory(fTeam, fIsWrite); // Cache the callbacks before we unblock waiters and unlock. Any of the // following could delete this request, so we don't want to touch it // once we have started telling others that it is done. IORequest* parent = fParent; io_request_finished_callback finishedCallback = fFinishedCallback; void* finishedCookie = fFinishedCookie; status_t status = fStatus; size_t lastTransferredOffset = fRelativeParentOffset + fTransferSize; bool partialTransfer = status != B_OK || fPartialTransfer; bool deleteRequest = (fFlags & B_DELETE_IO_REQUEST) != 0; // unblock waiters fIsNotified = true; fFinishedCondition.NotifyAll(); locker.Unlock(); // notify callback if (finishedCallback != NULL) { finishedCallback(finishedCookie, this, status, partialTransfer, lastTransferredOffset); } // notify parent if (parent != NULL) { parent->SubRequestFinished(this, status, partialTransfer, lastTransferredOffset); } if (deleteRequest) delete this; }