diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/Collision/Models/GameObjectModel.h | 2 | ||||
| -rw-r--r-- | src/common/Configuration/BuiltInConfig.cpp | 52 | ||||
| -rw-r--r-- | src/common/Configuration/BuiltInConfig.h | 42 | ||||
| -rw-r--r-- | src/common/Configuration/Config.cpp | 14 | ||||
| -rw-r--r-- | src/common/Configuration/Config.h | 14 | ||||
| -rw-r--r-- | src/common/Debugging/Errors.cpp | 7 | ||||
| -rw-r--r-- | src/common/Debugging/Errors.h | 2 | ||||
| -rw-r--r-- | src/common/GitRevision.cpp | 20 | ||||
| -rw-r--r-- | src/common/GitRevision.h | 4 | ||||
| -rw-r--r-- | src/common/Logging/Log.cpp | 25 | ||||
| -rw-r--r-- | src/common/Logging/Log.h | 7 | ||||
| -rw-r--r-- | src/common/Platform/ServiceWin32.cpp | 263 | ||||
| -rw-r--r-- | src/common/Platform/ServiceWin32.h | 28 | ||||
| -rw-r--r-- | src/common/Threading/LockedQueue.h | 8 | ||||
| -rw-r--r-- | src/common/Threading/MPSCQueue.h | 83 | ||||
| -rw-r--r-- | src/common/Utilities/Random.cpp | 8 | ||||
| -rw-r--r-- | src/common/Utilities/Random.h | 4 | ||||
| -rw-r--r-- | src/common/Utilities/StringFormat.h | 2 | ||||
| -rw-r--r-- | src/common/Utilities/Util.cpp | 11 | ||||
| -rw-r--r-- | src/common/Utilities/Util.h | 1 |
20 files changed, 560 insertions, 37 deletions
diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index 9d8687233c1..7834f53c63a 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -84,4 +84,6 @@ private: std::unique_ptr<GameObjectModelOwnerBase> owner; }; +void LoadGameObjectModelList(std::string const& dataPath); + #endif // _GAMEOBJECT_MODEL_H diff --git a/src/common/Configuration/BuiltInConfig.cpp b/src/common/Configuration/BuiltInConfig.cpp new file mode 100644 index 00000000000..c2fc3b91766 --- /dev/null +++ b/src/common/Configuration/BuiltInConfig.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program 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; either version 2 of the License, or (at your + * option) any later version. + * + * 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/>. + */ + +#include "BuiltInConfig.h" +#include "Config.h" +#include "GitRevision.h" + +template<typename Fn> +static std::string GetStringWithDefaultValueFromFunction( + std::string const& key, Fn getter) +{ + std::string const value = sConfigMgr->GetStringDefault(key, ""); + return value.empty() ? getter() : value; +} + +std::string BuiltInConfig::GetCMakeCommand() +{ + return GetStringWithDefaultValueFromFunction( + "CMakeCommand", GitRevision::GetCMakeCommand); +} + +std::string BuiltInConfig::GetBuildDirectory() +{ + return GetStringWithDefaultValueFromFunction( + "BuildDirectory", GitRevision::GetBuildDirectory); +} + +std::string BuiltInConfig::GetSourceDirectory() +{ + return GetStringWithDefaultValueFromFunction( + "SourceDirectory", GitRevision::GetSourceDirectory); +} + +std::string BuiltInConfig::GetMySQLExecutable() +{ + return GetStringWithDefaultValueFromFunction( + "MySQLExecutable", GitRevision::GetMySQLExecutable); +} diff --git a/src/common/Configuration/BuiltInConfig.h b/src/common/Configuration/BuiltInConfig.h new file mode 100644 index 00000000000..4ae4ed40189 --- /dev/null +++ b/src/common/Configuration/BuiltInConfig.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program 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; either version 2 of the License, or (at your + * option) any later version. + * + * 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/>. + */ + +#ifndef BUILT_IN_CONFIG_H +#define BUILT_IN_CONFIG_H + +#include <string> + +/// Provides helper functions to access built-in values +/// which can be overwritten in config +namespace BuiltInConfig +{ + /// Returns the CMake command when any is specified in the config, + /// returns the built-in path otherwise + std::string GetCMakeCommand(); + /// Returns the build directory path when any is specified in the config, + /// returns the built-in one otherwise + std::string GetBuildDirectory(); + /// Returns the source directory path when any is specified in the config, + /// returns the built-in one otherwise + std::string GetSourceDirectory(); + /// Returns the path to the mysql executable (`mysql`) when any is specified + /// in the config, returns the built-in one otherwise + std::string GetMySQLExecutable(); + +} // namespace BuiltInConfig + +#endif // BUILT_IN_CONFIG_H diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index 6ac04615315..fba438dbd33 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -56,12 +56,18 @@ bool ConfigMgr::LoadInitial(std::string const& file, std::string& error) return true; } +ConfigMgr* ConfigMgr::instance() +{ + static ConfigMgr instance; + return &instance; +} + bool ConfigMgr::Reload(std::string& error) { return LoadInitial(_filename, error); } -std::string ConfigMgr::GetStringDefault(std::string const& name, const std::string& def) +std::string ConfigMgr::GetStringDefault(std::string const& name, const std::string& def) const { std::string value = _config.get<std::string>(ptree::path_type(name, '/'), def); @@ -70,7 +76,7 @@ std::string ConfigMgr::GetStringDefault(std::string const& name, const std::stri return value; } -bool ConfigMgr::GetBoolDefault(std::string const& name, bool def) +bool ConfigMgr::GetBoolDefault(std::string const& name, bool def) const { try { @@ -84,12 +90,12 @@ bool ConfigMgr::GetBoolDefault(std::string const& name, bool def) } } -int ConfigMgr::GetIntDefault(std::string const& name, int def) +int ConfigMgr::GetIntDefault(std::string const& name, int def) const { return _config.get<int>(ptree::path_type(name, '/'), def); } -float ConfigMgr::GetFloatDefault(std::string const& name, float def) +float ConfigMgr::GetFloatDefault(std::string const& name, float def) const { return _config.get<float>(ptree::path_type(name, '/'), def); } diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h index 5b04212ed7c..6882517b509 100644 --- a/src/common/Configuration/Config.h +++ b/src/common/Configuration/Config.h @@ -33,18 +33,14 @@ public: /// Method used only for loading main configuration files (authserver.conf and worldserver.conf) bool LoadInitial(std::string const& file, std::string& error); - static ConfigMgr* instance() - { - static ConfigMgr instance; - return &instance; - } + static ConfigMgr* instance(); bool Reload(std::string& error); - std::string GetStringDefault(std::string const& name, const std::string& def); - bool GetBoolDefault(std::string const& name, bool def); - int GetIntDefault(std::string const& name, int def); - float GetFloatDefault(std::string const& name, float def); + std::string GetStringDefault(std::string const& name, const std::string& def) const; + bool GetBoolDefault(std::string const& name, bool def) const; + int GetIntDefault(std::string const& name, int def) const; + float GetFloatDefault(std::string const& name, float def) const; std::string const& GetFilename(); std::list<std::string> GetKeysByString(std::string const& name); diff --git a/src/common/Debugging/Errors.cpp b/src/common/Debugging/Errors.cpp index 1ec66ff6d59..2ce00229e53 100644 --- a/src/common/Debugging/Errors.cpp +++ b/src/common/Debugging/Errors.cpp @@ -96,4 +96,11 @@ void Abort(char const* file, int line, char const* function) exit(1); } +void AbortHandler(int /*sigval*/) +{ + // nothing useful to log here, no way to pass args + *((volatile int*)NULL) = 0; + exit(1); +} + } // namespace Trinity diff --git a/src/common/Debugging/Errors.h b/src/common/Debugging/Errors.h index 38e311a6b13..37d247ada82 100644 --- a/src/common/Debugging/Errors.h +++ b/src/common/Debugging/Errors.h @@ -34,6 +34,8 @@ namespace Trinity void Warning(char const* file, int line, char const* function, char const* message); + DECLSPEC_NORETURN void AbortHandler(int sigval) ATTR_NORETURN; + } // namespace Trinity #if COMPILER == COMPILER_MICROSOFT diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp index d0719c09959..5343fbd6531 100644 --- a/src/common/GitRevision.cpp +++ b/src/common/GitRevision.cpp @@ -17,6 +17,16 @@ char const* GitRevision::GetBranch() return _BRANCH; } +char const* GitRevision::GetCMakeCommand() +{ + return _CMAKE_COMMAND; +} + +char const* GitRevision::GetBuildDirectory() +{ + return _BUILD_DIRECTORY; +} + char const* GitRevision::GetSourceDirectory() { return _SOURCE_DIRECTORY; @@ -66,13 +76,3 @@ char const* GitRevision::GetProductVersionStr() { return VER_PRODUCTVERSION_STR; } - -char const* GitRevision::GetCompilerCFlags() -{ - return COMPILER_C_FLAGS; -} - -char const* GitRevision::GetCompilerCXXFlags() -{ - return COMPILER_CXX_FLAGS; -} diff --git a/src/common/GitRevision.h b/src/common/GitRevision.h index 8d2764ba861..7fddcb7605a 100644 --- a/src/common/GitRevision.h +++ b/src/common/GitRevision.h @@ -25,6 +25,8 @@ namespace GitRevision char const* GetHash(); char const* GetDate(); char const* GetBranch(); + char const* GetCMakeCommand(); + char const* GetBuildDirectory(); char const* GetSourceDirectory(); char const* GetMySQLExecutable(); char const* GetFullDatabase(); @@ -33,8 +35,6 @@ namespace GitRevision char const* GetLegalCopyrightStr(); char const* GetFileVersionStr(); char const* GetProductVersionStr(); - char const* GetCompilerCFlags(); - char const* GetCompilerCXXFlags(); } #endif diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp index 4bd0487343d..f7a84fb8b47 100644 --- a/src/common/Logging/Log.cpp +++ b/src/common/Logging/Log.cpp @@ -214,13 +214,13 @@ void Log::ReadLoggersFromConfig() AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, ExtraAppenderArgs()); appenders[appender->getId()] = appender; - Logger& logger = loggers[LOGGER_ROOT]; - logger.Create(LOGGER_ROOT, LOG_LEVEL_ERROR); - logger.addAppender(appender->getId(), appender); + Logger& rootLogger = loggers[LOGGER_ROOT]; + rootLogger.Create(LOGGER_ROOT, LOG_LEVEL_ERROR); + rootLogger.addAppender(appender->getId(), appender); - logger = loggers["server"]; - logger.Create("server", LOG_LEVEL_ERROR); - logger.addAppender(appender->getId(), appender); + Logger& serverLogger = loggers["server"]; + serverLogger.Create("server", LOG_LEVEL_INFO); + serverLogger.addAppender(appender->getId(), appender); } } @@ -320,6 +320,12 @@ void Log::Close() appenders.clear(); } +Log* Log::instance() +{ + static Log instance; + return &instance; +} + void Log::Initialize(boost::asio::io_service* ioService) { if (ioService) @@ -331,6 +337,13 @@ void Log::Initialize(boost::asio::io_service* ioService) LoadFromConfig(); } +void Log::SetSynchronous() +{ + delete _strand; + _strand = nullptr; + _ioService = nullptr; +} + void Log::LoadFromConfig() { Close(); diff --git a/src/common/Logging/Log.h b/src/common/Logging/Log.h index a90481ad5d2..062f14d525c 100644 --- a/src/common/Logging/Log.h +++ b/src/common/Logging/Log.h @@ -44,13 +44,10 @@ class Log public: - static Log* instance() - { - static Log instance; - return &instance; - } + static Log* instance(); void Initialize(boost::asio::io_service* ioService); + void SetSynchronous(); // Not threadsafe - should only be called from main() after all threads are joined void LoadFromConfig(); void Close(); bool ShouldLog(std::string const& type, LogLevel level) const; diff --git a/src/common/Platform/ServiceWin32.cpp b/src/common/Platform/ServiceWin32.cpp new file mode 100644 index 00000000000..3c34f3e322c --- /dev/null +++ b/src/common/Platform/ServiceWin32.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com> + * + * This program 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; either version 2 of the License, or (at your + * option) any later version. + * + * 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/>. + */ + +#ifdef _WIN32 + +#include "Common.h" +#include "Log.h" +#include <cstring> +#include <windows.h> +#include <winsvc.h> + +#if !defined(WINADVAPI) +#if !defined(_ADVAPI32_) +#define WINADVAPI DECLSPEC_IMPORT +#else +#define WINADVAPI +#endif +#endif + +extern int main(int argc, char ** argv); +extern char serviceLongName[]; +extern char serviceName[]; +extern char serviceDescription[]; + +extern int m_ServiceStatus; + +SERVICE_STATUS serviceStatus; + +SERVICE_STATUS_HANDLE serviceStatusHandle = 0; + +typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID); + +bool WinServiceInstall() +{ + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE); + + if (serviceControlManager) + { + char path[_MAX_PATH + 10]; + if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0) + { + SC_HANDLE service; + std::strcat(path, " --service run"); + service = CreateService(serviceControlManager, + serviceName, // name of service + serviceLongName, // service name to display + SERVICE_ALL_ACCESS, // desired access + // service type + SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, + SERVICE_AUTO_START, // start type + SERVICE_ERROR_IGNORE, // error control type + path, // service's binary + 0, // no load ordering group + 0, // no tag identifier + 0, // no dependencies + 0, // LocalSystem account + 0); // no password + if (service) + { + HMODULE advapi32 = GetModuleHandle("ADVAPI32.DLL"); + if (!advapi32) + { + CloseServiceHandle(service); + CloseServiceHandle(serviceControlManager); + return false; + } + + CSD_T ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A"); + if (!ChangeService_Config2) + { + CloseServiceHandle(service); + CloseServiceHandle(serviceControlManager); + return false; + } + + SERVICE_DESCRIPTION sdBuf; + sdBuf.lpDescription = serviceDescription; + ChangeService_Config2( + service, // handle to service + SERVICE_CONFIG_DESCRIPTION, // change: description + &sdBuf); // new data + + SC_ACTION _action[1]; + _action[0].Type = SC_ACTION_RESTART; + _action[0].Delay = 10000; + SERVICE_FAILURE_ACTIONS sfa; + ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS)); + sfa.lpsaActions = _action; + sfa.cActions = 1; + sfa.dwResetPeriod =INFINITE; + ChangeService_Config2( + service, // handle to service + SERVICE_CONFIG_FAILURE_ACTIONS, // information level + &sfa); // new data + + CloseServiceHandle(service); + + } + } + CloseServiceHandle(serviceControlManager); + } + + printf("Service installed\n"); + return true; +} + +bool WinServiceUninstall() +{ + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); + + if (serviceControlManager) + { + SC_HANDLE service = OpenService(serviceControlManager, + serviceName, SERVICE_QUERY_STATUS | DELETE); + if (service) + { + SERVICE_STATUS serviceStatus2; + if (QueryServiceStatus(service, &serviceStatus2)) + { + if (serviceStatus2.dwCurrentState == SERVICE_STOPPED) + DeleteService(service); + } + CloseServiceHandle(service); + } + + CloseServiceHandle(serviceControlManager); + } + + printf("Service uninstalled\n"); + return true; +} + +void WINAPI ServiceControlHandler(DWORD controlCode) +{ + switch (controlCode) + { + case SERVICE_CONTROL_INTERROGATE: + break; + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + m_ServiceStatus = 0; + return; + + case SERVICE_CONTROL_PAUSE: + m_ServiceStatus = 2; + serviceStatus.dwCurrentState = SERVICE_PAUSED; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + break; + + case SERVICE_CONTROL_CONTINUE: + serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + m_ServiceStatus = 1; + break; + + default: + if ( controlCode >= 128 && controlCode <= 255 ) + // user defined control code + break; + else + // unrecognized control code + break; + } + + SetServiceStatus(serviceStatusHandle, &serviceStatus); +} + +void WINAPI ServiceMain(DWORD argc, char *argv[]) +{ + // initialise service status + serviceStatus.dwServiceType = SERVICE_WIN32; + serviceStatus.dwCurrentState = SERVICE_START_PENDING; + serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; + serviceStatus.dwWin32ExitCode = NO_ERROR; + serviceStatus.dwServiceSpecificExitCode = NO_ERROR; + serviceStatus.dwCheckPoint = 0; + serviceStatus.dwWaitHint = 0; + + serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler); + + if ( serviceStatusHandle ) + { + char path[_MAX_PATH + 1]; + unsigned int i, last_slash = 0; + + GetModuleFileName(0, path, sizeof(path)/sizeof(path[0])); + + size_t pathLen = std::strlen(path); + for (i = 0; i < pathLen; i++) + { + if (path[i] == '\\') last_slash = i; + } + + path[last_slash] = 0; + + // service is starting + serviceStatus.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + // do initialisation here + SetCurrentDirectory(path); + + // running + serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus( serviceStatusHandle, &serviceStatus ); + + //////////////////////// + // service main cycle // + //////////////////////// + + m_ServiceStatus = 1; + argc = 1; + main(argc, argv); + + // service was stopped + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + // do cleanup here + + // service is now stopped + serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + } +} + +bool WinServiceRun() +{ + SERVICE_TABLE_ENTRY serviceTable[] = + { + { serviceName, ServiceMain }, + { 0, 0 } + }; + + if (!StartServiceCtrlDispatcher(serviceTable)) + { + TC_LOG_ERROR("server.worldserver", "StartService Failed. Error [%u]", uint32(::GetLastError())); + return false; + } + return true; +} +#endif diff --git a/src/common/Platform/ServiceWin32.h b/src/common/Platform/ServiceWin32.h new file mode 100644 index 00000000000..b892ba4e3b6 --- /dev/null +++ b/src/common/Platform/ServiceWin32.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com> + * + * This program 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; either version 2 of the License, or (at your + * option) any later version. + * + * 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/>. + */ + +#ifdef _WIN32 +#ifndef _WIN32_SERVICE_ +#define _WIN32_SERVICE_ + +bool WinServiceInstall(); +bool WinServiceUninstall(); +bool WinServiceRun(); + +#endif // _WIN32_SERVICE_ +#endif // _WIN32 diff --git a/src/common/Threading/LockedQueue.h b/src/common/Threading/LockedQueue.h index c6faaaf81ca..21a29d7e53b 100644 --- a/src/common/Threading/LockedQueue.h +++ b/src/common/Threading/LockedQueue.h @@ -57,6 +57,14 @@ public: unlock(); } + //! Adds items back to front of the queue + template<class Iterator> + void readd(Iterator begin, Iterator end) + { + std::lock_guard<std::mutex> lock(_lock); + _queue.insert(_queue.begin(), begin, end); + } + //! Gets the next result in the queue, if any. bool next(T& result) { diff --git a/src/common/Threading/MPSCQueue.h b/src/common/Threading/MPSCQueue.h new file mode 100644 index 00000000000..09648b844be --- /dev/null +++ b/src/common/Threading/MPSCQueue.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program 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; either version 2 of the License, or (at your + * option) any later version. + * + * 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/>. + */ + +#ifndef MPSCQueue_h__ +#define MPSCQueue_h__ + +#include <atomic> +#include <utility> + +// C++ implementation of Dmitry Vyukov's lock free MPSC queue +// http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue +template<typename T> +class MPSCQueue +{ +public: + MPSCQueue() : _head(new Node()), _tail(_head.load(std::memory_order_relaxed)) + { + Node* front = _head.load(std::memory_order_relaxed); + front->Next.store(nullptr, std::memory_order_relaxed); + } + + ~MPSCQueue() + { + T* output; + while (this->Dequeue(output)) + ; + + Node* front = _head.load(std::memory_order_relaxed); + delete front; + } + + void Enqueue(T* input) + { + Node* node = new Node(input); + Node* prevHead = _head.exchange(node, std::memory_order_acq_rel); + prevHead->Next.store(node, std::memory_order_release); + } + + bool Dequeue(T*& result) + { + Node* tail = _tail.load(std::memory_order_relaxed); + Node* next = tail->Next.load(std::memory_order_acquire); + if (!next) + return false; + + result = next->Data; + _tail.store(next, std::memory_order_release); + delete tail; + return true; + } + +private: + struct Node + { + Node() = default; + explicit Node(T* data) : Data(data) { Next.store(nullptr, std::memory_order_relaxed); } + + T* Data; + std::atomic<Node*> Next; + }; + + std::atomic<Node*> _head; + std::atomic<Node*> _tail; + + MPSCQueue(MPSCQueue const&) = delete; + MPSCQueue& operator=(MPSCQueue const&) = delete; +}; + +#endif // MPSCQueue_h__ diff --git a/src/common/Utilities/Random.cpp b/src/common/Utilities/Random.cpp index cc013110b01..31318e8f52d 100644 --- a/src/common/Utilities/Random.cpp +++ b/src/common/Utilities/Random.cpp @@ -61,6 +61,14 @@ float frand(float min, float max) return float(GetRng()->Random() * (max - min) + min); } +Milliseconds randtime(Milliseconds const& min, Milliseconds const& max) +{ + long long diff = max.count() - min.count(); + ASSERT(diff >= 0); + ASSERT(diff <= (uint32)-1); + return min + Milliseconds(urand(0, diff)); +} + uint32 rand32() { return GetRng()->BRandom(); diff --git a/src/common/Utilities/Random.h b/src/common/Utilities/Random.h index 5610651a83b..5dea6117f97 100644 --- a/src/common/Utilities/Random.h +++ b/src/common/Utilities/Random.h @@ -19,6 +19,7 @@ #define Random_h__ #include "Define.h" +#include "Duration.h" #include <limits> #include <random> @@ -34,6 +35,9 @@ uint32 urandms(uint32 min, uint32 max); /* Return a random number in the range 0 .. UINT32_MAX. */ uint32 rand32(); +/* Return a random time in the range min..max (up to millisecond precision). Only works for values where millisecond difference is a valid uint32. */ +Milliseconds randtime(Milliseconds const& min, Milliseconds const& max); + /* Return a random number in the range min..max */ float frand(float min, float max); diff --git a/src/common/Utilities/StringFormat.h b/src/common/Utilities/StringFormat.h index d85523bc11f..e21b1024e87 100644 --- a/src/common/Utilities/StringFormat.h +++ b/src/common/Utilities/StringFormat.h @@ -19,7 +19,7 @@ #ifndef TRINITYCORE_STRING_FORMAT_H #define TRINITYCORE_STRING_FORMAT_H -#include "format.h" +#include "cppformat/format.h" namespace Trinity { diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index 1360253294f..ddc07505942 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -487,6 +487,17 @@ void vutf8printf(FILE* out, const char *str, va_list* ap) #endif } +bool Utf8ToUpperOnlyLatin(std::string& utf8String) +{ + std::wstring wstr; + if (!Utf8toWStr(utf8String, wstr)) + return false; + + std::transform(wstr.begin(), wstr.end(), wstr.begin(), wcharToUpperOnlyLatin); + + return WStrToUtf8(wstr, utf8String); +} + std::string ByteArrayToHexStr(uint8 const* bytes, uint32 arrayLen, bool reverse /* = false */) { int32 init = 0; diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index ab5cabca8d2..a3e3f21466e 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -310,6 +310,7 @@ bool consoleToUtf8(const std::string& conStr, std::string& utf8str); bool Utf8FitTo(const std::string& str, std::wstring const& search); void utf8printf(FILE* out, const char *str, ...); void vutf8printf(FILE* out, const char *str, va_list* ap); +bool Utf8ToUpperOnlyLatin(std::string& utf8String); bool IsIPAddress(char const* ipaddress); |
