bool LLQueuedThread::completeRequest(handle_t handle)
{
	bool res = false;
	lockData();
	QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
	if (req)
	{
		llassert_always(req->getStatus() != STATUS_QUEUED);
		llassert_always(req->getStatus() != STATUS_INPROGRESS);
#if _DEBUG
// 		LL_INFOS() << llformat("LLQueuedThread::Completed req [%08d]",handle) << LL_ENDL;
#endif
		if (!(req->getFlags() & FLAG_LOCKED))
		{
			mRequestHash.erase(handle);
			req->deleteRequest();
// 			check();
 		}
 		else
 		{
			// Cause deletion immediately after FLAG_LOCKED is released.
 			req->setFlags(FLAG_AUTO_COMPLETE);
 		}
		res = true;
	}
	unlockData();
	return res;
}
// MAIN thread
void LLQueuedThread::setFlags(handle_t handle, U32 flags)
{
	lockData();
	QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
	if (req)
	{
		req->setFlags(flags);
	}
	unlockData();
}
void LLQueuedThread::abortRequest(handle_t handle, bool autocomplete)
{
	lockData();
	QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
	if (req)
	{
		req->setFlags(FLAG_ABORT | (autocomplete ? FLAG_AUTO_COMPLETE : 0));
	}
	unlockData();
}
LLQueuedThread::status_t LLQueuedThread::getRequestStatus(handle_t handle)
{
	status_t res = STATUS_EXPIRED;
	lockData();
	QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
	if (req)
	{
		res = req->getStatus();
	}
	unlockData();
	return res;
}
// MAIN thread
void LLQueuedThread::printQueueStats()
{
	lockData();
	if (!mRequestQueue.empty())
	{
		QueuedRequest *req = *mRequestQueue.begin();
		llinfos << llformat("Pending Requests:%d Current status:%d", mRequestQueue.size(), req->getStatus()) << llendl;
	}
	else
	{
		llinfos << "Queued Thread Idle" << llendl;
	}
	unlockData();
}
示例#6
0
void LLQueuedThread::shutdown()
{
	setQuitting();

	unpause(); // MAIN THREAD
	if (mThreaded)
	{
		S32 timeout = 100;
		for ( ; timeout>0; timeout--)
		{
			if (isStopped())
			{
				break;
			}
			ms_sleep(100);
			LLThread::yield();
		}
		if (timeout == 0)
		{
			llwarns << "~LLQueuedThread (" << mName << ") timed out!" << llendl;
		}
	}
	else
	{
		mStatus = STOPPED;
	}

	QueuedRequest* req;
	S32 active_count = 0;
	while ( (req = (QueuedRequest*)mRequestHash.pop_element()) )
	{
		if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS)
		{
			++active_count;
			req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest
		}
		req->deleteRequest();
	}
	if (active_count)
	{
		llwarns << "~LLQueuedThread() called with active requests: " << active_count << llendl;
	}
}
void LLQueuedThread::setPriority(handle_t handle, U32 priority)
{
	lockData();
	QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
	if (req)
	{
		if(req->getStatus() == STATUS_INPROGRESS)
		{
			// not in list
			req->setPriority(priority);
		}
		else if(req->getStatus() == STATUS_QUEUED)
		{
			// remove from list then re-insert
			llverify(mRequestQueue.erase(req) == 1);
			req->setPriority(priority);
			mRequestQueue.insert(req);
		}
	}
	unlockData();
}
// MAIN thread
bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_complete)
{
	llassert (handle != nullHandle());
	bool res = false;
	bool waspaused = isPaused();
	bool done = false;
	while(!done)
	{
		update(0); // unpauses
		lockData();
		QueuedRequest* req = (QueuedRequest*)mRequestHash.find(handle);
		if (!req)
		{
			done = true; // request does not exist
		}
		else if (req->getStatus() == STATUS_COMPLETE && !(req->getFlags() & FLAG_LOCKED))
		{
			res = true;
			if (auto_complete)
			{
				mRequestHash.erase(handle);
				req->deleteRequest();
// 				check();
			}
			done = true;
		}
		unlockData();
		
		if (!done && mThreaded)
		{
			yield();
		}
	}
	if (waspaused)
	{
		pause();
	}
	return res;
}
示例#9
0
void TIDorb::core::poa::RequestQueue::discardAll() 
{
  // TIDThr::Synchronized synchro(*this); // Always called from a syncronized block

  QueuedRequest* req;
 
  switch (_comparator_type){
  case PRIORITY_REQUEST_COMPARATOR:
    while (!_priority_value->empty()){  
      req = _priority_value->top();
      req->setMustDiscard(true);
      _priority_value->pop();
    }
    break;
  case DEADLINE_REQUEST_COMPARATOR:
    while (!_deadline_value->empty()){  
      req = _deadline_value->top();
      req->setMustDiscard(true);
      _deadline_value->pop();
    }
    break; 
  case TEMPORAL_REQUEST_COMPARATOR:
    while (!_temporal_value->empty()){  
      req = _temporal_value->top();
      req->setMustDiscard(true);
      _temporal_value->pop();
    }
    break;
  default:
    while (!_value->empty()){
      req = _value->front();
      req->setMustDiscard(true);
      _value->pop_front();
    }
    break;
  }

};
S32 LLQueuedThread::processNextRequest()
{
	QueuedRequest *req;
	// Get next request from pool
	lockData();
	while(1)
	{
		req = NULL;
		if (mRequestQueue.empty())
		{
			break;
		}
		req = *mRequestQueue.begin();
		mRequestQueue.erase(mRequestQueue.begin());
		if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
		{
			req->setStatus(STATUS_ABORTED);
			// Unlock, because we can't call finishRequest() while keeping this lock:
			// generateHandle() takes this lock too and is called while holding a lock
			// (ie LLTextureFetchWorker::mWorkMutex) that finishRequest will lock too,
			// causing a dead lock.
			// Although a complete rewrite of LLQueuedThread is in order because it's
			// far from robust the way it handles it's locking; the following rationale
			// at least makes plausible that releasing the lock here SHOULD work if
			// the original coder didn't completely f**k up: if before the QueuedRequest
			// req was only accessed while keeping the lock, then it still should
			// never happen that another thread is waiting for this lock in order to
			// access the QueuedRequest: a few lines lower we delete it.
			// In other words, if directly after releasing this lock another thread
			// would access req, then that can only happen by finding it again in
			// either mRequestQueue or mRequestHash. We already deleted it from the
			// first, so this access would have to happen by finding it in mRequestHash.
			// Such access happens in the following functions:
			// 1) LLQueuedThread::shutdown -- but it does that anyway, as it doesn't use any locking.
			// 2) LLQueuedThread::generateHandle -- might skip our handle while before it would block until we deleted it. Skipping it is actually better.
			// 3) LLQueuedThread::waitForResult -- this now doesn't touch the req when it has the flag FLAG_LOCKED set.
			// 4) LLQueuedThread::getRequest -- whereever this is used, FLAG_LOCKED is tested before using the req.
			// 5) LLQueuedThread::getRequestStatus -- this is a read-only operation on the status, which should never be changed from finishRequest().
			// 6) LLQueuedThread::abortRequest -- it doesn't seem to hurt to add flags (if this happens at all), while calling finishRequest().
			// 7) LLQueuedThread::setFlags -- same.
			// 8) LLQueuedThread::setPriority -- doesn't access req with status STATUS_ABORTED, STATUS_COMPLETE or STATUS_INPROGRESS.
			// 9) LLQueuedThread::completeRequest -- now sets FLAG_AUTO_COMPLETE instead of deleting the req, if FLAG_LOCKED is set, so that deletion happens here when finishRequest returns.
			req->setFlags(FLAG_LOCKED);
			unlockData();
			req->finishRequest(false);
			lockData();
			req->resetFlags(FLAG_LOCKED);
			if ((req->getFlags() & FLAG_AUTO_COMPLETE))
			{
				req->resetFlags(FLAG_AUTO_COMPLETE);
				mRequestHash.erase(req);
// 				check();
				unlockData();
				req->deleteRequest();
				lockData();
			}
			continue;
		}
		llassert_always(req->getStatus() == STATUS_QUEUED);
		break;
	}
	U32 start_priority = 0 ;
	if (req)
	{
		req->setStatus(STATUS_INPROGRESS);
		start_priority = req->getPriority();
	}
	unlockData();

	// This is the only place we will call req->setStatus() after
	// it has initially been seet to STATUS_QUEUED, so it is
	// safe to access req.
	if (req)
	{
		// process request
		bool complete = req->processRequest();

		if (complete)
		{
			lockData();
			req->setStatus(STATUS_COMPLETE);
			req->setFlags(FLAG_LOCKED);
			unlockData();
			req->finishRequest(true);
			if ((req->getFlags() & FLAG_AUTO_COMPLETE))
			{
				lockData();
				req->resetFlags(FLAG_AUTO_COMPLETE);
				mRequestHash.erase(req);
// 				check();
				req->resetFlags(FLAG_LOCKED);
				unlockData();
				req->deleteRequest();
			}
			else
			{
				req->resetFlags(FLAG_LOCKED);
			}
		}
		else
		{
			lockData();
			req->setStatus(STATUS_QUEUED);
			mRequestQueue.insert(req);
			unlockData();
			if (mThreaded && start_priority < PRIORITY_NORMAL)
			{
				ms_sleep(1); // sleep the thread a little
			}
		}
	}

	S32 pending = getPending();

	return pending;
}