mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Add a way for us to place jobs with a concurrency limit.
The main use case is having all threads stuck in ledgerData, fighting each other.
This commit is contained in:
@@ -31,6 +31,11 @@ JobQueue::JobQueue (boost::asio::io_service& svc)
|
||||
}
|
||||
|
||||
void JobQueue::addJob (JobType type, const std::string& name, const FUNCTION_TYPE<void (Job&)>& jobFunc)
|
||||
{
|
||||
addLimitJob(type, name, 0, jobFunc);
|
||||
}
|
||||
|
||||
void JobQueue::addLimitJob (JobType type, const std::string& name, int limit, const FUNCTION_TYPE<void (Job&)>& jobFunc)
|
||||
{
|
||||
assert (type != jtINVALID);
|
||||
|
||||
@@ -39,7 +44,7 @@ void JobQueue::addJob (JobType type, const std::string& name, const FUNCTION_TYP
|
||||
if (type != jtCLIENT) // FIXME: Workaround incorrect client shutdown ordering
|
||||
assert (mThreadCount != 0); // do not add jobs to a queue with no threads
|
||||
|
||||
mJobSet.insert (Job (type, name, ++mLastJob, mJobLoads[type], jobFunc));
|
||||
mJobSet.insert (Job (type, name, limit, ++mLastJob, mJobLoads[type], jobFunc));
|
||||
++mJobCounts[type].first;
|
||||
mJobCond.notify_one ();
|
||||
}
|
||||
@@ -232,6 +237,37 @@ void JobQueue::setThreadCount (int c, bool const standaloneMode)
|
||||
mJobCond.notify_one (); // in case we sucked up someone else's signal
|
||||
}
|
||||
|
||||
bool JobQueue::getJob(Job& job)
|
||||
{
|
||||
if (mJobSet.empty() || mShuttingDown)
|
||||
return false;
|
||||
|
||||
std::set<Job>::iterator it = mJobSet.begin ();
|
||||
|
||||
while (1)
|
||||
{
|
||||
// Are we out of jobs?
|
||||
if (it == mJobSet.end())
|
||||
return false;
|
||||
|
||||
// Does this job have no limit?
|
||||
if (it->getLimit() == 0)
|
||||
break;
|
||||
|
||||
// Is this job category below the limit?
|
||||
if (mJobCounts[it->getType()].second < it->getLimit())
|
||||
break;
|
||||
|
||||
// Try the next job, if any
|
||||
++it;
|
||||
}
|
||||
|
||||
job = *it;
|
||||
mJobSet.erase (it);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// do jobs until asked to stop
|
||||
void JobQueue::threadEntry ()
|
||||
{
|
||||
@@ -239,27 +275,32 @@ void JobQueue::threadEntry ()
|
||||
|
||||
while (1)
|
||||
{
|
||||
JobType type;
|
||||
|
||||
setCallingThreadName ("waiting");
|
||||
|
||||
while (mJobSet.empty () && !mShuttingDown)
|
||||
{
|
||||
mJobCond.wait (sl);
|
||||
}
|
||||
|
||||
if (mJobSet.empty ())
|
||||
break;
|
||||
|
||||
JobType type;
|
||||
std::set<Job>::iterator it = mJobSet.begin ();
|
||||
{
|
||||
Job job (*it);
|
||||
mJobSet.erase (it);
|
||||
Job job;
|
||||
while (!getJob(job))
|
||||
{
|
||||
if (mShuttingDown)
|
||||
{
|
||||
--mThreadCount;
|
||||
mJobCond.notify_all();
|
||||
return;
|
||||
}
|
||||
mJobCond.wait (sl);
|
||||
}
|
||||
|
||||
type = job.getType ();
|
||||
-- (mJobCounts[type].first);
|
||||
|
||||
if (type == jtDEATH)
|
||||
break;
|
||||
{
|
||||
--mThreadCount;
|
||||
mJobCond.notify_all();
|
||||
return;
|
||||
}
|
||||
|
||||
++ (mJobCounts[type].second);
|
||||
sl.unlock ();
|
||||
@@ -267,12 +308,10 @@ void JobQueue::threadEntry ()
|
||||
WriteLog (lsTRACE, JobQueue) << "Doing " << Job::toString (type) << " job";
|
||||
job.doJob ();
|
||||
} // must destroy job without holding lock
|
||||
|
||||
sl.lock ();
|
||||
-- (mJobCounts[type].second);
|
||||
}
|
||||
|
||||
--mThreadCount;
|
||||
mJobCond.notify_all ();
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
Reference in New Issue
Block a user