Ejemplo n.º 1
0
 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();
   }
 }
Ejemplo n.º 2
0
    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();
        }
      }
    }
Ejemplo n.º 3
0
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;
}