diff options
-rw-r--r-- | CMakeLists.txt | 7 | ||||
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | include/services.h | 1 | ||||
-rw-r--r-- | include/threadengine.h | 116 | ||||
-rw-r--r-- | src/CMakeLists.txt | 10 | ||||
-rw-r--r-- | src/Makefile | 11 | ||||
-rw-r--r-- | src/threadengine.cpp | 38 | ||||
-rw-r--r-- | src/threadengine_pthread.cpp | 108 | ||||
-rw-r--r-- | src/threadengine_win32.cpp | 104 |
10 files changed, 395 insertions, 4 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8493c5835..4ee4c13d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -286,6 +286,13 @@ if(NOT MSVC) if(HAVE_NSL_LIB) set(LDFLAGS "${LDFLAGS} -lnsl") endif(HAVE_NSL_LIB) + # Check if pthread_create is within the pthread library (if the library exists), and add it to the linker flags if needed + check_library_exists(pthread pthread_create "" HAVE_PTHREAD) + if(HAVE_PTHREAD) + set(LDFLAGS "${LDFLAGS} -pthread") + else(HAVE_PTHREAD) + message(FATAL_ERROR "The pthread library is required to build Anope") + endif(HAVE_PTHREAD) endif(NOT WIN32) endif(NOT MSVC) @@ -3398,6 +3398,8 @@ fi +ANOPELIBS="$ANOPELIBS -pthread" + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' diff --git a/configure.in b/configure.in index 4fb762d66..1bda1b300 100644 --- a/configure.in +++ b/configure.in @@ -95,6 +95,8 @@ int main() AC_SUBST(ANOPELIBS) AC_SUBST(LDFLAGS) +ANOPELIBS="$ANOPELIBS -pthread" + AC_CHECK_HEADER(sys/types.h,AC_DEFINE(HAS_SYS_TYPES_H,1,"Has sys/types.h")) dnl module checking based on Unreal's module checking code AC_DEFUN(AC_ENABLE_DYN, diff --git a/include/services.h b/include/services.h index 4dd35a751..43e91a21b 100644 --- a/include/services.h +++ b/include/services.h @@ -358,6 +358,7 @@ typedef struct exception_ Exception; typedef struct session_ Session; #include "extensible.h" +#include "threadengine.h" #include "bots.h" #include "opertype.h" #include "modes.h" diff --git a/include/threadengine.h b/include/threadengine.h new file mode 100644 index 000000000..e2125c6bd --- /dev/null +++ b/include/threadengine.h @@ -0,0 +1,116 @@ +#ifdef _WIN32 +typedef HANDLE ThreadHandle; +typedef CRITICAL_SECTION MutexHandle; +typedef HANDLE CondHandle; +#else +# include <pthread.h> +typedef pthread_t ThreadHandle; +typedef pthread_mutex_t MutexHandle; +typedef pthread_cond_t CondHandle; +#endif + +class ThreadEngine; +class Thread; + +extern CoreExport ThreadEngine threadEngine; + +class ThreadEngine +{ + public: + /** Threadengines constructor + */ + ThreadEngine(); + + /** Threadengines destructor + */ + ~ThreadEngine(); + + /** Start a new thread + * @param thread A pointer to a newley allocated thread + */ + void Start(Thread *thread); +}; + +class Thread : public Extensible +{ + private: + /* Set to true to tell the thread to finish and we are waiting for it */ + bool Exit; + + /** Join to the thread, sets the exit state to true + */ + void Join(); + public: + /* Handle for this thread */ + ThreadHandle Handle; + + /** Threads constructor + */ + Thread(); + + /** Threads destructor + */ + virtual ~Thread(); + + /** Sets the exit state as true informing the thread we want it to shut down + */ + void SetExitState(); + + /** Returns the exit state of the thread + * @return true if we want to exit + */ + bool GetExitState() const; + + /** Called to run the thread, should be overloaded + */ + virtual void Run(); +}; + +class Mutex +{ + protected: + /* A mutex, used to keep threads in sync */ + MutexHandle mutex; + + public: + /** Constructor + */ + Mutex(); + + /** Destructor + */ + ~Mutex(); + + /** Attempt to lock the mutex, will hang until a lock can be achieved + */ + void Lock(); + + /** Unlock the mutex, it must be locked first + */ + void Unlock(); +}; + +class Condition : public Mutex +{ + private: + /* A condition */ + CondHandle cond; + + public: + /** Constructor + */ + Condition(); + + /** Destructor + */ + ~Condition(); + + /** Called to wakeup the waiter + */ + void Wakeup(); + + /** Called to wait for a Wakeup() call + */ + void Wait(); +}; + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4bad367b4..8cf232a77 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,14 +2,24 @@ file(GLOB SRC_SRCS_C RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.c") file(GLOB SRC_SRCS_CPP RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp") set(SRC_SRCS ${SRC_SRCS_C} ${SRC_SRCS_CPP}) + # Don't include win32_memory.cpp, it's only required by Visual Studio to override it's override of the new/delete operators remove_item_from_list(SRC_SRCS win32_memory.cpp) + # If not using Windows, don't include windows.cpp, as it's Windows-specific if(NOT WIN32) remove_item_from_list(SRC_SRCS windows.cpp) endif(NOT WIN32) sort_list(SRC_SRCS) +# If using Windows, remove the pthread threading engine from the list +if(WIN32) + remove_item_from_list(SRC_SRCS threadengine_pthread.cpp) +# If not using Windows, remove the Windows threading engine from the list +else(WIN32) + remove_item_from_list(SRC_SRCS threadengine_win32.cpp) +endif(WIN32) + # Set all the files to use C++ as well as set their compile flags (use the module-specific compile flags, though) set_source_files_properties(${SRC_SRCS} PROPERTIES LANGUAGE CXX COMPILE_FLAGS "${CXXFLAGS}") diff --git a/src/Makefile b/src/Makefile index be4004ec9..3e66abc3d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,13 +2,14 @@ OBJS = actions.o base64.o bots.o botserv.o channels.o chanserv.o command.o comm config.o configreader.o encrypt.o hashcomp.o hostserv.o init.o ircd.o language.o log.o mail.o main.o \ memory.o memoserv.o messages.o misc.o modes.o modules.o module.o modulemanager.o nickalias.o \ nickcore.o nickserv.o operserv.o process.o protocol.o regchannel.o send.o servers.o sessions.o slist.o \ - sockets.o timers.o opertype.o users.o wildcard.o + sockets.o threadengine.o threadengine_pthread.o timers.o opertype.o users.o wildcard.o INCLUDES = ../include/commands.h ../include/defs.h ../include/language.h \ ../include/pseudo.h ../include/sysconf.h ../include/config.h \ ../include/messages.h ../include/services.h \ ../include/timers.h ../include/extern.h \ - ../include/modules.h ../include/slist.h ../include/hashcomp.h + ../include/modules.h ../include/slist.h ../include/hashcomp.h \ + ../include/threadengine.h MAKEARGS = 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'ANOPELIBS=${ANOPELIBS}' \ 'LDFLAGS=${LDFLAGS}' 'INSTDIR=${INSTDIR}' 'INSTALL=${INSTALL}' \ @@ -72,8 +73,10 @@ send.o: send.c $(INCLUDES) servers.o: servers.cpp $(INCLUDES) sessions.o: sessions.c $(INCLUDES) slist.o: slist.c $(INCLUDES) -sockets.o: sockets.cpp $(INCLUDES) -timers.o: timers.cpp $(INCLUDES) +sockets.o: sockets.cpp $(INCLUDES) +threadengine.o: threadengine.cpp $(INCLUDES) +threadengine_pthread.o: threadengine_pthread.cpp $(INCLUDES) +timers.o: timers.cpp $(INCLUDES) users.o: users.c $(INCLUDES) wildcard.o: wildcard.cpp $(INCLUDES) diff --git a/src/threadengine.cpp b/src/threadengine.cpp new file mode 100644 index 000000000..f7e924fb6 --- /dev/null +++ b/src/threadengine.cpp @@ -0,0 +1,38 @@ +#include "services.h" + +ThreadEngine threadEngine; + +/** Threads constructor + */ +Thread::Thread() : Exit(false) +{ +} + +/** Threads destructor + */ +Thread::~Thread() +{ + Join(); +} + +/** Sets the exit state as true informing the thread we want it to shut down + */ +void Thread::SetExitState() +{ + Exit = true; +} + +/** Returns the exit state of the thread + * @return true if we want to exit + */ +bool Thread::GetExitState() const +{ + return Exit; +} + +/** Called to run the thread, should be overloaded + */ +void Thread::Run() +{ +} + diff --git a/src/threadengine_pthread.cpp b/src/threadengine_pthread.cpp new file mode 100644 index 000000000..58b3a11ac --- /dev/null +++ b/src/threadengine_pthread.cpp @@ -0,0 +1,108 @@ +#include "services.h" + +/** Join to the thread, sets the exit state to true + */ +void Thread::Join() +{ + SetExitState(); + pthread_join(Handle, NULL); +} + +/* Threadengine attributes used by this thread engine */ +static pthread_attr_t threadengine_attr; + +/** Entry point used for the threads + * @param parameter A Thread* cast to a void* + */ +static void *entry_point(void *parameter) +{ + Thread *thread = static_cast<Thread *>(parameter); + thread->Run(); + return parameter; +} + +/** Threadengines constructor + */ +ThreadEngine::ThreadEngine() +{ + if (pthread_attr_init(&threadengine_attr)) + { + throw CoreException("ThreadEngine: Error calling pthread_attr_init"); + } +} + +/** Threadengines destructor + */ +ThreadEngine::~ThreadEngine() +{ + pthread_attr_destroy(&threadengine_attr); +} + +/** Start a new thread + * @param thread A pointer to a newley allocated thread + */ +void ThreadEngine::Start(Thread *thread) +{ + if (pthread_create(&thread->Handle, &threadengine_attr, entry_point, thread)) + { + delete thread; + throw CoreException("Unable to create thread"); + } +} + +/** Constructor + */ +Mutex::Mutex() +{ + pthread_mutex_init(&mutex, NULL); +} + +/** Destructor + */ +Mutex::~Mutex() +{ + pthread_mutex_destroy(&mutex); +} + +/** Attempt to lock the mutex, will hang until a lock can be achieved + */ +void Mutex::Lock() +{ + pthread_mutex_lock(&mutex); +} + +/** Unlock the mutex, it must be locked first + */ +void Mutex::Unlock() +{ + pthread_mutex_unlock(&mutex); +} + +/** Constructor + */ +Condition::Condition() : Mutex() +{ + pthread_cond_init(&cond, NULL); +} + +/** Destructor + */ +Condition::~Condition() +{ + pthread_cond_destroy(&cond); +} + +/** Called to wakeup the waiter + */ +void Condition::Wakeup() +{ + pthread_cond_signal(&cond); +} + +/** Called to wait for a Wakeup() call + */ +void Condition::Wait() +{ + pthread_cond_wait(&cond, &mutex); +} + diff --git a/src/threadengine_win32.cpp b/src/threadengine_win32.cpp new file mode 100644 index 000000000..602d8b809 --- /dev/null +++ b/src/threadengine_win32.cpp @@ -0,0 +1,104 @@ +#include "services.h" + +/** Join to the thread, sets the exit state to true + */ +void Thread::Join() +{ + SetExitState(); + WaitForSingleObject(Handle, INFINITE); +} + +/** Entry point for the thread + * @param paramter A Thread* cast to a void* + */ +static DWORD WINAPI entry_point(void *parameter) +{ + Thread *thread = static_cast<Thread *>(parameter); + thread->Run(); + return 0; +} + +/** Threadengines constructor + */ +ThreadEngine::ThreadEngine() +{ +} + +/** Threadengines destructor + */ +ThreadEngine::~ThreadEngine() +{ +} + +/** Start a new thread + * @param thread A pointer to a newley allocated thread + */ +void ThreadEngine::Start(Thread *thread) +{ + thread->Handle = CreateThread(NULL, 0, entry_point, thread, 0, NULL); + + if (!thread->Handle) + { + delete thread; + throw CoreException("Unable to create thread"); + } +} + +/** Constructor + */ +Mutex::Mutex() +{ + InitializeCriticalSection(&mutex); +} + +/** Destructor + */ +Mutex::~Mutex() +{ + DeleteCriticalSection(&mutex); +} + +/** Attempt to lock the mutex, will hang until a lock can be achieved + */ +void Mutex::Lock() +{ + EnterCriticalSection(&mutex); +} + +/** Unlock the mutex, it must be locked first + */ +void Mutex::Unlock() +{ + LeaveCriticalSection(&mutex); +} + +/** Constructor + */ +Condition::Condition() : Mutex() +{ + cond = CreateEvent(NULL, false, false, NULL); +} + +/** Destructor + */ +Condition::~Condition() +{ + CloseHandle(cond); +} + +/** Called to wakeup the waiter + */ +void Condition::Wakeup() +{ + PulseEvent(cond); +} + +/** Called to wait for a Wakeup() call + */ +void Condition::Wait() +{ + LeaveCriticalSection(&mutex); + WaitForSingleObject(cond, INFINITE); + EnterCriticalSection(&mutex); +} + |