diff options
| author | 2019-05-15 16:22:24 +0100 | |
|---|---|---|
| committer | 2019-05-15 21:06:09 +0100 | |
| commit | 03d3563ef95efc6ab8076d66ebda48545c6089c4 (patch) | |
| tree | 0160e0a3b333a000c7c880d9373b46cfa3968e79 /include | |
| parent | Merge branch 'insp3' into master. (diff) | |
Replace socketengine_{pthread,win32} with C++11 threads.
Diffstat (limited to 'include')
| -rw-r--r-- | include/compat.h | 2 | ||||
| -rw-r--r-- | include/configreader.h | 31 | ||||
| -rw-r--r-- | include/inspircd.h | 7 | ||||
| -rw-r--r-- | include/thread.h | 67 | ||||
| -rw-r--r-- | include/threadengine.h | 173 | ||||
| -rw-r--r-- | include/threadengines/threadengine_pthread.h | 136 | ||||
| -rw-r--r-- | include/threadengines/threadengine_win32.h | 139 | ||||
| -rw-r--r-- | include/threadsocket.h | 83 |
8 files changed, 173 insertions, 465 deletions
diff --git a/include/compat.h b/include/compat.h index 903a45b23..22ac82fe5 100644 --- a/include/compat.h +++ b/include/compat.h @@ -38,11 +38,9 @@ */ #if defined _WIN32 # include "inspircd_win32wrapper.h" -# include "threadengines/threadengine_win32.h" #else # define ENTRYPOINT int main(int argc, char** argv) # define DllExport __attribute__ ((visibility ("default"))) # define CoreExport __attribute__ ((visibility ("default"))) # include <unistd.h> -# include "threadengines/threadengine_pthread.h" #endif diff --git a/include/configreader.h b/include/configreader.h index f9b9b582b..a7105ea7f 100644 --- a/include/configreader.h +++ b/include/configreader.h @@ -461,24 +461,35 @@ class CoreExport ServerConfig */ class CoreExport ConfigReaderThread : public Thread { - ServerConfig* Config; - volatile bool done; + private: + /** The new server configuration. */ + ServerConfig* Config = new ServerConfig(); + + /** Whether the config has been read yet. */ + std::atomic_bool done = { false }; + + protected: + /** @copydoc Thread::OnStart */ + void OnStart() override; + + /** @copydoc Thread::OnStop */ + void OnStop() override; + public: - const std::string TheUserUID; - ConfigReaderThread(const std::string &useruid) - : Config(new ServerConfig), done(false), TheUserUID(useruid) + const std::string UUID; + + ConfigReaderThread(const std::string& uuid) + : UUID(uuid) { } - virtual ~ConfigReaderThread() + ~ConfigReaderThread() { delete Config; } - void Run() override; - /** Run in the main thread to apply the configuration */ - void Finish(); - bool IsDone() { return done; } + /** Whether the configuration has been read yet. */ + bool IsDone() { return done.load(); } }; class CoreExport ConfigStatus diff --git a/include/inspircd.h b/include/inspircd.h index f01a57297..10c5dd958 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -85,7 +85,8 @@ CoreExport extern InspIRCd* ServerInstance; #include "message.h" #include "modules.h" #include "clientprotocol.h" -#include "threadengine.h" +#include "thread.h" +#include "threadsocket.h" #include "configreader.h" #include "inspstring.h" #include "protocol.h" @@ -238,10 +239,6 @@ class CoreExport InspIRCd */ CommandParser Parser; - /** Thread engine, Handles threading where required - */ - ThreadEngine Threads; - /** The thread/class used to read config files in REHASH and on startup */ ConfigReaderThread* ConfigThread; diff --git a/include/thread.h b/include/thread.h new file mode 100644 index 000000000..4145c9e88 --- /dev/null +++ b/include/thread.h @@ -0,0 +1,67 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2019 Peter Powell <petpow@saberuk.com> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +#include <thread> + +class CoreExport Thread +{ + private: + /** Whether this thread is in the process of stopping. */ + std::atomic_bool stopping = { false }; + + /** The underlying C++ thread. */ + std::thread* thread = nullptr; + + /** Internal callback which sets up the thread and calls OnStart. + * @param thread A thread which is starting up. + */ + static void StartInternal(Thread* thread); + + protected: + /** Callback which is executed on this thread after it has started. */ + virtual void OnStart() = 0; + + /** Callback which is executed on the calling thread before this thread is stopped. */ + virtual void OnStop() { }; + + /** Initialises an instance of the Thread class. */ + Thread() = default; + + public: + /** Destroys an instance of the Thread class. */ + virtual ~Thread() = default; + + /** Determines whether this thread is currently running. */ + bool IsRunning() const { return thread; } + + /** Determines whether this thread is currently stopping. */ + bool IsStopping() const { return stopping.load(); } + + /** Starts the execution of this thread. + * @return True if the thread was started, false if it was already running. + */ + bool Start(); + + /** Stops the execution of this thread. + * @return True if the thread was stopped, false if it was already stopped. + */ + bool Stop(); +}; diff --git a/include/threadengine.h b/include/threadengine.h deleted file mode 100644 index 0b816e27c..000000000 --- a/include/threadengine.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> - * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc> - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -#pragma once - -#include <vector> -#include <string> -#include <map> -#include "config.h" -#include "base.h" - -/** Derive from this class to implement your own threaded sections of - * code. Be sure to keep your code thread-safe and not prone to deadlocks - * and race conditions if you MUST use threading! - */ -class CoreExport Thread -{ - private: - /** Set to true when the thread is to exit - */ - bool ExitFlag; - - /** Opaque thread state managed by the ThreadEngine - */ - ThreadEngine::ThreadState state; - - /** ThreadEngine manages Thread::state - */ - friend class ThreadEngine; - - protected: - /** Get thread's current exit status. - * (are we being asked to exit?) - */ - bool GetExitFlag() - { - return ExitFlag; - } - public: - /** Set Creator to NULL at this point - */ - Thread() : ExitFlag(false) - { - } - - /** Override this method to put your actual - * threaded code here. - */ - virtual void Run() = 0; - - /** Signal the thread to exit gracefully. - */ - virtual void SetExitFlag(); - - /** Join the thread (calls SetExitFlag and waits for exit) - */ - void join(); -}; - - -class CoreExport QueuedThread : public Thread -{ - ThreadQueueData queue; - protected: - /** Waits for an enqueue operation to complete - * You MUST hold the queue lock when you call this. - * It will be unlocked while you wait, and will be relocked - * before the function returns - */ - void WaitForQueue() - { - queue.Wait(); - } - public: - /** Lock queue. - */ - void LockQueue() - { - queue.Lock(); - } - /** Unlock queue. - */ - void UnlockQueue() - { - queue.Unlock(); - } - /** Unlock queue and wake up worker - */ - void UnlockQueueWakeup() - { - queue.Wakeup(); - queue.Unlock(); - } - void SetExitFlag() override - { - queue.Lock(); - Thread::SetExitFlag(); - queue.Wakeup(); - queue.Unlock(); - } -}; - -class CoreExport SocketThread : public Thread -{ - ThreadQueueData queue; - ThreadSignalData signal; - protected: - /** Waits for an enqueue operation to complete - * You MUST hold the queue lock when you call this. - * It will be unlocked while you wait, and will be relocked - * before the function returns - */ - void WaitForQueue() - { - queue.Wait(); - } - public: - /** Notifies parent by making the SignalFD ready to read - * No requirements on locking - */ - void NotifyParent(); - SocketThread(); - virtual ~SocketThread(); - /** Lock queue. - */ - void LockQueue() - { - queue.Lock(); - } - /** Unlock queue. - */ - void UnlockQueue() - { - queue.Unlock(); - } - /** Unlock queue and send wakeup to worker - */ - void UnlockQueueWakeup() - { - queue.Wakeup(); - queue.Unlock(); - } - void SetExitFlag() override - { - queue.Lock(); - Thread::SetExitFlag(); - queue.Wakeup(); - queue.Unlock(); - } - - /** - * Called in the context of the parent thread after a notification - * has passed through the socket - */ - virtual void OnNotify() = 0; -}; diff --git a/include/threadengines/threadengine_pthread.h b/include/threadengines/threadengine_pthread.h deleted file mode 100644 index ca3354260..000000000 --- a/include/threadengines/threadengine_pthread.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> - * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc> - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -#pragma once - -#include <pthread.h> -#include "typedefs.h" - -/** The ThreadEngine class has the responsibility of initialising - * Thread derived classes. It does this by creating operating system - * level threads which are then associated with the class transparently. - * This allows Thread classes to be derived without needing to know how - * the OS implements threads. You should ensure that any sections of code - * that use threads are threadsafe and do not interact with any other - * parts of the code which are NOT known threadsafe! If you really MUST - * access non-threadsafe code from a Thread, use the Mutex class to wrap - * access to the code carefully. - */ -class CoreExport ThreadEngine -{ - public: - /** Per-thread state, present in each Thread object, managed by the ThreadEngine - */ - struct ThreadState - { - pthread_t pthread_id; - }; - - /** Create a new thread. This takes an already allocated - * Thread* pointer and initializes it to use this threading - * engine. On failure, this function may throw a CoreException. - * @param thread_to_init Pointer to a newly allocated Thread - * derived object. - */ - void Start(Thread* thread_to_init); - - /** Stop a thread gracefully. - * First, this function asks the thread to terminate by calling Thread::SetExitFlag(). - * Next, it waits until the thread terminates (on the operating system level). Finally, - * all OS-level resources associated with the thread are released. The Thread instance - * passed to the function is NOT freed. - * When this function returns, the thread is stopped and you can destroy it or restart it - * at a later point. - * Stopping a thread that is not running is a bug. - * @param thread The thread to stop. - */ - void Stop(Thread* thread); -}; - -/** The Mutex class represents a mutex, which can be used to keep threads - * properly synchronised. Use mutexes sparingly, as they are a good source - * of thread deadlocks etc, and should be avoided except where absolutely - * neccessary. Note that the internal behaviour of the mutex varies from OS - * to OS depending on the thread engine, for example in windows a Mutex - * in InspIRCd uses critical sections, as they are faster and simpler to - * manage. - */ -class CoreExport Mutex -{ - protected: - pthread_mutex_t putex; - public: - /** Constructor. - */ - Mutex() - { - pthread_mutex_init(&putex, NULL); - } - /** Enter/enable the mutex lock. - */ - void Lock() - { - pthread_mutex_lock(&putex); - } - /** Leave/disable the mutex lock. - */ - void Unlock() - { - pthread_mutex_unlock(&putex); - } - /** Destructor - */ - ~Mutex() - { - pthread_mutex_destroy(&putex); - } -}; - -class ThreadQueueData : public Mutex -{ - pthread_cond_t cond; - public: - ThreadQueueData() - { - pthread_cond_init(&cond, NULL); - } - - ~ThreadQueueData() - { - pthread_cond_destroy(&cond); - } - - void Wakeup() - { - pthread_cond_signal(&cond); - } - - void Wait() - { - pthread_cond_wait(&cond, &putex); - } -}; - -class ThreadSignalSocket; -class ThreadSignalData -{ - public: - ThreadSignalSocket* sock; -}; diff --git a/include/threadengines/threadengine_win32.h b/include/threadengines/threadengine_win32.h deleted file mode 100644 index aac7b8b97..000000000 --- a/include/threadengines/threadengine_win32.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * InspIRCd -- Internet Relay Chat Daemon - * - * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> - * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc> - * - * This file is part of InspIRCd. InspIRCd is free software: you can - * redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, version 2. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -#pragma once - -#include "config.h" -#include "base.h" - -class Thread; - -/** The ThreadEngine class has the responsibility of initialising - * Thread derived classes. It does this by creating operating system - * level threads which are then associated with the class transparently. - * This allows Thread classes to be derived without needing to know how - * the OS implements threads. You should ensure that any sections of code - * that use threads are threadsafe and do not interact with any other - * parts of the code which are NOT known threadsafe! If you really MUST - * access non-threadsafe code from a Thread, use the Mutex class to wrap - * access to the code carefully. - */ -class CoreExport ThreadEngine -{ - public: - /** Per-thread state, present in each Thread object, managed by the ThreadEngine - */ - struct ThreadState - { - HANDLE handle; - }; - - static DWORD WINAPI Entry(void* parameter); - - /** Create a new thread. This takes an already allocated - * Thread* pointer and initializes it to use this threading - * engine. On failure, this function may throw a CoreException. - * @param thread_to_init Pointer to a newly allocated Thread - * derived object. - */ - void Start(Thread* thread_to_init); - - /** Stop a thread gracefully. - * First, this function asks the thread to terminate by calling Thread::SetExitFlag(). - * Next, it waits until the thread terminates (on the operating system level). Finally, - * all OS-level resources associated with the thread are released. The Thread instance - * passed to the function is NOT freed. - * When this function returns, the thread is stopped and you can destroy it or restart it - * at a later point. - * Stopping a thread that is not running is a bug. - * @param thread The thread to stop. - */ - void Stop(Thread* thread); -}; - -/** The Mutex class represents a mutex, which can be used to keep threads - * properly synchronised. Use mutexes sparingly, as they are a good source - * of thread deadlocks etc, and should be avoided except where absolutely - * neccessary. Note that the internal behaviour of the mutex varies from OS - * to OS depending on the thread engine, for example in windows a Mutex - * in InspIRCd uses critical sections, as they are faster and simpler to - * manage. - */ -class CoreExport Mutex -{ - private: - CRITICAL_SECTION wutex; - public: - Mutex() - { - InitializeCriticalSection(&wutex); - } - void Lock() - { - EnterCriticalSection(&wutex); - } - void Unlock() - { - LeaveCriticalSection(&wutex); - } - ~Mutex() - { - DeleteCriticalSection(&wutex); - } -}; - -class ThreadQueueData : public Mutex -{ - HANDLE event; - public: - ThreadQueueData() - { - event = CreateEvent(NULL, false, false, NULL); - if (event == NULL) - throw CoreException("CreateEvent() failed in ThreadQueueData::ThreadQueueData()!"); - } - - ~ThreadQueueData() - { - CloseHandle(event); - } - - void Wakeup() - { - PulseEvent(event); - } - - void Wait() - { - Unlock(); - WaitForSingleObject(event, INFINITE); - Lock(); - } -}; - -class ThreadSignalData -{ - public: - int connFD; - ThreadSignalData() - { - connFD = -1; - } -}; diff --git a/include/threadsocket.h b/include/threadsocket.h new file mode 100644 index 000000000..5d0d035ec --- /dev/null +++ b/include/threadsocket.h @@ -0,0 +1,83 @@ +/* + * InspIRCd -- Internet Relay Chat Daemon + * + * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> + * Copyright (C) 2008 Craig Edwards <craigedwards@brainbox.cc> + * + * This file is part of InspIRCd. InspIRCd is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation, version 2. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#pragma once + +#include <condition_variable> +#include <mutex> + +class ThreadSignalSocket; + +class CoreExport SocketThread : public Thread +{ + private: + std::mutex mutex; + std::condition_variable_any condvar; + ThreadSignalSocket* socket; + + protected: + /** Waits for an enqueue operation to complete + * You MUST hold the queue lock when you call this. + * It will be unlocked while you wait, and will be relocked + * before the function returns + */ + void WaitForQueue() + { + condvar.wait(mutex); + } + public: + /** Notifies parent by making the SignalFD ready to read + * No requirements on locking + */ + void NotifyParent(); + SocketThread(); + virtual ~SocketThread(); + /** Lock queue. + */ + void LockQueue() + { + mutex.lock(); + } + /** Unlock queue. + */ + void UnlockQueue() + { + mutex.unlock(); + } + /** Unlock queue and send wakeup to worker + */ + void UnlockQueueWakeup() + { + condvar.notify_all(); + mutex.unlock(); + } + void OnStop() override + { + mutex.lock(); + condvar.notify_all(); + mutex.unlock(); + } + + /** + * Called in the context of the parent thread after a notification + * has passed through the socket + */ + virtual void OnNotify() = 0; +}; |
