mirror of
https://github.com/znc/znc.git
synced 2026-07-06 01:41:12 +02:00
Use C++11 threads instead of custom pthread wrappers.
Signal handling of CThread was handled in previous commit.
This commit is contained in:
+5
-162
@@ -29,179 +29,27 @@
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <pthread.h>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
|
||||
/**
|
||||
* This class represents a non-recursive mutex. Only a single thread may own the
|
||||
* mutex at any point in time.
|
||||
*/
|
||||
class CMutex {
|
||||
public:
|
||||
friend class CConditionVariable;
|
||||
|
||||
CMutex() : m_mutex() {
|
||||
int i = pthread_mutex_init(&m_mutex, nullptr);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't initialize mutex: " + CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
~CMutex() {
|
||||
int i = pthread_mutex_destroy(&m_mutex);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't destroy mutex: " + CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void lock() {
|
||||
int i = pthread_mutex_lock(&m_mutex);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't lock mutex: " + CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
int i = pthread_mutex_unlock(&m_mutex);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't unlock mutex: " + CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Undefined copy constructor and assignment operator
|
||||
CMutex(const CMutex&);
|
||||
CMutex& operator=(const CMutex&);
|
||||
|
||||
pthread_mutex_t m_mutex;
|
||||
};
|
||||
using CMutex = std::mutex;
|
||||
|
||||
/**
|
||||
* A mutex locker should always be used as an automatic variable. This
|
||||
* class makes sure that the mutex is unlocked when this class is destructed.
|
||||
* For example, this makes it easier to make code exception-safe.
|
||||
*/
|
||||
class CMutexLocker {
|
||||
public:
|
||||
CMutexLocker(CMutex& mutex, bool initiallyLocked = true)
|
||||
: m_mutex(mutex), m_locked(false) {
|
||||
if (initiallyLocked)
|
||||
lock();
|
||||
}
|
||||
|
||||
~CMutexLocker() {
|
||||
if (m_locked)
|
||||
unlock();
|
||||
}
|
||||
|
||||
void lock() {
|
||||
assert(!m_locked);
|
||||
m_mutex.lock();
|
||||
m_locked = true;
|
||||
}
|
||||
|
||||
void unlock() {
|
||||
assert(m_locked);
|
||||
m_locked = false;
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
// Undefined copy constructor and assignment operator
|
||||
CMutexLocker(const CMutexLocker&);
|
||||
CMutexLocker& operator=(const CMutexLocker&);
|
||||
|
||||
CMutex &m_mutex;
|
||||
bool m_locked;
|
||||
};
|
||||
using CMutexLocker = std::unique_lock<std::mutex>;
|
||||
|
||||
/**
|
||||
* A condition variable makes it possible for threads to wait until some
|
||||
* condition is reached at which point the thread can wake up again.
|
||||
*/
|
||||
class CConditionVariable {
|
||||
public:
|
||||
CConditionVariable() : m_cond() {
|
||||
int i = pthread_cond_init(&m_cond, nullptr);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't initialize condition variable: "
|
||||
+ CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
~CConditionVariable() {
|
||||
int i = pthread_cond_destroy(&m_cond);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't destroy condition variable: "
|
||||
+ CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void wait(CMutex& mutex) {
|
||||
int i = pthread_cond_wait(&m_cond, &mutex.m_mutex);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't wait on condition variable: "
|
||||
+ CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void signal() {
|
||||
int i = pthread_cond_signal(&m_cond);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't signal condition variable: "
|
||||
+ CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void broadcast() {
|
||||
int i = pthread_cond_broadcast(&m_cond);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't broadcast condition variable: "
|
||||
+ CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Undefined copy constructor and assignment operator
|
||||
CConditionVariable(const CConditionVariable&);
|
||||
CConditionVariable& operator=(const CConditionVariable&);
|
||||
|
||||
pthread_cond_t m_cond;
|
||||
};
|
||||
|
||||
class CThread {
|
||||
public:
|
||||
typedef void *threadRoutine(void *);
|
||||
static void startThread(threadRoutine *func, void *arg) {
|
||||
pthread_t thr;
|
||||
sigset_t old_sigmask, sigmask;
|
||||
|
||||
/* Block all signals. The thread will inherit our signal mask
|
||||
* and thus won't ever try to handle signals.
|
||||
*/
|
||||
int i = sigfillset(&sigmask);
|
||||
i |= pthread_sigmask(SIG_SETMASK, &sigmask, &old_sigmask);
|
||||
i |= pthread_create(&thr, nullptr, func, arg);
|
||||
i |= pthread_sigmask(SIG_SETMASK, &old_sigmask, nullptr);
|
||||
i |= pthread_detach(thr);
|
||||
if (i) {
|
||||
CUtils::PrintError("Can't start new thread: "
|
||||
+ CString(strerror(errno)));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Undefined constructor
|
||||
CThread();
|
||||
};
|
||||
using CConditionVariable = std::condition_variable_any;
|
||||
|
||||
/**
|
||||
* A job is a task which should run without blocking the main thread. You do
|
||||
@@ -292,11 +140,6 @@ private:
|
||||
void finishJob(CJob *) const;
|
||||
|
||||
void threadFunc();
|
||||
static void *threadPoolFunc(void *arg) {
|
||||
CThreadPool &pool = *reinterpret_cast<CThreadPool *>(arg);
|
||||
pool.threadFunc();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// mutex protecting all of these members
|
||||
CMutex m_mutex;
|
||||
|
||||
Reference in New Issue
Block a user