jobserver: synchronization cleanup
This change cleans up in/out queue synchronization in the job server. End-of-jobs conditions are now properly signaled through the SynchronizedQueue, allowing to resume and abort blocked readers when no more input is expected. Change-Id: I3eaf37115ccf8c5b5afe3d971c7109cd62b68906
This commit is contained in:
@ -41,21 +41,30 @@ boost::mutex CommThread::m_CommMutex;
|
|||||||
ExperimentData *JobServer::getDone()
|
ExperimentData *JobServer::getDone()
|
||||||
{
|
{
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
if (m_undoneJobs.Size() == 0
|
ExperimentData *exp = m_doneJobs.Dequeue();
|
||||||
&& noMoreExperiments()
|
if (exp) {
|
||||||
&& m_runningJobs.Size() == 0
|
m_inOutCounter.decrement();
|
||||||
&& m_doneJobs.Size() == 0
|
|
||||||
&& m_inOutCounter.getValue() == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ExperimentData *exp = NULL;
|
|
||||||
exp = m_doneJobs.Dequeue();
|
|
||||||
m_inOutCounter.decrement();
|
|
||||||
return exp;
|
return exp;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JobServer::setNoMoreExperiments()
|
||||||
|
{
|
||||||
|
#ifndef __puma
|
||||||
|
boost::unique_lock<boost::mutex> lock(CommThread::m_CommMutex);
|
||||||
|
#endif
|
||||||
|
// currently not really necessary, as we only non-blockingly dequeue:
|
||||||
|
m_undoneJobs.setIsFinished();
|
||||||
|
|
||||||
|
m_noMoreExps = true;
|
||||||
|
if (m_undoneJobs.Size() == 0 &&
|
||||||
|
noMoreExperiments() &&
|
||||||
|
m_runningJobs.Size() == 0) {
|
||||||
|
m_doneJobs.setIsFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SERVER_PERFORMANCE_MEASURE
|
#ifdef SERVER_PERFORMANCE_MEASURE
|
||||||
void JobServer::measure()
|
void JobServer::measure()
|
||||||
{
|
{
|
||||||
@ -361,6 +370,12 @@ void CommThread::receiveExperimentResults(Minion& minion, FailControlMessage& ct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all results complete?
|
||||||
|
if (m_js.m_undoneJobs.Size() == 0 &&
|
||||||
|
m_js.noMoreExperiments() &&
|
||||||
|
m_js.m_runningJobs.Size() == 0) {
|
||||||
|
m_js.m_doneJobs.setIsFinished();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|||||||
@ -118,7 +118,7 @@ public:
|
|||||||
* sets. We need this, as we allow concurrent parameter generation and
|
* sets. We need this, as we allow concurrent parameter generation and
|
||||||
* distribution.
|
* distribution.
|
||||||
*/
|
*/
|
||||||
void setNoMoreExperiments() { m_noMoreExps = true; }
|
void setNoMoreExperiments();
|
||||||
/**
|
/**
|
||||||
* Checks whether there are no more experiment parameter sets.
|
* Checks whether there are no more experiment parameter sets.
|
||||||
* @return \c true if no more parameter sets available, \c false otherwise
|
* @return \c true if no more parameter sets available, \c false otherwise
|
||||||
|
|||||||
@ -18,14 +18,15 @@ class SynchronizedQueue { // Adapted from: http://www.quantnet.com/cplusplus-mul
|
|||||||
private:
|
private:
|
||||||
std::queue<T> m_queue; //!< Use STL queue to store data
|
std::queue<T> m_queue; //!< Use STL queue to store data
|
||||||
unsigned capacity;
|
unsigned capacity;
|
||||||
|
bool finished;
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
boost::mutex m_mutex; //!< The mutex to synchronise on
|
boost::mutex m_mutex; //!< The mutex to synchronise on
|
||||||
boost::condition_variable m_cond; //!< The condition to wait for
|
boost::condition_variable m_cond; //!< The condition to wait for
|
||||||
boost::condition_variable m_cond_capacity; //!< Another condition to wait for
|
boost::condition_variable m_cond_capacity; //!< Another condition to wait for
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
SynchronizedQueue() : capacity(0) {}
|
SynchronizedQueue() : capacity(0), finished(false) {}
|
||||||
SynchronizedQueue(unsigned capacity) : capacity(capacity) {}
|
SynchronizedQueue(unsigned capacity) : capacity(capacity), finished(false) {}
|
||||||
int Size()
|
int Size()
|
||||||
{
|
{
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
@ -69,6 +70,10 @@ public:
|
|||||||
// again after the wait
|
// again after the wait
|
||||||
#ifndef __puma
|
#ifndef __puma
|
||||||
while (m_queue.size() == 0) {
|
while (m_queue.size() == 0) {
|
||||||
|
if (finished) {
|
||||||
|
// default-constructed T, 0 for integral types
|
||||||
|
return T();
|
||||||
|
}
|
||||||
m_cond.wait(lock);
|
m_cond.wait(lock);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -116,6 +121,17 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} // Lock is automatically released here
|
} // Lock is automatically released here
|
||||||
|
|
||||||
|
void setIsFinished(bool value = true)
|
||||||
|
{
|
||||||
|
#ifndef __puma
|
||||||
|
boost::unique_lock<boost::mutex> lock(m_mutex);
|
||||||
|
#endif
|
||||||
|
finished = value;
|
||||||
|
#ifndef __puma
|
||||||
|
m_cond.notify_all();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end-of-namespace: fail
|
} // end-of-namespace: fail
|
||||||
|
|||||||
Reference in New Issue
Block a user