From: hama Date: Sat, 14 Mar 2015 22:28:12 +0000 (+0100) Subject: ReMutex, ReThread without syntax errors X-Git-Url: https://gitweb.hamatoma.de/?a=commitdiff_plain;h=dceb22816323aa4c69743a94419d28215844ff2c;p=crepublib ReMutex, ReThread without syntax errors --- diff --git a/base/ReAppenders.hpp b/base/ReAppenders.hpp index 7c65df2..783ce6c 100644 --- a/base/ReAppenders.hpp +++ b/base/ReAppenders.hpp @@ -25,8 +25,8 @@ public: ReMemoryAppender(int maxLines); ~ReMemoryAppender(); public: - virtual void say(ReLogger* logger, const char* message); ReByteBuffer& join(ReByteBuffer& buffer, bool append = false); + virtual void say(ReLogger* logger, const char* message); protected: int m_maxLines; }; @@ -35,8 +35,9 @@ protected: * This appender writes the messages to another logger. * * This is useful in multithreaded applications: There is one "normal logger" - * in the main thread and each other thread have its own logger with a - * ReSlaveAppender which write to the main logger. + * called "master logger" in the main thread and each other thread has its + * own logger with a ReSlaveAppender which write to the + * master logger. * * Reason: Because of the architecture of the argument handling * (say().arg().end() it is not possible to protect the argument @@ -46,9 +47,14 @@ class ReSlaveAppender : public ReAppender { public: ReSlaveAppender(ReLogger* masterLogger, char charPrefix = '\0'); virtual ~ReSlaveAppender(); -public: public: virtual void say(ReLogger* logger, const char* message); + /** Sets the master logger. + * @param logger the master logger + */ + void setMasterLogger(ReLogger* logger){ + m_masterLogger = logger; + } private: ReLogger* m_masterLogger; char m_charPrefix; diff --git a/base/ReLogger.cpp b/base/ReLogger.cpp index 99a1503..07f37fc 100644 --- a/base/ReLogger.cpp +++ b/base/ReLogger.cpp @@ -9,6 +9,9 @@ #include "base/rebase.hpp" +enum RELOC_SEQARRAY { + LC_LOGGER_1 = LC_LOGGER + 1, // 50701 +}; #ifdef __linux__ extern size_t strftime (char* s, size_t maxsize, const char* format, const struct tm* tp); #endif @@ -263,9 +266,8 @@ ReLogger::ReLogger(bool isGlobal) : m_stdConsoleAppender(NULL), m_stdFileAppender(NULL), m_locationOfOpenSayF(0), - m_mutex(), + m_mutex(LC_LOGGER_1, 10), m_charPrefix('\0') { - sem_init(&m_mutex, 0, 1); if (isGlobal) { delete m_globalLogger; m_globalLogger = this; @@ -285,7 +287,6 @@ ReLogger::~ReLogger() { m_appenderListSize = 0; if (m_globalLogger == this) m_globalLogger = NULL; - sem_destroy(&m_mutex); } /** @brief Issues a log message. * @@ -300,7 +301,7 @@ ReLogger::~ReLogger() { */ bool ReLogger::say(ReClassCategoryGranularity mode, ReLogLocation location, const char* message) { - sem_wait(&m_mutex); + m_mutex.wait(); m_mode = mode; m_location = location; m_standardPrefix[0] = '\0'; @@ -310,7 +311,7 @@ bool ReLogger::say(ReClassCategoryGranularity mode, ReLogLocation location, if (app->accept(mode)) app->say(this, message); } - sem_post(&m_mutex); + m_mutex.release(); return true; } /** @brief Issues a log message. @@ -326,7 +327,7 @@ bool ReLogger::say(ReClassCategoryGranularity mode, ReLogLocation location, */ bool ReLogger::say(char prefix, ReClassCategoryGranularity mode, ReLogLocation location, const char* message) { - sem_wait(&m_mutex); + m_mutex.wait(); char safePrefix = m_charPrefix; m_charPrefix = prefix; m_mode = mode; @@ -339,7 +340,7 @@ bool ReLogger::say(char prefix, ReClassCategoryGranularity mode, app->say(this, message); } m_charPrefix = safePrefix; - sem_post(&m_mutex); + m_mutex.release(); return true; } @@ -358,7 +359,7 @@ bool ReLogger::say(char prefix, ReClassCategoryGranularity mode, */ ReVarArgs& ReLogger::sayF(ReClassCategoryGranularity mode, ReLogLocation location, const char* format) { - sem_wait(&m_mutex); + m_mutex.wait(); if (m_locationOfOpenSayF != 0) { char message[128]; _snprintf(message, sizeof message, @@ -370,7 +371,7 @@ ReVarArgs& ReLogger::sayF(ReClassCategoryGranularity mode, m_location = location; m_standardPrefix[0] = '\0'; reset(format); - sem_post(&m_mutex); + m_mutex.release(); return *this; } /** Adds an appender to the appender list. diff --git a/base/ReLogger.hpp b/base/ReLogger.hpp index f177aa4..d7e112a 100644 --- a/base/ReLogger.hpp +++ b/base/ReLogger.hpp @@ -180,7 +180,7 @@ protected: ReAppender* m_stdConsoleAppender; ReFileAppender* m_stdFileAppender; int m_locationOfOpenSayF; - ReMutex_t m_mutex; + ReMutex m_mutex; char m_charPrefix; private: diff --git a/base/ReMutex.cpp b/base/ReMutex.cpp new file mode 100644 index 0000000..1d16294 --- /dev/null +++ b/base/ReMutex.cpp @@ -0,0 +1,53 @@ +/* + * ReMutex.cpp + * + * License: Public domain + * Do what you want. + * No warranties and disclaimer of any damages. + * The latest sources: https://github.com/republib + */ + +#include "base/rebase.hpp" + +/** + * Constructor. + * + * @param maxWaitSec maximal timeout. If reached an error occurres + */ +ReMutex::ReMutex(int location, int maxWaitSec) : +#if defined __linux__ + m_mutex(), +#elif defined __WIN32__ + m_mutex(0), +#endif + m_maxWaitSec(maxWaitSec){ +#if defined __linux__ + sem_init(&m_mutex, 0, 0); +#elif defined __WIN32__ + m_mutex = CreateMutex(NULL, FALSE, NULL); +#endif +} + +/** + * Destructor. + */ +ReMutex::~ReMutex() { +#if defined __linux__ + sem_destroy(&m_mutex); +#elif defined __WIN32__ + CloseMutex(m_mutex); +#endif +} + +bool ReMutex::timedWait(int sec){ + bool rc = true; +#if defined __linux__ + struct timespec time; + time.tv_sec = sec; + time.tv_nsec = 0; + rc = sem_timedwait(&m_mutex, &time) == 0; +#elif defined __WIN32__ + +#endif + return rc; +} diff --git a/base/ReMutex.hpp b/base/ReMutex.hpp new file mode 100644 index 0000000..f851887 --- /dev/null +++ b/base/ReMutex.hpp @@ -0,0 +1,42 @@ +/* + * ReMutex.hpp + * + * License: Public domain + * Do what you want. + * No warranties and disclaimer of any damages. + * The latest sources: https://github.com/republib + */ + +#ifndef BASE_REMUTEX_HPP_ +#define BASE_REMUTEX_HPP_ + +class ReMutex { +public: + ReMutex(int location, int maxWaitSec = -1); + virtual ~ReMutex(); +public: + inline void release(){ +#if defined __linux__ + sem_post(&m_mutex); +#elif defined __WIN32__ +#error "mutex in ReMutex missed" +#endif + } + bool timedWait(int sec = -1); + inline void wait(){ +#if defined __linux__ + sem_wait(&m_mutex); +#elif defined __WIN32__ +#error "mutex in ReMutex missed" +#endif + } +private: +#if defined __linux__ + sem_t m_mutex; +#elif defined __WIN32__ + HANDLE m_mutex; +#endif + int m_maxWaitSec; +}; + +#endif /* BASE_REMUTEX_HPP_ */ diff --git a/base/ReThread.cpp b/base/ReThread.cpp index aba5f12..bf8facf 100644 --- a/base/ReThread.cpp +++ b/base/ReThread.cpp @@ -10,16 +10,34 @@ #include "base/rebase.hpp" enum RELOC_HASHLIST { - LC_SET_MASTER_LOGGER_1 = LC_THREAD + 1, // 50601 + LC_PREPARE_TO_RUN_1 = LC_THREAD + 1, // 50601 LC_START_THREAD_1, // 50602 + LC_NE_1, // 50603 }; + /** * Constructor. + * + * @param autodelete true: the ReThreadStarter + * deletes the instance when it is stopped */ -ReThread::ReThread() : - m_logger(false), - m_appender(NULL){ +ReThread::ReThread(bool autoDelete) : + m_threadId(-1), + m_threadLogger(false), + m_appender(NULL), + m_starter(NULL), +#if defined __linux__ + m_threadInfo(), +#elif defined __WIN32__ + m_threadInfo(UNDEF_HANDLE), +#endif + m_shouldStop(false), + m_isStopped(false), + m_autoDelete(autoDelete){ +#if defined __linux__ + memset(&m_threadInfo, 0, sizeof m_threadInfo); +#endif } /** * Destructor. @@ -27,21 +45,41 @@ ReThread::ReThread() : ReThread::~ReThread(){ } -void ReThread::setMasterLogger(ReLogger* masterLogger){ - if (m_appender == NULL){ - m_appender = new ReSlaveAppender(masterLogger); +/** + * Prepares the thread for running. + * + * Should only called by ReThredStarter() + * + * @param id the thread id + * @param masterLogger the logger for error handling + * @param starter the instance which has started the thread + */ +bool ReThread::prepareToRun(int id, ReLogger* masterLogger, + ReThreadStarter* starter){ + bool rc = false; + if (m_starter != NULL){ + globalLogger()->say(LOG_ERROR | CAT_LIB, LC_PREPARE_TO_RUN_1, + i18n("setMasterLogger() is called multiple times")); } else { - globalLogger()->say(LOG_ERROR | CAT_LIB, LC_NEXT_1, - i18n("setMasterLogger() is called multiple times")); + m_threadId = id; + m_appender->setMasterLogger(masterLogger); + m_starter = starter; + rc = true; } } /** * Constructor. + * + * @param maxThreads the maximal number of threads + * @param logger the (master) logger for error handling */ -ReThreadStarter::ReThreadStarter(ReLogger* logger) : - m_id(0), - m_logger(logger){ +ReThreadStarter::ReThreadStarter(int maxThreads, ReLogger* logger) : + m_nextId(0), + m_logger(logger), + m_maxThreads(maxThreads){ + m_threads = new ReThread*[maxThreads]; + memset(m_threads, 0, maxThreads * sizeof *m_threads); } /** * Destructor. @@ -74,24 +112,23 @@ DWORD WINAPI starterFunction(_In_ LPVOID pParameter){ * * @param thread the */ -void ReThreadStarter::startThread(ReThread& thread){ - thread.setId(++m_nextId); - thread.setMasterLogger(m_logger); - bool error; +bool ReThreadStarter::startThread(ReThread& thread){ + bool ok = false; + if (thread.prepareToRun(++m_nextId, m_logger, this)){ #if defined __linux__ - pthread_t sniffer_thread; - error = (pthread_create(&sniffer_thread, NULL, starterFunction, - (void*) thread) < 0; - -#else defined __WIN32__ - HANDLE threadHandle; - error = (threadHandle = CreateThread(NULL, 0, starterFunction, - &thread, 0)) == NULL; + pthread_t sniffer_thread; + ok = pthread_create(&sniffer_thread, NULL, starterFunction, + reinterpret_cast(&thread)) >= 0; +#elif defined __WIN32__ + HANDLE threadHandle; + ok = (threadHandle = CreateThread(NULL, 0, starterFunction, + &thread, 0)) != NULL; #endif - if (error) - m_logger->sayF(LOG_ERROR | CAT_PROCESS, - LC_START_THREAD_1, - i18n("cannot create a thread: $1")).arg( - getLastOSError()).end(); - + if (! ok) + m_logger->sayF(LOG_ERROR | CAT_PROCESS, + LC_START_THREAD_1, + i18n("cannot create a thread: $1")).arg( + getLastOSError()).end(); + } + return ok; } diff --git a/base/ReThread.hpp b/base/ReThread.hpp index f6b088d..d6aafbf 100644 --- a/base/ReThread.hpp +++ b/base/ReThread.hpp @@ -10,6 +10,8 @@ #ifndef BASE_RETHREAD_HPP_ #define BASE_RETHREAD_HPP_ +class ReThreadStarter; +class ReSlaveAppender; /** * Abstract base class for threads * @@ -17,18 +19,39 @@ */ class ReThread { public: - ReThread(); + ReThread(bool autoDelete); virtual ~ReThread(); private: friend class ReThreadStarter; - void setId(int id); - void setMasterLogger(ReLogger* masterLogger); + bool prepareToRun(int id, ReLogger* masterLogger, + ReThreadStarter* starter); public: virtual void run() = 0; + /** Returns if the thread is stopped. + * @return truethe thread is stopped + */ + inline bool isStopped() const{ + return m_isStopped; + } + /** Sets the wish for stopping the thread. + * @param value true: the thread should stop as soon as possible + */ + inline bool setShouldStop(bool value){ + m_shouldStop = value; + } protected: - int m_id; - ReLogger m_logger; + int m_threadId; + ReLogger m_threadLogger; ReSlaveAppender* m_appender; + ReThreadStarter* m_starter; +#if defined __linux__ + pthread_t m_threadInfo; +#elif defined __WIN32__ + HANDLE m_threadInfo; +#endif + bool m_shouldStop; + bool m_isStopped; + bool m_autoDelete; }; /** @@ -36,12 +59,16 @@ protected: */ class ReThreadStarter { public: - ReThreadStarter(ReLogger* logger); + ReThreadStarter(int maxThreads, ReLogger* logger); virtual ~ReThreadStarter(); public: - void startThread(ReThread& thread); + bool startThread(ReThread& thread); +private: + bool insertThread(ReThread* thread); private: int m_nextId; ReLogger* m_logger; + int m_maxThreads; + ReThread** m_threads; }; #endif /* BASE_RETHREAD_HPP_ */ diff --git a/base/baselocations.hpp b/base/baselocations.hpp index 7ef4b40..7aa301a 100644 --- a/base/baselocations.hpp +++ b/base/baselocations.hpp @@ -20,6 +20,7 @@ enum RELOC_LIB { LC_TRAVERSER = 50400, LC_TCP = 50500, LC_THREAD = 50600, + LC_LOGGER = 50700, }; enum RELOC_UDPCONNECTION { LC_UDPCONNECTION_CONSTRUCT = 50101, diff --git a/base/rebase.hpp b/base/rebase.hpp index 93b40f0..1183324 100644 --- a/base/rebase.hpp +++ b/base/rebase.hpp @@ -40,8 +40,6 @@ typedef u_int64_t uint64_t; typedef u_int8_t uint8_t; typedef __off_t ReFileSize_t; typedef timespec ReFileTime_t; -typedef sem_t ReMutex_t; -#define reInitMutex(mutex) # define _strdup strdup # define _unlink unlink # define _strnicmp(s1, s2, n) strncasecmp(s1, s2, n) @@ -63,8 +61,6 @@ inline int getLastOSError() { # define lstat stat # define OS_SEPARATOR_CHAR '\\' # define OS_SEPARATOR "\\" -typedef HANDLE ReMutex_t; -#define initMutex(mutex) mutex = CreateMutex(NULL, FALSE, NULL) typedef _int64 int64_t; typedef unsigned long long uint64_t; typedef unsigned char uint8_t; @@ -82,21 +78,23 @@ inline int getLastOSError() { #endif #define RE_TESTUNIT +#include "base/ReMutex.hpp" #include "base/ReByteBuffer.hpp" #include "base/ReVarArgs.hpp" #include "base/ReLogger.hpp" +#include "base/ReThread.hpp" #include "base/ReTestUnit.hpp" #include "base/ReCString.hpp" #include "base/ReException.hpp" #include "base/ReStringUtils.hpp" #include "base/ReDirectory.hpp" #include "base/ReSeqArray.hpp" +#include "base/ReAppenders.hpp" #include "base/ReStringList.hpp" #include "base/ReHashList.hpp" #include "base/ReConfigFile.hpp" #include "base/ReI18N.hpp" #include "base/ReProgramArgs.hpp" -#include "base/ReAppenders.hpp" typedef unsigned char byte_t; typedef int ReErrNo_t; diff --git a/base/remath.hpp b/base/remath.hpp deleted file mode 100644 index 5ea7c50..0000000 --- a/base/remath.hpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * remath.hpp - * - * License: Public domain - * Do what you want. - * No warranties and disclaimer of any damages. - * The latest sources: https://github.com/republib - */ - -#ifndef REMATH_HPP_ -#define REMATH_HPP_ - -#ifndef REBASE_HPP_ -#include "base/rebase.hpp" -#endif -#include "math/ReObfuscator.hpp" -#include "math/ReRandomizer.hpp" - -#endif /* REMATH_HPP_ */ diff --git a/base/renet.hpp b/base/renet.hpp deleted file mode 100644 index a1e33cf..0000000 --- a/base/renet.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * renet.hpp - * - * License: Public domain - * Do what you want. - * No warranties and disclaimer of any damages. - * The latest sources: https://github.com/republib - */ - -#ifndef RENET_HPP_ -#define RENET_HPP_ - -#ifndef REBASE_HPP_ -#include "../base/rebase.hpp" -#endif -#include "net/ReUdpConnection.hpp" -#endif /* RENET_HPP_ */ diff --git a/math/ReObfuscator.cpp b/math/ReObfuscator.cpp index d4b961d..846e228 100644 --- a/math/ReObfuscator.cpp +++ b/math/ReObfuscator.cpp @@ -8,7 +8,7 @@ */ #include "base/rebase.hpp" -#include "base/remath.hpp" +#include "math/remath.hpp" /** @brief Constructor. * diff --git a/net/ReTCP.cpp b/net/ReTCP.cpp index 7a77901..8191fb6 100644 --- a/net/ReTCP.cpp +++ b/net/ReTCP.cpp @@ -317,12 +317,12 @@ void ReTCPConnection::send(const char* command, const char* data, int length) { * @param id an identifier for logging * @param logger the logger for error handling */ -ReTCPServerConnection::ReTCPServerConnection(int id, ReLogger* masterLogger, - ReTCPServer* server) : +ReTCPServerConnection::ReTCPServerConnection(int id, ReTCPServer* server) : ReTCPConnection(id, new ReLogger(false)), + ReThread(true), m_server(server), - m_slaveAppender(masterLogger, '0' + id % ('z' - '0' + 1)) { - m_logger->addAppender(&m_slaveAppender); + m_slaveAppender(NULL, '0' + id % ('z' - '0' + 1)) { + ReTCPConnection::m_logger->addAppender(&m_slaveAppender); } /** @@ -334,7 +334,7 @@ ReTCPServerConnection::~ReTCPServerConnection() { /** * Serves the commands of a single connection (in a single thread). */ -void ReTCPServerConnection::handleConnection() { +void ReTCPServerConnection::run() { ReByteBuffer command; ReNetCommandHandler::ProcessingState rc = ReNetCommandHandler::PS_UNDEF; do { @@ -393,8 +393,7 @@ ReTCPServerConnection* ReTCPServer::createConnection(int id, int handleSocket, ReTCPServerConnection* rc = NULL; for (int ii = 0; rc == NULL && ii < m_maxConnections; ii++) { if (m_connections[ii] == NULL) - m_connections[ii] = rc = new ReTCPServerConnection(id, m_logger, - this); + m_connections[ii] = rc = new ReTCPServerConnection(id, this); else if (m_connections[ii]->id() < 0) { rc = m_connections[ii]; rc->setId(id); @@ -417,19 +416,6 @@ ReTCPServerConnection* ReTCPServer::createConnection(int id, int handleSocket, return rc; } -/** - * The start routine of pthread_start - * - * This will handle the connection for each client (in an own thread). - * - * @param pConnection a void* pointer to the ReTCPServerConnection instance - * */ -static void* serverSlaveThread(void *pConnection) { - ReTCPServerConnection* connection = - reinterpret_cast(pConnection); - connection->handleConnection(); -} - /** * Accepts connections and create a thread which will handle this connection. */ @@ -437,6 +423,7 @@ bool ReTCPServer::listenForAll() { bool rc = false; struct addrinfo hints; struct addrinfo* addrInfo; + ReThreadStarter threadStarter(m_maxConnections + 1, m_logger); // first, load up address structs with getaddrinfo(): memset(&hints, 0, sizeof hints); @@ -496,11 +483,10 @@ bool ReTCPServer::listenForAll() { reCloseSocket(clientSocket); } else { pthread_t sniffer_thread; - ReTCPConnection* connection = createConnection(nextId++, + ReTCPServerConnection* connection = createConnection(nextId++, clientSocket, addrClient); - if (pthread_create(&sniffer_thread, NULL, serverSlaveThread, - (void*) connection) < 0) { + if (! threadStarter.startThread(*connection)) { m_logger->sayF(LOG_ERROR | CAT_PROCESS, LC_LISTEN_FOR_ALL_6, i18n("cannot create a thread: $1")).arg( diff --git a/net/ReTCP.hpp b/net/ReTCP.hpp index 4364ed8..22f3683 100644 --- a/net/ReTCP.hpp +++ b/net/ReTCP.hpp @@ -125,12 +125,12 @@ class ReTCPServer; /** * Implements a single server connection to a client (in a single thread). */ -class ReTCPServerConnection: public ReTCPConnection { +class ReTCPServerConnection: public ReTCPConnection, public ReThread { public: - ReTCPServerConnection(int id, ReLogger* logger, ReTCPServer* server); + ReTCPServerConnection(int id, ReTCPServer* server); virtual ~ReTCPServerConnection(); public: - void handleConnection(); + virtual void run(); private: ReTCPServer* m_server; ReSlaveAppender m_slaveAppender; diff --git a/net/ReUdpConnection.cpp b/net/ReUdpConnection.cpp index 2aeb961..8f4340f 100644 --- a/net/ReUdpConnection.cpp +++ b/net/ReUdpConnection.cpp @@ -4,7 +4,8 @@ * Created on: 12.11.2010 * Author: wk */ -#include "../base/renet.hpp" +#include "base/rebase.hpp" +#include "net/renet.hpp" /** @brief Constructor. *