mirror of
https://github.com/znc/znc.git
synced 2026-08-07 01:13:25 +02:00
CThreadPool: Add cancellation support
This adds CThreadPool::cancelJob() and cancelJobs() which can cancel a set of jobs synchronously. These functions only return when the job was successfully cancelled. It tries to cancel the jobs as quickly as possible, skipping any callbacks on CJob that were not yet called. A job that is already running can use CJob::wasCancelled() to check if it should quit. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
+38
-2
@@ -216,6 +216,17 @@ private:
|
||||
*/
|
||||
class CJob {
|
||||
public:
|
||||
friend class CThreadPool;
|
||||
|
||||
enum EJobState {
|
||||
READY,
|
||||
RUNNING,
|
||||
DONE,
|
||||
CANCELLED
|
||||
};
|
||||
|
||||
CJob() : m_eState(READY) {}
|
||||
|
||||
/// Destructor, always called from the main thread.
|
||||
virtual ~CJob() {}
|
||||
|
||||
@@ -224,17 +235,26 @@ public:
|
||||
|
||||
/// This function is called from the main thread after runThread()
|
||||
/// finishes. It can be used to handle the results from runThread()
|
||||
/// without needing synchronization primitives.
|
||||
/// without needing synchronization primitives.
|
||||
virtual void runMain() = 0;
|
||||
|
||||
/// This can be used to check if the job was cancelled. For example,
|
||||
/// runThread() can return early if this returns true.
|
||||
bool wasCancelled() const;
|
||||
|
||||
private:
|
||||
// Undefined copy constructor and assignment operator
|
||||
CJob(const CJob&);
|
||||
CJob& operator=(const CJob&);
|
||||
|
||||
// Synchronized via the thread pool's mutex! Do not access without that mutex!
|
||||
EJobState m_eState;
|
||||
};
|
||||
|
||||
class CThreadPool {
|
||||
private:
|
||||
friend class CJob;
|
||||
|
||||
CThreadPool();
|
||||
~CThreadPool();
|
||||
|
||||
@@ -244,6 +264,16 @@ public:
|
||||
/// Add a job to the thread pool and run it. The job will be deleted when done.
|
||||
void addJob(CJob *job);
|
||||
|
||||
/// Cancel a job that was previously passed to addJob(). This *might*
|
||||
/// mean that runThread() and/or runMain() will not be called on the job.
|
||||
/// This function BLOCKS until the job finishes!
|
||||
void cancelJob(CJob *job);
|
||||
|
||||
/// Cancel some jobs that were previously passed to addJob(). This *might*
|
||||
/// mean that runThread() and/or runMain() will not be called on some of
|
||||
/// the jobs. This function BLOCKS until all jobs finish!
|
||||
void cancelJobs(const std::set<CJob *> &jobs);
|
||||
|
||||
int getReadFD() const {
|
||||
return m_iJobPipe[0];
|
||||
}
|
||||
@@ -251,11 +281,14 @@ public:
|
||||
void handlePipeReadable() const;
|
||||
|
||||
private:
|
||||
void jobDone(const CJob* pJob) const;
|
||||
void jobDone(CJob* pJob);
|
||||
|
||||
// Check if the calling thread is still needed, must be called with m_mutex held
|
||||
bool threadNeeded() const;
|
||||
|
||||
CJob *getJobFromPipe() const;
|
||||
void finishJob(CJob *) const;
|
||||
|
||||
void threadFunc();
|
||||
static void *threadPoolFunc(void *arg) {
|
||||
CThreadPool &pool = *reinterpret_cast<CThreadPool *>(arg);
|
||||
@@ -269,6 +302,9 @@ private:
|
||||
// condition variable for waiting idle threads
|
||||
CConditionVariable m_cond;
|
||||
|
||||
// condition variable for reporting finished cancellation
|
||||
CConditionVariable m_cancellationCond;
|
||||
|
||||
// when this is true, all threads should exit
|
||||
bool m_done;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user