ZNC  trunk
Threads.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2004-2024 ZNC, see the NOTICE file for details.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ZNC_THREADS_H
18 #define ZNC_THREADS_H
19 
20 #include <znc/zncconfig.h>
21 
22 #ifdef HAVE_PTHREAD
23 
24 #include <znc/Utils.h>
25 
26 #include <cerrno>
27 #include <csignal>
28 #include <cstdlib>
29 #include <cstring>
30 #include <list>
31 #include <pthread.h>
32 #include <mutex>
33 #include <condition_variable>
34 
39 using CMutex = std::mutex;
40 
46 using CMutexLocker = std::unique_lock<std::mutex>;
47 
52 using CConditionVariable = std::condition_variable_any;
53 
67 class CJob {
68  public:
69  friend class CThreadPool;
70 
72 
73  CJob() : m_eState(READY) {}
74 
76  virtual ~CJob() {}
77 
79  virtual void runThread() = 0;
80 
84  virtual void runMain() = 0;
85 
88  bool wasCancelled() const;
89 
90  private:
91  // Undefined copy constructor and assignment operator
92  CJob(const CJob&);
93  CJob& operator=(const CJob&);
94 
95  // Synchronized via the thread pool's mutex! Do not access without that
96  // mutex!
97  EJobState m_eState;
98 };
99 
100 class CThreadPool {
101  private:
102  friend class CJob;
103 
104  CThreadPool();
105  ~CThreadPool();
106 
107  public:
108  static CThreadPool& Get();
109 
111  void addJob(CJob* job);
112 
116  void cancelJob(CJob* job);
117 
121  void cancelJobs(const std::set<CJob*>& jobs);
122 
123  int getReadFD() const { return m_iJobPipe[0]; }
124 
125  void handlePipeReadable() const;
126 
127  private:
128  void jobDone(CJob* pJob);
129 
130  // Check if the calling thread is still needed, must be called with m_mutex
131  // held
132  bool threadNeeded() const;
133 
134  CJob* getJobFromPipe() const;
135  void finishJob(CJob*) const;
136 
137  void threadFunc();
138 
139  // mutex protecting all of these members
140  CMutex m_mutex;
141 
142  // condition variable for waiting idle threads
143  CConditionVariable m_cond;
144 
145  // condition variable for reporting finished cancellation
146  CConditionVariable m_cancellationCond;
147 
148  // condition variable for waiting running threads == 0
149  CConditionVariable m_exit_cond;
150 
151  // when this is true, all threads should exit
152  bool m_done;
153 
154  // total number of running threads
155  size_t m_num_threads;
156 
157  // number of idle threads waiting on the condition variable
158  size_t m_num_idle;
159 
160  // pipe for waking up the main thread
161  int m_iJobPipe[2];
162 
163  // list of pending jobs
164  std::list<CJob*> m_jobs;
165 };
166 
167 #endif // HAVE_PTHREAD
168 #endif // !ZNC_THREADS_H
std::unique_lock< std::mutex > CMutexLocker
A mutex locker should always be used as an automatic variable.
Definition: Threads.h:46
std::condition_variable_any CConditionVariable
A condition variable makes it possible for threads to wait until some condition is reached at which p...
Definition: Threads.h:52
std::mutex CMutex
This class represents a non-recursive mutex.
Definition: Threads.h:39
A job is a task which should run without blocking the main thread.
Definition: Threads.h:67
virtual void runThread()=0
This function is called in a separate thread and can do heavy, blocking work.
virtual ~CJob()
Destructor, always called from the main thread.
Definition: Threads.h:76
bool wasCancelled() const
This can be used to check if the job was cancelled.
EJobState
Definition: Threads.h:71
@ RUNNING
Definition: Threads.h:71
@ DONE
Definition: Threads.h:71
@ CANCELLED
Definition: Threads.h:71
@ READY
Definition: Threads.h:71
virtual void runMain()=0
This function is called from the main thread after runThread() finishes.
friend class CThreadPool
Definition: Threads.h:69
CJob()
Definition: Threads.h:73
Definition: Threads.h:100
int getReadFD() const
Definition: Threads.h:123
void addJob(CJob *job)
Add a job to the thread pool and run it. The job will be deleted when done.
void handlePipeReadable() const
static CThreadPool & Get()
void cancelJobs(const std::set< CJob * > &jobs)
Cancel some jobs that were previously passed to addJob().
void cancelJob(CJob *job)
Cancel a job that was previously passed to addJob().