From e4bff8be94c0db4f94e63ad448d0eeb869ccdbbd Mon Sep 17 00:00:00 2001 From: ShadowNinja Date: Tue, 7 Apr 2015 06:13:12 -0400 Subject: Clean up threading * Rename everything. * Strip J prefix. * Change UpperCamelCase functions to lowerCamelCase. * Remove global (!) semaphore count mutex on OSX. * Remove semaphore count getter (unused, unsafe, depended on internal API functions on Windows, and used a hack on OSX). * Add `Atomic`. * Make `Thread` handle thread names. * Add support for C++11 multi-threading. * Combine pthread and win32 sources. * Remove `ThreadStarted` (unused, unneeded). * Move some includes from the headers to the sources. * Move all of `Event` into its header (allows inlining with no new includes). * Make `Event` use `Semaphore` (except on Windows). * Move some porting functions into `Thread`. * Integrate logging with `Thread`. * Add threading test. --- .gitignore | 44 +---- build/android/jni/Android.mk | 15 +- src/CMakeLists.txt | 2 +- src/ban.cpp | 18 +- src/ban.h | 8 +- src/client.cpp | 20 +- src/client.h | 13 +- src/client/clientlauncher.cpp | 6 +- src/client/tile.cpp | 14 +- src/clientiface.cpp | 24 +-- src/clientiface.h | 12 +- src/clientmap.cpp | 22 +-- src/clientmap.h | 4 +- src/debug.cpp | 14 +- src/emerge.cpp | 41 ++--- src/emerge.h | 2 +- src/environment.cpp | 12 +- src/environment.h | 6 +- src/httpfetch.cpp | 38 ++-- src/jthread/CMakeLists.txt | 14 -- src/jthread/LICENSE.MIT | 20 -- src/jthread/jevent.h | 59 ------ src/jthread/jmutex.h | 79 -------- src/jthread/jmutexautolock.h | 43 ----- src/jthread/jsemaphore.h | 64 ------- src/jthread/jthread.h | 117 ------------ src/jthread/pthread/jevent.cpp | 67 ------- src/jthread/pthread/jmutex.cpp | 58 ------ src/jthread/pthread/jsemaphore.cpp | 156 ---------------- src/jthread/pthread/jthread.cpp | 168 ----------------- src/jthread/win32/jevent.cpp | 43 ----- src/jthread/win32/jmutex.cpp | 68 ------- src/jthread/win32/jsemaphore.cpp | 104 ----------- src/jthread/win32/jthread.cpp | 146 --------------- src/log.cpp | 22 +-- src/main.cpp | 2 +- src/mapblock.cpp | 2 +- src/mg_decoration.cpp | 6 +- src/mg_decoration.h | 2 +- src/minimap.cpp | 20 +- src/minimap.h | 17 +- src/network/clientpackethandler.cpp | 8 +- src/network/connection.cpp | 128 +++++++------ src/network/connection.h | 62 +++---- src/particles.cpp | 16 +- src/particles.h | 4 +- src/player.cpp | 10 +- src/player.h | 4 +- src/porting.cpp | 124 ------------- src/porting.h | 89 --------- src/porting_android.cpp | 17 +- src/profiler.h | 20 +- src/quicktune.cpp | 14 +- src/script/cpp_api/s_async.cpp | 68 +++---- src/script/cpp_api/s_async.h | 27 +-- src/script/cpp_api/s_base.h | 6 +- src/script/cpp_api/s_internal.h | 6 +- src/server.cpp | 106 +++++------ src/server.h | 4 +- src/settings.cpp | 36 ++-- src/settings.h | 6 +- src/shader.cpp | 8 +- src/threading/CMakeLists.txt | 6 + src/threading/atomic.h | 96 ++++++++++ src/threading/event.h | 57 ++++++ src/threading/mutex.cpp | 83 +++++++++ src/threading/mutex.h | 66 +++++++ src/threading/mutex_auto_lock.h | 50 +++++ src/threading/semaphore.cpp | 161 ++++++++++++++++ src/threading/semaphore.h | 52 ++++++ src/threading/thread.cpp | 354 ++++++++++++++++++++++++++++++++++++ src/threading/thread.h | 119 ++++++++++++ src/threads.h | 6 +- src/unittest/CMakeLists.txt | 1 + src/unittest/test_threading.cpp | 85 +++++++++ src/util/container.h | 171 +++++------------ src/util/numeric.cpp | 6 +- src/util/numeric.h | 4 +- src/util/thread.h | 60 +++--- 79 files changed, 1640 insertions(+), 2092 deletions(-) delete mode 100644 src/jthread/CMakeLists.txt delete mode 100644 src/jthread/LICENSE.MIT delete mode 100644 src/jthread/jevent.h delete mode 100644 src/jthread/jmutex.h delete mode 100644 src/jthread/jmutexautolock.h delete mode 100644 src/jthread/jsemaphore.h delete mode 100644 src/jthread/jthread.h delete mode 100644 src/jthread/pthread/jevent.cpp delete mode 100644 src/jthread/pthread/jmutex.cpp delete mode 100644 src/jthread/pthread/jsemaphore.cpp delete mode 100644 src/jthread/pthread/jthread.cpp delete mode 100644 src/jthread/win32/jevent.cpp delete mode 100644 src/jthread/win32/jmutex.cpp delete mode 100644 src/jthread/win32/jsemaphore.cpp delete mode 100755 src/jthread/win32/jthread.cpp create mode 100644 src/threading/CMakeLists.txt create mode 100644 src/threading/atomic.h create mode 100644 src/threading/event.h create mode 100644 src/threading/mutex.cpp create mode 100644 src/threading/mutex.h create mode 100644 src/threading/mutex_auto_lock.h create mode 100644 src/threading/semaphore.cpp create mode 100644 src/threading/semaphore.h create mode 100644 src/threading/thread.cpp create mode 100644 src/threading/thread.h create mode 100644 src/unittest/test_threading.cpp diff --git a/.gitignore b/.gitignore index 7b2b030af..77b6a2b00 100644 --- a/.gitignore +++ b/.gitignore @@ -36,45 +36,18 @@ doc/html/ doc/doxygen_* ## Build files -CMakeFiles/* -src/CMakeFiles/* -src/Makefile -src/android_version_githash.h +CMakeFiles +Makefile +!build/android/Makefile +cmake_install.cmake +CMakeCache.txt +CPackConfig.cmake +CPackSourceConfig.cmake src/android_version.h +src/android_version_githash.h src/cmake_config.h src/cmake_config_githash.h -src/cmake_install.cmake -src/script/CMakeFiles/* -src/script/common/CMakeFiles/* -src/script/cpp_api/CMakeFiles/* -src/script/lua_api/CMakeFiles/* -src/util/CMakeFiles/* -src/unittest/CMakeFiles/* -src/jthread/CMakeFiles/* -src/jthread/Makefile -src/jthread/cmake_config.h -src/jthread/cmake_install.cmake -src/jthread/libjthread.a -src/json/libjson.a src/lua/build/ -src/lua/CMakeFiles/ -src/cguittfont/CMakeFiles/ -src/cguittfont/libcguittfont.a -src/cguittfont/cmake_install.cmake -src/cguittfont/Makefile -src/gmp/CMakeFiles/ -src/gmp/libgmp.a -src/json/CMakeFiles/ -src/json/libjsoncpp.a -src/sqlite/CMakeFiles/* -src/sqlite/libsqlite3.a -src/client/CMakeFiles/ -src/network/CMakeFiles/ -CMakeCache.txt -CPackConfig.cmake -CPackSourceConfig.cmake -Makefile -cmake_install.cmake locale/ .directory .kdev4/ @@ -82,6 +55,7 @@ locale/ *.kdev4 *.layout *.o +*.a ## Android build files build/android/assets diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk index 61ba1d0f0..cf7094ca8 100644 --- a/build/android/jni/Android.mk +++ b/build/android/jni/Android.mk @@ -342,17 +342,16 @@ LOCAL_SRC_FILES += \ jni/src/lua/src/lzio.c \ jni/src/lua/src/print.c -# sqlite +# SQLite3 LOCAL_SRC_FILES += deps/sqlite/sqlite3.c -# jthread -LOCAL_SRC_FILES += \ - jni/src/jthread/pthread/jevent.cpp \ - jni/src/jthread/pthread/jmutex.cpp \ - jni/src/jthread/pthread/jsemaphore.cpp \ - jni/src/jthread/pthread/jthread.cpp +# Threading +LOCAL_SRC_FILES += \ + jni/src/threading/Mutex.cpp \ + jni/src/threading/Semaphore.cpp \ + jni/src/threading/Thread.cpp -# json +# JSONCPP LOCAL_SRC_FILES += jni/src/json/jsoncpp.cpp LOCAL_SHARED_LIBRARIES := iconv openal ogg vorbis gmp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 614e81908..2d52de68b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -297,7 +297,7 @@ add_custom_target(GenerateVersion WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") -add_subdirectory(jthread) +add_subdirectory(threading) add_subdirectory(network) add_subdirectory(script) add_subdirectory(unittest) diff --git a/src/ban.cpp b/src/ban.cpp index 7c1a68d45..108319953 100644 --- a/src/ban.cpp +++ b/src/ban.cpp @@ -19,7 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "ban.h" #include -#include "jthread/jmutexautolock.h" +#include "threading/mutex_auto_lock.h" #include #include #include "strfnd.h" @@ -48,7 +48,7 @@ BanManager::~BanManager() void BanManager::load() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); infostream<<"BanManager: loading from "<first == ip_or_name || it->second == ip_or_name @@ -110,7 +110,7 @@ std::string BanManager::getBanDescription(const std::string &ip_or_name) std::string BanManager::getBanName(const std::string &ip) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); StringMap::iterator it = m_ips.find(ip); if (it == m_ips.end()) return ""; @@ -119,14 +119,14 @@ std::string BanManager::getBanName(const std::string &ip) void BanManager::add(const std::string &ip, const std::string &name) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); m_ips[ip] = name; m_modified = true; } void BanManager::remove(const std::string &ip_or_name) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); for (StringMap::iterator it = m_ips.begin(); it != m_ips.end();) { if ((it->first == ip_or_name) || (it->second == ip_or_name)) { m_ips.erase(it++); @@ -140,7 +140,7 @@ void BanManager::remove(const std::string &ip_or_name) bool BanManager::isModified() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); return m_modified; } diff --git a/src/ban.h b/src/ban.h index 5db7179de..d1a49cb15 100644 --- a/src/ban.h +++ b/src/ban.h @@ -21,9 +21,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #define BAN_HEADER #include "util/string.h" -#include "jthread/jthread.h" -#include "jthread/jmutex.h" +#include "threading/thread.h" +#include "threading/mutex.h" #include "exceptions.h" +#include +#include class BanManager { @@ -40,7 +42,7 @@ public: void remove(const std::string &ip_or_name); bool isModified(); private: - JMutex m_mutex; + Mutex m_mutex; std::string m_banfilepath; StringMap m_ips; bool m_modified; diff --git a/src/client.cpp b/src/client.cpp index 946f4f1c4..2a253fd75 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -21,7 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#include "jthread/jmutexautolock.h" +#include "threading/mutex_auto_lock.h" #include "util/auth.h" #include "util/directiontables.h" #include "util/pointedthing.h" @@ -82,7 +82,7 @@ MeshUpdateQueue::MeshUpdateQueue() MeshUpdateQueue::~MeshUpdateQueue() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); for(std::vector::iterator i = m_queue.begin(); @@ -102,7 +102,7 @@ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_se assert(data); // pre-condition - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); if(urgent) m_urgents.insert(p); @@ -141,7 +141,7 @@ void MeshUpdateQueue::addBlock(v3s16 p, MeshMakeData *data, bool ack_block_to_se // Returns NULL if queue is empty QueuedMeshUpdate *MeshUpdateQueue::pop() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); bool must_be_urgent = !m_urgents.empty(); for(std::vector::iterator @@ -269,7 +269,7 @@ Client::Client( void Client::Stop() { //request all client managed threads to stop - m_mesh_update_thread.Stop(); + m_mesh_update_thread.stop(); // Save local server map if (m_localdb) { infostream << "Local map saving ended." << std::endl; @@ -280,7 +280,7 @@ void Client::Stop() bool Client::isShutdown() { - if (!m_mesh_update_thread.IsRunning()) return true; + if (!m_mesh_update_thread.isRunning()) return true; return false; } @@ -289,8 +289,8 @@ Client::~Client() { m_con.Disconnect(); - m_mesh_update_thread.Stop(); - m_mesh_update_thread.Wait(); + m_mesh_update_thread.stop(); + m_mesh_update_thread.wait(); while (!m_mesh_update_thread.m_queue_out.empty()) { MeshUpdateResult r = m_mesh_update_thread.m_queue_out.pop_frontNoEx(); delete r.mesh; @@ -1270,7 +1270,7 @@ void Client::sendPlayerPos() u16 our_peer_id; { - //JMutexAutoLock lock(m_con_mutex); //bulk comment-out + //MutexAutoLock lock(m_con_mutex); //bulk comment-out our_peer_id = m_con.GetPeerID(); } @@ -1794,7 +1794,7 @@ void Client::afterContentReceived(IrrlichtDevice *device) // Start mesh update thread after setting up content definitions infostream<<"- Starting mesh update thread"< #include #include @@ -89,14 +89,14 @@ public: u32 size() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); return m_queue.size(); } private: std::vector m_queue; std::set m_urgents; - JMutex m_mutex; + Mutex m_mutex; }; struct MeshUpdateResult @@ -119,19 +119,14 @@ private: MeshUpdateQueue m_queue_in; protected: - const char *getName() - { return "MeshUpdateThread"; } virtual void doUpdate(); public: - MeshUpdateThread() - { - } + MeshUpdateThread() : UpdateThread("Mesh") {} void enqueueUpdate(v3s16 p, MeshMakeData *data, bool ack_block_to_server, bool urgent); - MutexedQueue m_queue_out; v3s16 m_camera_offset; diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index bad5c384c..60eb21674 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -651,14 +651,14 @@ void ClientLauncher::speed_tests() infostream << "Around 5000/ms should do well here." << std::endl; TimeTaker timer("Testing mutex speed"); - JMutex m; + Mutex m; u32 n = 0; u32 i = 0; do { n += 10000; for (; i < n; i++) { - m.Lock(); - m.Unlock(); + m.lock(); + m.unlock(); } } // Do at least 10ms diff --git a/src/client/tile.cpp b/src/client/tile.cpp index a28b40c65..1f1e9d38c 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -414,7 +414,7 @@ private: // Maps a texture name to an index in the former. std::map m_name_to_id; // The two former containers are behind this mutex - JMutex m_textureinfo_cache_mutex; + Mutex m_textureinfo_cache_mutex; // Queued texture fetches (to be processed by the main thread) RequestQueue m_get_texture_queue; @@ -490,7 +490,7 @@ u32 TextureSource::getTextureId(const std::string &name) /* See if texture already exists */ - JMutexAutoLock lock(m_textureinfo_cache_mutex); + MutexAutoLock lock(m_textureinfo_cache_mutex); std::map::iterator n; n = m_name_to_id.find(name); if (n != m_name_to_id.end()) @@ -593,7 +593,7 @@ u32 TextureSource::generateTexture(const std::string &name) /* See if texture already exists */ - JMutexAutoLock lock(m_textureinfo_cache_mutex); + MutexAutoLock lock(m_textureinfo_cache_mutex); std::map::iterator n; n = m_name_to_id.find(name); if (n != m_name_to_id.end()) { @@ -631,7 +631,7 @@ u32 TextureSource::generateTexture(const std::string &name) Add texture to caches (add NULL textures too) */ - JMutexAutoLock lock(m_textureinfo_cache_mutex); + MutexAutoLock lock(m_textureinfo_cache_mutex); u32 id = m_textureinfo_cache.size(); TextureInfo ti(name, tex); @@ -643,7 +643,7 @@ u32 TextureSource::generateTexture(const std::string &name) std::string TextureSource::getTextureName(u32 id) { - JMutexAutoLock lock(m_textureinfo_cache_mutex); + MutexAutoLock lock(m_textureinfo_cache_mutex); if (id >= m_textureinfo_cache.size()) { @@ -658,7 +658,7 @@ std::string TextureSource::getTextureName(u32 id) video::ITexture* TextureSource::getTexture(u32 id) { - JMutexAutoLock lock(m_textureinfo_cache_mutex); + MutexAutoLock lock(m_textureinfo_cache_mutex); if (id >= m_textureinfo_cache.size()) return NULL; @@ -712,7 +712,7 @@ void TextureSource::insertSourceImage(const std::string &name, video::IImage *im void TextureSource::rebuildImagesAndTextures() { - JMutexAutoLock lock(m_textureinfo_cache_mutex); + MutexAutoLock lock(m_textureinfo_cache_mutex); video::IVideoDriver* driver = m_device->getVideoDriver(); sanity_check(driver); diff --git a/src/clientiface.cpp b/src/clientiface.cpp index 3330e0af9..d4efe60ef 100644 --- a/src/clientiface.cpp +++ b/src/clientiface.cpp @@ -593,7 +593,7 @@ ClientInterface::~ClientInterface() Delete clients */ { - JMutexAutoLock clientslock(m_clients_mutex); + MutexAutoLock clientslock(m_clients_mutex); for(std::map::iterator i = m_clients.begin(); @@ -609,7 +609,7 @@ ClientInterface::~ClientInterface() std::vector ClientInterface::getClientIDs(ClientState min_state) { std::vector reply; - JMutexAutoLock clientslock(m_clients_mutex); + MutexAutoLock clientslock(m_clients_mutex); for(std::map::iterator i = m_clients.begin(); @@ -660,7 +660,7 @@ void ClientInterface::UpdatePlayerList() infostream << "* " << player->getName() << "\t"; { - JMutexAutoLock clientslock(m_clients_mutex); + MutexAutoLock clientslock(m_clients_mutex); RemoteClient* client = lockedGetClientNoEx(*i); if(client != NULL) client->PrintInfo(infostream); @@ -680,7 +680,7 @@ void ClientInterface::send(u16 peer_id, u8 channelnum, void ClientInterface::sendToAll(u16 channelnum, NetworkPacket* pkt, bool reliable) { - JMutexAutoLock clientslock(m_clients_mutex); + MutexAutoLock clientslock(m_clients_mutex); for(std::map::iterator i = m_clients.begin(); i != m_clients.end(); ++i) { @@ -694,7 +694,7 @@ void ClientInterface::sendToAll(u16 channelnum, RemoteClient* ClientInterface::getClientNoEx(u16 peer_id, ClientState state_min) { - JMutexAutoLock clientslock(m_clients_mutex); + MutexAutoLock clientslock(m_clients_mutex); std::map::iterator n; n = m_clients.find(peer_id); // The client may not exist; clients are immediately removed if their @@ -725,7 +725,7 @@ RemoteClient* ClientInterface::lockedGetClientNoEx(u16 peer_id, ClientState stat ClientState ClientInterface::getClientState(u16 peer_id) { - JMutexAutoLock clientslock(m_clients_mutex); + MutexAutoLock clientslock(m_clients_mutex); std::map::iterator n; n = m_clients.find(peer_id); // The client may not exist; clients are immediately removed if their @@ -738,7 +738,7 @@ ClientState ClientInterface::getClientState(u16 peer_id) void ClientInterface::setPlayerName(u16 peer_id,std::string name) { - JMutexAutoLock clientslock(m_clients_mutex); + MutexAutoLock clientslock(m_clients_mutex); std::map::iterator n; n = m_clients.find(peer_id); // The client may not exist; clients are immediately removed if their @@ -749,7 +749,7 @@ void ClientInterface::setPlayerName(u16 peer_id,std::string name) void ClientInterface::DeleteClient(u16 peer_id) { - JMutexAutoLock conlock(m_clients_mutex); + MutexAutoLock conlock(m_clients_mutex); // Error check std::map::iterator n; @@ -784,7 +784,7 @@ void ClientInterface::DeleteClient(u16 peer_id) void ClientInterface::CreateClient(u16 peer_id) { - JMutexAutoLock conlock(m_clients_mutex); + MutexAutoLock conlock(m_clients_mutex); // Error check std::map::iterator n; @@ -801,7 +801,7 @@ void ClientInterface::CreateClient(u16 peer_id) void ClientInterface::event(u16 peer_id, ClientStateEvent event) { { - JMutexAutoLock clientlock(m_clients_mutex); + MutexAutoLock clientlock(m_clients_mutex); // Error check std::map::iterator n; @@ -823,7 +823,7 @@ void ClientInterface::event(u16 peer_id, ClientStateEvent event) u16 ClientInterface::getProtocolVersion(u16 peer_id) { - JMutexAutoLock conlock(m_clients_mutex); + MutexAutoLock conlock(m_clients_mutex); // Error check std::map::iterator n; @@ -838,7 +838,7 @@ u16 ClientInterface::getProtocolVersion(u16 peer_id) void ClientInterface::setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full) { - JMutexAutoLock conlock(m_clients_mutex); + MutexAutoLock conlock(m_clients_mutex); // Error check std::map::iterator n; diff --git a/src/clientiface.h b/src/clientiface.h index f6c4294e2..9be8bda61 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "constants.h" #include "serialization.h" // for SER_FMT_VER_INVALID -#include "jthread/jmutex.h" +#include "threading/mutex.h" #include "network/networkpacket.h" #include @@ -487,10 +487,8 @@ public: protected: //TODO find way to avoid this functions - void Lock() - { m_clients_mutex.Lock(); } - void Unlock() - { m_clients_mutex.Unlock(); } + void lock() { m_clients_mutex.lock(); } + void unlock() { m_clients_mutex.unlock(); } std::map& getClientList() { return m_clients; } @@ -501,14 +499,14 @@ private: // Connection con::Connection* m_con; - JMutex m_clients_mutex; + Mutex m_clients_mutex; // Connected clients (behind the con mutex) std::map m_clients; std::vector m_clients_names; //for announcing masterserver // Environment ServerEnvironment *m_env; - JMutex m_env_mutex; + Mutex m_env_mutex; float m_print_info_timer; diff --git a/src/clientmap.cpp b/src/clientmap.cpp index 288a12135..b890e338b 100644 --- a/src/clientmap.cpp +++ b/src/clientmap.cpp @@ -70,7 +70,7 @@ ClientMap::ClientMap( ClientMap::~ClientMap() { - /*JMutexAutoLock lock(mesh_mutex); + /*MutexAutoLock lock(mesh_mutex); if(mesh != NULL) { @@ -94,7 +94,7 @@ MapSector * ClientMap::emergeSector(v2s16 p2d) ClientMapSector *sector = new ClientMapSector(this, p2d, m_gamedef); { - //JMutexAutoLock lock(m_sector_mutex); // Bulk comment-out + //MutexAutoLock lock(m_sector_mutex); // Bulk comment-out m_sectors[p2d] = sector; } @@ -157,12 +157,12 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver) } m_drawlist.clear(); - m_camera_mutex.Lock(); + m_camera_mutex.lock(); v3f camera_position = m_camera_position; v3f camera_direction = m_camera_direction; f32 camera_fov = m_camera_fov; //v3s16 camera_offset = m_camera_offset; - m_camera_mutex.Unlock(); + m_camera_mutex.unlock(); // Use a higher fov to accomodate faster camera movements. // Blocks are cropped better when they are drawn. @@ -263,7 +263,7 @@ void ClientMap::updateDrawList(video::IVideoDriver* driver) Ignore if mesh doesn't exist */ { - //JMutexAutoLock lock(block->mesh_mutex); + //MutexAutoLock lock(block->mesh_mutex); if(block->mesh == NULL){ blocks_in_range_without_mesh++; @@ -433,11 +433,11 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) int crack = m_client->getCrackLevel(); u32 daynight_ratio = m_client->getEnv().getDayNightRatio(); - m_camera_mutex.Lock(); + m_camera_mutex.lock(); v3f camera_position = m_camera_position; v3f camera_direction = m_camera_direction; f32 camera_fov = m_camera_fov; - m_camera_mutex.Unlock(); + m_camera_mutex.unlock(); /* Get all blocks and draw all visible ones @@ -504,7 +504,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) // Mesh animation { - //JMutexAutoLock lock(block->mesh_mutex); + //MutexAutoLock lock(block->mesh_mutex); MapBlockMesh *mapBlockMesh = block->mesh; assert(mapBlockMesh); // Pretty random but this should work somewhat nicely @@ -534,7 +534,7 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass) Get the meshbuffers of the block */ { - //JMutexAutoLock lock(block->mesh_mutex); + //MutexAutoLock lock(block->mesh_mutex); MapBlockMesh *mapBlockMesh = block->mesh; assert(mapBlockMesh); @@ -799,9 +799,9 @@ void ClientMap::renderPostFx(CameraMode cam_mode) // Sadly ISceneManager has no "post effects" render pass, in that case we // could just register for that and handle it in renderMap(). - m_camera_mutex.Lock(); + m_camera_mutex.lock(); v3f camera_position = m_camera_position; - m_camera_mutex.Unlock(); + m_camera_mutex.unlock(); MapNode n = getNodeNoEx(floatToInt(camera_position, BS)); diff --git a/src/clientmap.h b/src/clientmap.h index 492e23fa5..54d1dc96d 100644 --- a/src/clientmap.h +++ b/src/clientmap.h @@ -89,7 +89,7 @@ public: void updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset) { - JMutexAutoLock lock(m_camera_mutex); + MutexAutoLock lock(m_camera_mutex); m_camera_position = pos; m_camera_direction = dir; m_camera_fov = fov; @@ -149,7 +149,7 @@ private: v3f m_camera_direction; f32 m_camera_fov; v3s16 m_camera_offset; - JMutex m_camera_mutex; + Mutex m_camera_mutex; std::map m_drawlist; diff --git a/src/debug.cpp b/src/debug.cpp index ae2ffadc3..3608f42d2 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -26,8 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#include "jthread/jmutex.h" -#include "jthread/jmutexautolock.h" +#include "threading/mutex.h" +#include "threading/mutex_auto_lock.h" #include "config.h" #ifdef _MSC_VER @@ -229,7 +229,7 @@ void DebugStack::print(std::ostream &os, bool everything) } std::map g_debug_stacks; -JMutex g_debug_stacks_mutex; +Mutex g_debug_stacks_mutex; void debug_stacks_init() { @@ -237,7 +237,7 @@ void debug_stacks_init() void debug_stacks_print_to(std::ostream &os) { - JMutexAutoLock lock(g_debug_stacks_mutex); + MutexAutoLock lock(g_debug_stacks_mutex); os<<"Debug stacks:"<::iterator n; n = g_debug_stacks.find(threadid); @@ -307,7 +307,7 @@ DebugStacker::DebugStacker(const char *text) DebugStacker::~DebugStacker() { - JMutexAutoLock lock(g_debug_stacks_mutex); + MutexAutoLock lock(g_debug_stacks_mutex); if(m_overflowed == true) return; diff --git a/src/emerge.cpp b/src/emerge.cpp index d6bda731a..084470783 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server.h" #include #include -#include "jthread/jevent.h" +#include "threading/event.h" #include "map.h" #include "environment.h" #include "util/container.h" @@ -59,7 +59,7 @@ MapgenDesc reg_mapgens[] = { {"singlenode", new MapgenFactorySinglenode}, }; -class EmergeThread : public JThread +class EmergeThread : public Thread { public: Server *m_server; @@ -73,7 +73,6 @@ public: std::queue blockqueue; EmergeThread(Server *server, int ethreadid): - JThread(), m_server(server), map(NULL), emerge(NULL), @@ -81,9 +80,10 @@ public: enable_mapgen_debug_info(false), id(ethreadid) { + name = "Emerge-" + itos(id); } - void *Thread(); + void *run(); bool popBlockEmerge(v3s16 *pos, u8 *flags); bool getBlockOrStartGen(v3s16 p, MapBlock **b, BlockMakeData *data, bool allow_generate); @@ -112,7 +112,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef) // some other misc thread s16 nthreads = 0; if (!g_settings->getS16NoEx("num_emerge_threads", nthreads)) - nthreads = porting::getNumberOfProcessors() - 2; + nthreads = Thread::getNumberOfProcessors() - 2; if (nthreads < 1) nthreads = 1; @@ -141,9 +141,9 @@ EmergeManager::~EmergeManager() { for (u32 i = 0; i != emergethread.size(); i++) { if (threads_active) { - emergethread[i]->Stop(); + emergethread[i]->stop(); emergethread[i]->qevent.signal(); - emergethread[i]->Wait(); + emergethread[i]->wait(); } delete emergethread[i]; delete mapgen[i]; @@ -196,7 +196,7 @@ void EmergeManager::initMapgens() Mapgen *EmergeManager::getCurrentMapgen() { for (u32 i = 0; i != emergethread.size(); i++) { - if (emergethread[i]->IsSameThread()) + if (emergethread[i]->isSameThread()) return emergethread[i]->mapgen; } @@ -210,7 +210,7 @@ void EmergeManager::startThreads() return; for (u32 i = 0; i != emergethread.size(); i++) - emergethread[i]->Start(); + emergethread[i]->start(); threads_active = true; } @@ -223,13 +223,13 @@ void EmergeManager::stopThreads() // Request thread stop in parallel for (u32 i = 0; i != emergethread.size(); i++) { - emergethread[i]->Stop(); + emergethread[i]->stop(); emergethread[i]->qevent.signal(); } // Then do the waiting for each for (u32 i = 0; i != emergethread.size(); i++) - emergethread[i]->Wait(); + emergethread[i]->wait(); threads_active = false; } @@ -247,7 +247,7 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate flags |= BLOCK_EMERGE_ALLOWGEN; { - JMutexAutoLock queuelock(queuemutex); + MutexAutoLock queuelock(queuemutex); count = blocks_enqueued.size(); if (count >= qlimit_total) @@ -360,7 +360,7 @@ MapgenSpecificParams *EmergeManager::createMapgenParams(const std::string &mgnam bool EmergeThread::popBlockEmerge(v3s16 *pos, u8 *flags) { std::map::iterator iter; - JMutexAutoLock queuelock(emerge->queuemutex); + MutexAutoLock queuelock(emerge->queuemutex); if (blockqueue.empty()) return false; @@ -390,7 +390,7 @@ bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, { v2s16 p2d(p.X, p.Z); //envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire - JMutexAutoLock envlock(m_server->m_env_mutex); + MutexAutoLock envlock(m_server->m_env_mutex); // Load sector if it isn't loaded if (map->getSectorNoGenerateNoEx(p2d) == NULL) @@ -418,10 +418,8 @@ bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, } -void *EmergeThread::Thread() +void *EmergeThread::run() { - ThreadStarted(); - log_register_thread("EmergeThread" + itos(id)); DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER @@ -434,9 +432,7 @@ void *EmergeThread::Thread() mapgen = emerge->mapgen[id]; enable_mapgen_debug_info = emerge->mapgen_debug_info; - porting::setThreadName("EmergeThread"); - - while (!StopRequested()) + while (!stopRequested()) try { if (!popBlockEmerge(&p, &flags)) { qevent.wait(); @@ -471,7 +467,7 @@ void *EmergeThread::Thread() { //envlock: usually 0ms, but can take either 30 or 400ms to acquire - JMutexAutoLock envlock(m_server->m_env_mutex); + MutexAutoLock envlock(m_server->m_env_mutex); ScopeProfiler sp(g_profiler, "EmergeThread: after " "Mapgen::makeChunk (envlock)", SPT_AVG); @@ -538,7 +534,7 @@ void *EmergeThread::Thread() } { - JMutexAutoLock queuelock(emerge->queuemutex); + MutexAutoLock queuelock(emerge->queuemutex); while (!blockqueue.empty()) { v3s16 p = blockqueue.front(); @@ -555,6 +551,5 @@ void *EmergeThread::Thread() } END_DEBUG_EXCEPTION_HANDLER(errorstream) - log_deregister_thread(); return NULL; } diff --git a/src/emerge.h b/src/emerge.h index 1653199ec..2ed21bb06 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -86,7 +86,7 @@ public: std::set gen_notify_on_deco_ids; //// Block emerge queue data structures - JMutex queuemutex; + Mutex queuemutex; std::map blocks_enqueued; std::map peer_queue_count; diff --git a/src/environment.cpp b/src/environment.cpp index dbbfc6f1f..baeb3a3c6 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -44,7 +44,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map.h" #include "emerge.h" #include "util/serialize.h" -#include "jthread/jmutexautolock.h" +#include "threading/mutex_auto_lock.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -204,34 +204,34 @@ u32 Environment::getDayNightRatio() void Environment::setTimeOfDaySpeed(float speed) { - JMutexAutoLock(this->m_timeofday_lock); + MutexAutoLock(this->m_timeofday_lock); m_time_of_day_speed = speed; } float Environment::getTimeOfDaySpeed() { - JMutexAutoLock(this->m_timeofday_lock); + MutexAutoLock(this->m_timeofday_lock); float retval = m_time_of_day_speed; return retval; } void Environment::setTimeOfDay(u32 time) { - JMutexAutoLock(this->m_time_lock); + MutexAutoLock(this->m_time_lock); m_time_of_day = time; m_time_of_day_f = (float)time / 24000.0; } u32 Environment::getTimeOfDay() { - JMutexAutoLock(this->m_time_lock); + MutexAutoLock(this->m_time_lock); u32 retval = m_time_of_day; return retval; } float Environment::getTimeOfDayF() { - JMutexAutoLock(this->m_time_lock); + MutexAutoLock(this->m_time_lock); float retval = m_time_of_day_f; return retval; } diff --git a/src/environment.h b/src/environment.h index c70694316..6ace12671 100644 --- a/src/environment.h +++ b/src/environment.h @@ -39,7 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/numeric.h" #include "mapnode.h" #include "mapblock.h" -#include "jthread/jmutex.h" +#include "threading/mutex.h" #include "network/networkprotocol.h" // for AccessDeniedCode class ServerEnvironment; @@ -127,8 +127,8 @@ protected: bool m_cache_enable_shaders; private: - JMutex m_timeofday_lock; - JMutex m_time_lock; + Mutex m_timeofday_lock; + Mutex m_time_lock; }; diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index 56cdad2b1..6040b1b3b 100644 --- a/src/httpfetch.cpp +++ b/src/httpfetch.cpp @@ -25,7 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#include "jthread/jevent.h" +#include "threading/event.h" #include "config.h" #include "exceptions.h" #include "debug.h" @@ -35,7 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "version.h" #include "settings.h" -JMutex g_httpfetch_mutex; +Mutex g_httpfetch_mutex; std::map > g_httpfetch_results; HTTPFetchRequest::HTTPFetchRequest() @@ -55,7 +55,7 @@ static void httpfetch_deliver_result(const HTTPFetchResult &fetch_result) { unsigned long caller = fetch_result.caller; if (caller != HTTPFETCH_DISCARD) { - JMutexAutoLock lock(g_httpfetch_mutex); + MutexAutoLock lock(g_httpfetch_mutex); g_httpfetch_results[caller].push(fetch_result); } } @@ -64,7 +64,7 @@ static void httpfetch_request_clear(unsigned long caller); unsigned long httpfetch_caller_alloc() { - JMutexAutoLock lock(g_httpfetch_mutex); + MutexAutoLock lock(g_httpfetch_mutex); // Check each caller ID except HTTPFETCH_DISCARD const unsigned long discard = HTTPFETCH_DISCARD; @@ -91,14 +91,14 @@ void httpfetch_caller_free(unsigned long caller) httpfetch_request_clear(caller); if (caller != HTTPFETCH_DISCARD) { - JMutexAutoLock lock(g_httpfetch_mutex); + MutexAutoLock lock(g_httpfetch_mutex); g_httpfetch_results.erase(caller); } } bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result) { - JMutexAutoLock lock(g_httpfetch_mutex); + MutexAutoLock lock(g_httpfetch_mutex); // Check that caller exists std::map >::iterator @@ -390,7 +390,7 @@ HTTPFetchOngoing::~HTTPFetchOngoing() } -class CurlFetchThread : public JThread +class CurlFetchThread : public Thread { protected: enum RequestType { @@ -414,7 +414,8 @@ protected: std::list m_queued_fetches; public: - CurlFetchThread(int parallel_limit) + CurlFetchThread(int parallel_limit) : + Thread("CurlFetch") { if (parallel_limit >= 1) m_parallel_limit = parallel_limit; @@ -613,14 +614,10 @@ protected: } } - void * Thread() + void *run() { - ThreadStarted(); - log_register_thread("CurlFetchThread"); DSTACK(__FUNCTION_NAME); - porting::setThreadName("CurlFetchThread"); - CurlHandlePool pool; m_multi = curl_multi_init(); @@ -631,7 +628,7 @@ protected: FATAL_ERROR_IF(!m_all_ongoing.empty(), "Expected empty"); - while (!StopRequested()) { + while (!stopRequested()) { BEGIN_DEBUG_EXCEPTION_HANDLER /* @@ -719,9 +716,9 @@ void httpfetch_cleanup() { verbosestream<<"httpfetch_cleanup: cleaning up"<Stop(); + g_httpfetch_thread->stop(); g_httpfetch_thread->requestWakeUp(); - g_httpfetch_thread->Wait(); + g_httpfetch_thread->wait(); delete g_httpfetch_thread; curl_global_cleanup(); @@ -730,18 +727,17 @@ void httpfetch_cleanup() void httpfetch_async(const HTTPFetchRequest &fetch_request) { g_httpfetch_thread->requestFetch(fetch_request); - if (!g_httpfetch_thread->IsRunning()) - g_httpfetch_thread->Start(); + if (!g_httpfetch_thread->isRunning()) + g_httpfetch_thread->start(); } static void httpfetch_request_clear(unsigned long caller) { - if (g_httpfetch_thread->IsRunning()) { + if (g_httpfetch_thread->isRunning()) { Event event; g_httpfetch_thread->requestClear(caller, &event); event.wait(); - } - else { + } else { g_httpfetch_thread->requestClear(caller, NULL); } } diff --git a/src/jthread/CMakeLists.txt b/src/jthread/CMakeLists.txt deleted file mode 100644 index cebb35caa..000000000 --- a/src/jthread/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -if(UNIX) - set(THREAD_SYS_DIR pthread) -else() - set(THREAD_SYS_DIR win32) -endif() - -set(SRC_PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/${THREAD_SYS_DIR}) -set(JTHREAD_SRCS - ${SRC_PREFIX}/jmutex.cpp - ${SRC_PREFIX}/jthread.cpp - ${SRC_PREFIX}/jsemaphore.cpp - ${SRC_PREFIX}/jevent.cpp - PARENT_SCOPE) - diff --git a/src/jthread/LICENSE.MIT b/src/jthread/LICENSE.MIT deleted file mode 100644 index 2aa4fd57b..000000000 --- a/src/jthread/LICENSE.MIT +++ /dev/null @@ -1,20 +0,0 @@ -The license of JThread: - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. - diff --git a/src/jthread/jevent.h b/src/jthread/jevent.h deleted file mode 100644 index 9ea7ebde8..000000000 --- a/src/jthread/jevent.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ - -#ifndef JEVENT_H_ -#define JEVENT_H_ - -#ifdef _WIN32 -#include -#elif defined(__MACH__) && defined(__APPLE__) -#include -#include -#include -#include -#else -#include -#endif - - -class Event { -#ifdef _WIN32 - HANDLE hEvent; -#elif defined(__MACH__) && defined(__APPLE__) - semaphore_t sem; -#else - sem_t sem; -#endif - -public: - Event(); - ~Event(); - void wait(); - void signal(); -}; - -#endif /* JEVENT_H_ */ diff --git a/src/jthread/jmutex.h b/src/jthread/jmutex.h deleted file mode 100644 index e57cd8a43..000000000 --- a/src/jthread/jmutex.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ - -#ifndef JMUTEX_H - -#define JMUTEX_H - -#if (defined(WIN32) || defined(_WIN32_WCE)) - #ifndef _WIN32_WINNT - #define _WIN32_WINNT 0x0501 - #endif - #ifndef _WIN32_WCE - #include - #endif // _WIN32_WCE - #include - #include - // CriticalSection is way faster than the alternative - #define JMUTEX_CRITICALSECTION -#else // using pthread - #include -#endif // WIN32 - -#define ERR_JMUTEX_ALREADYINIT -1 -#define ERR_JMUTEX_NOTINIT -2 -#define ERR_JMUTEX_CANTCREATEMUTEX -3 - -class JMutex -{ -public: - JMutex(); - ~JMutex(); - int Lock(); - int Unlock(); - -private: -#if (defined(WIN32) || defined(_WIN32_WCE)) -#ifdef JMUTEX_CRITICALSECTION - CRITICAL_SECTION mutex; -#else // Use standard mutex - HANDLE mutex; -#endif // JMUTEX_CRITICALSECTION -#else // pthread mutex - pthread_mutex_t mutex; - - bool IsLocked() { - if (pthread_mutex_trylock(&mutex)) { - pthread_mutex_unlock(&mutex); - return true; - } - return false; - } -#endif // WIN32 -}; - -#endif // JMUTEX_H diff --git a/src/jthread/jmutexautolock.h b/src/jthread/jmutexautolock.h deleted file mode 100644 index 6020a5c33..000000000 --- a/src/jthread/jmutexautolock.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ - -#ifndef JMUTEXAUTOLOCK_H - -#define JMUTEXAUTOLOCK_H - -#include "jmutex.h" - -class JMutexAutoLock -{ -public: - JMutexAutoLock(JMutex &m) : mutex(m) { mutex.Lock(); } - ~JMutexAutoLock() { mutex.Unlock(); } -private: - JMutex &mutex; -}; - -#endif // JMUTEXAUTOLOCK_H diff --git a/src/jthread/jsemaphore.h b/src/jthread/jsemaphore.h deleted file mode 100644 index 32e9bc2f2..000000000 --- a/src/jthread/jsemaphore.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -Minetest -Copyright (C) 2013 sapier, < sapier AT gmx DOT net > - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#ifndef JSEMAPHORE_H_ -#define JSEMAPHORE_H_ - -#if defined(WIN32) -#include -#include -#define MAX_SEMAPHORE_COUNT 1024 -#elif defined(__MACH__) && defined(__APPLE__) -#include -#include -#include -#include -#include -#include -#include -#else -#include -#include -#endif - -class JSemaphore { -public: - JSemaphore(); - ~JSemaphore(); - JSemaphore(int initval); - - void Post(); - void Wait(); - bool Wait(unsigned int time_ms); - - int GetValue(); - -private: -#if defined(WIN32) - HANDLE m_hSemaphore; -#elif defined(__MACH__) && defined(__APPLE__) - semaphore_t m_semaphore; - int semcount; -#else - sem_t m_semaphore; -#endif -}; - - -#endif /* JSEMAPHORE_H_ */ diff --git a/src/jthread/jthread.h b/src/jthread/jthread.h deleted file mode 100644 index 89743a3e3..000000000 --- a/src/jthread/jthread.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ - -#ifndef JTHREAD_H -#define JTHREAD_H - -#if __cplusplus >= 201103L -#include -#endif - -#include "jthread/jmutex.h" - -#define ERR_JTHREAD_CANTINITMUTEX -1 -#define ERR_JTHREAD_CANTSTARTTHREAD -2 -#define ERR_JTHREAD_THREADFUNCNOTSET -3 -#define ERR_JTHREAD_NOTRUNNING -4 -#define ERR_JTHREAD_ALREADYRUNNING -5 - -class JThread -{ -public: - JThread(); - virtual ~JThread(); - int Start(); - inline void Stop() - { requeststop = true; } - int Kill(); - virtual void *Thread() = 0; - inline bool IsRunning() - { return running; } - inline bool StopRequested() - { return requeststop; } - void *GetReturnValue(); - bool IsSameThread(); - - /* - * Wait for thread to finish - * Note: this does not stop a thread you have to do this on your own - * WARNING: never ever call this on a thread not started or already killed! - */ - void Wait(); -protected: - void ThreadStarted(); -private: - -#if (defined(WIN32) || defined(_WIN32_WCE)) -#ifdef _WIN32_WCE - DWORD threadid; - static DWORD WINAPI TheThread(void *param); -#else - static UINT __stdcall TheThread(void *param); - UINT threadid; -#endif // _WIN32_WCE - HANDLE threadhandle; -#else // pthread type threads - static void *TheThread(void *param); - - pthread_t threadid; - - /* - * reading and writing bool values is atomic on all relevant architectures - * ( x86 + arm ). No need to waste time for locking here. - * once C++11 is supported we can tell compiler to handle cpu caches correct - * too. This should cause additional improvement (and silence thread - * concurrency check tools. - */ -#if __cplusplus >= 201103L - std::atomic_bool started; -#else - bool started; -#endif -#endif // WIN32 - void *retval; - /* - * reading and writing bool values is atomic on all relevant architectures - * ( x86 + arm ). No need to waste time for locking here. - * once C++11 is supported we can tell compiler to handle cpu caches correct - * too. This should cause additional improvement (and silence thread - * concurrency check tools. - */ -#if __cplusplus >= 201103L - std::atomic_bool running; - std::atomic_bool requeststop; -#else - bool running; - bool requeststop; -#endif - - JMutex continuemutex,continuemutex2; -}; - -#endif // JTHREAD_H - diff --git a/src/jthread/pthread/jevent.cpp b/src/jthread/pthread/jevent.cpp deleted file mode 100644 index e1d40f4c1..000000000 --- a/src/jthread/pthread/jevent.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ -#include -#include "jthread/jevent.h" - -#define UNUSED(expr) do { (void)(expr); } while (0) - -#if defined(__MACH__) && defined(__APPLE__) -#undef sem_t -#define sem_t semaphore_t -#undef sem_init -#define sem_init(s, p, c) semaphore_create(mach_task_self(), (s), 0, (c)) -#undef sem_wait -#define sem_wait(s) semaphore_wait(*(s)) -#undef sem_post -#define sem_post(s) semaphore_signal(*(s)) -#undef sem_destroy -#define sem_destroy(s) semaphore_destroy(mach_task_self(), *(s)) -#endif - -Event::Event() { - int sem_init_retval = sem_init(&sem, 0, 0); - assert(sem_init_retval == 0); - UNUSED(sem_init_retval); -} - -Event::~Event() { - int sem_destroy_retval = sem_destroy(&sem); - assert(sem_destroy_retval == 0); - UNUSED(sem_destroy_retval); -} - -void Event::wait() { - int sem_wait_retval = sem_wait(&sem); - assert(sem_wait_retval == 0); - UNUSED(sem_wait_retval); -} - -void Event::signal() { - int sem_post_retval = sem_post(&sem); - assert(sem_post_retval == 0); - UNUSED(sem_post_retval); -} diff --git a/src/jthread/pthread/jmutex.cpp b/src/jthread/pthread/jmutex.cpp deleted file mode 100644 index 0551b9728..000000000 --- a/src/jthread/pthread/jmutex.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ -#include -#include "jthread/jmutex.h" -#define UNUSED(expr) do { (void)(expr); } while (0) -JMutex::JMutex() -{ - int mutex_init_retval = pthread_mutex_init(&mutex,NULL); - assert( mutex_init_retval == 0 ); - UNUSED(mutex_init_retval); -} - -JMutex::~JMutex() -{ - int mutex_dextroy_retval = pthread_mutex_destroy(&mutex); - assert( mutex_dextroy_retval == 0 ); - UNUSED(mutex_dextroy_retval); -} - -int JMutex::Lock() -{ - int mutex_lock_retval = pthread_mutex_lock(&mutex); - assert( mutex_lock_retval == 0 ); - return mutex_lock_retval; - UNUSED(mutex_lock_retval); -} - -int JMutex::Unlock() -{ - int mutex_unlock_retval = pthread_mutex_unlock(&mutex); - assert( mutex_unlock_retval == 0 ); - return mutex_unlock_retval; - UNUSED(mutex_unlock_retval); -} diff --git a/src/jthread/pthread/jsemaphore.cpp b/src/jthread/pthread/jsemaphore.cpp deleted file mode 100644 index 15281ba64..000000000 --- a/src/jthread/pthread/jsemaphore.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* -Minetest -Copyright (C) 2013 sapier, < sapier AT gmx DOT net > - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include -#include -#include -#include "jthread/jsemaphore.h" -#if defined(__MACH__) && defined(__APPLE__) -#include -#endif - -#define UNUSED(expr) do { (void)(expr); } while (0) - -#if defined(__MACH__) && defined(__APPLE__) -#undef sem_t -#undef sem_init -#undef sem_wait -#undef sem_post -#undef sem_destroy -#define sem_t semaphore_t -#define sem_init(s, p, c) semaphore_create(mach_task_self(), (s), 0, (c)) -#define sem_wait(s) semaphore_wait(*(s)) -#define sem_post(s) semaphore_signal(*(s)) -#define sem_destroy(s) semaphore_destroy(mach_task_self(), *(s)) -pthread_mutex_t semcount_mutex; -#endif - -JSemaphore::JSemaphore() { - int sem_init_retval = sem_init(&m_semaphore,0,0); - assert(sem_init_retval == 0); - UNUSED(sem_init_retval); -#if defined(__MACH__) && defined(__APPLE__) - semcount = 0; -#endif -} - -JSemaphore::~JSemaphore() { - int sem_destroy_retval = sem_destroy(&m_semaphore); -#ifdef __ANDROID__ -// WORKAROUND for broken bionic semaphore implementation! - assert( - (sem_destroy_retval == 0) || - (errno == EBUSY) - ); -#else - assert(sem_destroy_retval == 0); -#endif - UNUSED(sem_destroy_retval); -} - -JSemaphore::JSemaphore(int initval) { - int sem_init_retval = sem_init(&m_semaphore,0,initval); - assert(sem_init_retval == 0); - UNUSED(sem_init_retval); -} - -void JSemaphore::Post() { - int sem_post_retval = sem_post(&m_semaphore); - assert(sem_post_retval == 0); - UNUSED(sem_post_retval); -#if defined(__MACH__) && defined(__APPLE__) - pthread_mutex_lock(&semcount_mutex); - semcount++; - pthread_mutex_unlock(&semcount_mutex); -#endif -} - -void JSemaphore::Wait() { - int sem_wait_retval = sem_wait(&m_semaphore); - assert(sem_wait_retval == 0); - UNUSED(sem_wait_retval); -#if defined(__MACH__) && defined(__APPLE__) - pthread_mutex_lock(&semcount_mutex); - semcount--; - pthread_mutex_unlock(&semcount_mutex); -#endif -} - -bool JSemaphore::Wait(unsigned int time_ms) { -#if defined(__MACH__) && defined(__APPLE__) - mach_timespec_t waittime; - waittime.tv_sec = time_ms / 1000; - waittime.tv_nsec = 1000000 * (time_ms % 1000); -#else - struct timespec waittime; -#endif - struct timeval now; - - if (gettimeofday(&now, NULL) == -1) { - assert("Unable to get time by clock_gettime!" == 0); - return false; - } - -#if !(defined(__MACH__) && defined(__APPLE__)) - waittime.tv_nsec = ((time_ms % 1000) * 1000 * 1000) + (now.tv_usec * 1000); - waittime.tv_sec = (time_ms / 1000) + (waittime.tv_nsec / (1000*1000*1000)) + now.tv_sec; - waittime.tv_nsec %= 1000*1000*1000; -#endif - - errno = 0; -#if defined(__MACH__) && defined(__APPLE__) - int sem_wait_retval = semaphore_timedwait(m_semaphore, waittime); - if (sem_wait_retval == KERN_OPERATION_TIMED_OUT) { - errno = ETIMEDOUT; - } else if (sem_wait_retval == KERN_ABORTED) { - errno = EINTR; - } else if (sem_wait_retval != 0) { - errno = EINVAL; - } -#else - int sem_wait_retval = sem_timedwait(&m_semaphore, &waittime); -#endif - - if (sem_wait_retval == 0) - { -#if defined(__MACH__) && defined(__APPLE__) - pthread_mutex_lock(&semcount_mutex); - semcount--; - pthread_mutex_unlock(&semcount_mutex); -#endif - return true; - } - else { - assert((errno == ETIMEDOUT) || (errno == EINTR)); - return false; - } - return sem_wait_retval == 0 ? true : false; -} - -int JSemaphore::GetValue() { - int retval = 0; -#if defined(__MACH__) && defined(__APPLE__) - pthread_mutex_lock(&semcount_mutex); - retval = semcount; - pthread_mutex_unlock(&semcount_mutex); -#else - sem_getvalue(&m_semaphore, &retval); -#endif - return retval; -} - diff --git a/src/jthread/pthread/jthread.cpp b/src/jthread/pthread/jthread.cpp deleted file mode 100644 index 414d8fde5..000000000 --- a/src/jthread/pthread/jthread.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ - -#include "jthread/jthread.h" -#include -#include -#include -#include - -#define UNUSED(expr) do { (void)(expr); } while (0) - -JThread::JThread() -{ - retval = NULL; - requeststop = false; - running = false; - started = false; -} - -JThread::~JThread() -{ - Kill(); -} - -void JThread::Wait() { - void* status; - if (started) { - int pthread_join_retval = pthread_join(threadid,&status); - assert(pthread_join_retval == 0); - UNUSED(pthread_join_retval); - started = false; - } -} - -int JThread::Start() -{ - int status; - - if (running) - { - return ERR_JTHREAD_ALREADYRUNNING; - } - requeststop = false; - - pthread_attr_t attr; - pthread_attr_init(&attr); - //pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); - - continuemutex.Lock(); - status = pthread_create(&threadid,&attr,TheThread,this); - pthread_attr_destroy(&attr); - if (status != 0) - { - continuemutex.Unlock(); - return ERR_JTHREAD_CANTSTARTTHREAD; - } - - /* Wait until 'running' is set */ - - while (!running) - { - struct timespec req,rem; - - req.tv_sec = 0; - req.tv_nsec = 1000000; - nanosleep(&req,&rem); - } - started = true; - - continuemutex.Unlock(); - - continuemutex2.Lock(); - continuemutex2.Unlock(); - return 0; -} - -int JThread::Kill() -{ - void* status; - if (!running) - { - if (started) { - int pthread_join_retval = pthread_join(threadid,&status); - assert(pthread_join_retval == 0); - UNUSED(pthread_join_retval); - started = false; - } - return ERR_JTHREAD_NOTRUNNING; - } -#ifdef __ANDROID__ - pthread_kill(threadid, SIGKILL); -#else - pthread_cancel(threadid); -#endif - if (started) { - int pthread_join_retval = pthread_join(threadid,&status); - assert(pthread_join_retval == 0); - UNUSED(pthread_join_retval); - started = false; - } - running = false; - return 0; -} - -void *JThread::GetReturnValue() -{ - void *val; - - if (running) { - val = NULL; - } else { - val = retval; - } - - return val; -} - -bool JThread::IsSameThread() -{ - return pthread_equal(pthread_self(), threadid); -} - -void *JThread::TheThread(void *param) -{ - JThread *jthread = (JThread *)param; - - jthread->continuemutex2.Lock(); - jthread->running = true; - - jthread->continuemutex.Lock(); - jthread->continuemutex.Unlock(); - - jthread->Thread(); - - jthread->running = false; - - return NULL; -} - -void JThread::ThreadStarted() -{ - continuemutex2.Unlock(); -} - diff --git a/src/jthread/win32/jevent.cpp b/src/jthread/win32/jevent.cpp deleted file mode 100644 index 67b468f01..000000000 --- a/src/jthread/win32/jevent.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ -#include "jthread/jevent.h" - -Event::Event() { - hEvent = CreateEvent(NULL, 0, 0, NULL); -} - -Event::~Event() { - CloseHandle(hEvent); -} - -void Event::wait() { - WaitForSingleObject(hEvent, INFINITE); -} - -void Event::signal() { - SetEvent(hEvent); -} diff --git a/src/jthread/win32/jmutex.cpp b/src/jthread/win32/jmutex.cpp deleted file mode 100644 index b9f5e0e73..000000000 --- a/src/jthread/win32/jmutex.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ -#include -#include "jthread/jmutex.h" - -JMutex::JMutex() -{ -#ifdef JMUTEX_CRITICALSECTION - InitializeCriticalSection(&mutex); -#else - mutex = CreateMutex(NULL,FALSE,NULL); - assert(mutex != NULL); -#endif // JMUTEX_CRITICALSECTION -} - -JMutex::~JMutex() -{ -#ifdef JMUTEX_CRITICALSECTION - DeleteCriticalSection(&mutex); -#else - CloseHandle(mutex); -#endif // JMUTEX_CRITICALSECTION -} - -int JMutex::Lock() -{ -#ifdef JMUTEX_CRITICALSECTION - EnterCriticalSection(&mutex); -#else - WaitForSingleObject(mutex,INFINITE); -#endif // JMUTEX_CRITICALSECTION - return 0; -} - -int JMutex::Unlock() -{ -#ifdef JMUTEX_CRITICALSECTION - LeaveCriticalSection(&mutex); -#else - ReleaseMutex(mutex); -#endif // JMUTEX_CRITICALSECTION - return 0; -} - diff --git a/src/jthread/win32/jsemaphore.cpp b/src/jthread/win32/jsemaphore.cpp deleted file mode 100644 index 27a11e819..000000000 --- a/src/jthread/win32/jsemaphore.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -Minetest -Copyright (C) 2013 sapier, < sapier AT gmx DOT net > - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ -#include "jthread/jsemaphore.h" - -JSemaphore::JSemaphore() { - m_hSemaphore = CreateSemaphore( - 0, - 0, - MAX_SEMAPHORE_COUNT, - 0); -} - -JSemaphore::~JSemaphore() { - CloseHandle(m_hSemaphore); -} - -JSemaphore::JSemaphore(int initval) { - m_hSemaphore = CreateSemaphore( - 0, - initval, - MAX_SEMAPHORE_COUNT, - 0); -} - -void JSemaphore::Post() { - ReleaseSemaphore( - m_hSemaphore, - 1, - 0); -} - -void JSemaphore::Wait() { - WaitForSingleObject( - m_hSemaphore, - INFINITE); -} - -bool JSemaphore::Wait(unsigned int time_ms) { - unsigned int retval = WaitForSingleObject( - m_hSemaphore, - time_ms); - - if (retval == WAIT_OBJECT_0) - { - return true; - } - else { - assert(retval == WAIT_TIMEOUT); - return false; - } -} - -typedef LONG (NTAPI *_NtQuerySemaphore)( - HANDLE SemaphoreHandle, - DWORD SemaphoreInformationClass, - PVOID SemaphoreInformation, - ULONG SemaphoreInformationLength, - PULONG ReturnLength OPTIONAL -); - -typedef struct _SEMAPHORE_BASIC_INFORMATION { - ULONG CurrentCount; - ULONG MaximumCount; -} SEMAPHORE_BASIC_INFORMATION; - -/* Note: this will only work as long as jthread is directly linked to application */ -/* it's gonna fail if someone tries to build jthread as dll */ -static _NtQuerySemaphore NtQuerySemaphore = - (_NtQuerySemaphore) - GetProcAddress - (GetModuleHandle ("ntdll.dll"), "NtQuerySemaphore"); - -int JSemaphore::GetValue() { - SEMAPHORE_BASIC_INFORMATION BasicInfo; - LONG retval; - - assert(NtQuerySemaphore); - - retval = NtQuerySemaphore (m_hSemaphore, 0, - &BasicInfo, sizeof (SEMAPHORE_BASIC_INFORMATION), NULL); - - if (retval == ERROR_SUCCESS) - return BasicInfo.CurrentCount; - - assert("unable to read semaphore count" == 0); - return 0; -} - diff --git a/src/jthread/win32/jthread.cpp b/src/jthread/win32/jthread.cpp deleted file mode 100755 index b523d664c..000000000 --- a/src/jthread/win32/jthread.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - - This file is a part of the JThread package, which contains some object- - oriented thread wrappers for different thread implementations. - - Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - -*/ - -#include "jthread/jthread.h" -#include -#define UNUSED(expr) do { (void)(expr); } while (0) -#ifndef _WIN32_WCE - #include -#endif // _WIN32_WCE - -JThread::JThread() -{ - retval = NULL; - requeststop = false; - running = false; -} - -JThread::~JThread() -{ - Kill(); -} - -void JThread::Wait() { - if (running) - { - WaitForSingleObject(threadhandle, INFINITE); - } -} - -int JThread::Start() -{ - if (running) - { - return ERR_JTHREAD_ALREADYRUNNING; - } - requeststop = false; - - continuemutex.Lock(); -#ifndef _WIN32_WCE - threadhandle = (HANDLE)_beginthreadex(NULL,0,TheThread,this,0,&threadid); -#else - threadhandle = CreateThread(NULL,0,TheThread,this,0,&threadid); -#endif // _WIN32_WCE - if (threadhandle == NULL) - { - continuemutex.Unlock(); - return ERR_JTHREAD_CANTSTARTTHREAD; - } - - /* Wait until 'running' is set */ - while (!running) - { - Sleep(1); - } - - continuemutex.Unlock(); - - continuemutex2.Lock(); - continuemutex2.Unlock(); - - return 0; -} - -int JThread::Kill() -{ - if (!running) - { - return ERR_JTHREAD_NOTRUNNING; - } - TerminateThread(threadhandle,0); - CloseHandle(threadhandle); - running = false; - return 0; -} - -void *JThread::GetReturnValue() -{ - void *val; - - if (running) { - val = NULL; - } else { - val = retval; - } - return val; -} - -bool JThread::IsSameThread() -{ - return GetCurrentThreadId() == threadid; -} - -#ifndef _WIN32_WCE -UINT __stdcall JThread::TheThread(void *param) -#else -DWORD WINAPI JThread::TheThread(void *param) -#endif // _WIN32_WCE -{ - JThread *jthread; - void *ret; - - jthread = (JThread *)param; - - jthread->continuemutex2.Lock(); - jthread->running = true; - - jthread->continuemutex.Lock(); - jthread->continuemutex.Unlock(); - - ret = jthread->Thread(); - - jthread->running = false; - jthread->retval = ret; - CloseHandle(jthread->threadhandle); - return 0; -} - -void JThread::ThreadStarted() -{ - continuemutex2.Unlock(); -} - diff --git a/src/log.cpp b/src/log.cpp index e6d80db34..9dc574d01 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "threads.h" -#include "jthread/jmutexautolock.h" +#include "threading/mutex_auto_lock.h" #include "debug.h" #include "gettime.h" #include "porting.h" @@ -54,8 +54,8 @@ unsigned int android_log_level_mapping[] = { #endif std::vector log_outputs[LMT_NUM_VALUES]; -std::map log_threadnames; -JMutex log_threadnamemutex; +std::map log_thread_names; +Mutex log_thread_name_mutex; void log_add_output(ILogOutput *out, enum LogMessageLevel lev) { @@ -86,7 +86,7 @@ void log_remove_output(ILogOutput *out) void log_set_lev_silence(enum LogMessageLevel lev, bool silence) { - JMutexAutoLock lock(log_threadnamemutex); + MutexAutoLock lock(log_thread_name_mutex); for (std::vector::iterator it = log_outputs[lev].begin(); it != log_outputs[lev].end(); ++it) { @@ -98,17 +98,17 @@ void log_set_lev_silence(enum LogMessageLevel lev, bool silence) void log_register_thread(const std::string &name) { threadid_t id = get_current_thread_id(); - JMutexAutoLock lock(log_threadnamemutex); + MutexAutoLock lock(log_thread_name_mutex); - log_threadnames[id] = name; + log_thread_names[id] = name; } void log_deregister_thread() { threadid_t id = get_current_thread_id(); - JMutexAutoLock lock(log_threadnamemutex); + MutexAutoLock lock(log_thread_name_mutex); - log_threadnames.erase(id); + log_thread_names.erase(id); } static std::string get_lev_string(enum LogMessageLevel lev) @@ -130,11 +130,11 @@ static std::string get_lev_string(enum LogMessageLevel lev) void log_printline(enum LogMessageLevel lev, const std::string &text) { - JMutexAutoLock lock(log_threadnamemutex); + MutexAutoLock lock(log_thread_name_mutex); std::string threadname = "(unknown thread)"; std::map::const_iterator i; - i = log_threadnames.find(get_current_thread_id()); - if(i != log_threadnames.end()) + i = log_thread_names.find(get_current_thread_id()); + if(i != log_thread_names.end()) threadname = i->second; std::string levelname = get_lev_string(lev); std::ostringstream os(std::ios_base::binary); diff --git a/src/main.cpp b/src/main.cpp index 1d73b4025..56ba7fac9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -153,7 +153,7 @@ int main(int argc, char *argv[]) log_add_output_maxlev(&main_stderr_log_out, LMT_ACTION); log_add_output_all_levs(&main_dstream_no_stderr_log_out); - log_register_thread("main"); + log_register_thread("Main"); Settings cmd_args; bool cmd_args_ok = get_cmdline_opts(argc, argv, &cmd_args); diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 43057f3a5..1f84c4d7b 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -96,7 +96,7 @@ MapBlock::~MapBlock() { #ifndef SERVER { - //JMutexAutoLock lock(mesh_mutex); + //MutexAutoLock lock(mesh_mutex); if(mesh) { diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index 0d6693929..f11a71518 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -139,7 +139,7 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) #if 0 printf("Decoration at (%d %d %d) cut off\n", x, y, z); //add to queue - JMutexAutoLock cutofflock(cutoff_mutex); + MutexAutoLock cutofflock(cutoff_mutex); cutoffs.push_back(CutoffData(x, y, z, height)); #endif } @@ -172,7 +172,7 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) // Copy over the cutoffs we're interested in so we don't needlessly hold a lock { - JMutexAutoLock cutofflock(cutoff_mutex); + MutexAutoLock cutofflock(cutoff_mutex); for (std::list::iterator i = cutoffs.begin(); i != cutoffs.end(); ++i) { CutoffData cutoff = *i; @@ -203,7 +203,7 @@ void Decoration::placeCutoffs(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) // Remove cutoffs that were handled from the cutoff list { - JMutexAutoLock cutofflock(cutoff_mutex); + MutexAutoLock cutofflock(cutoff_mutex); for (std::list::iterator i = cutoffs.begin(); i != cutoffs.end(); ++i) { diff --git a/src/mg_decoration.h b/src/mg_decoration.h index 056748918..c712ce7c8 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -84,7 +84,7 @@ public: std::set biomes; //std::list cutoffs; - //JMutex cutoff_mutex; + //Mutex cutoff_mutex; }; class DecoSimple : public Decoration { diff --git a/src/minimap.cpp b/src/minimap.cpp index d1fb3867d..7eb7247ca 100644 --- a/src/minimap.cpp +++ b/src/minimap.cpp @@ -20,8 +20,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "minimap.h" #include #include "logoutputbuffer.h" -#include "jthread/jmutexautolock.h" -#include "jthread/jsemaphore.h" +#include "threading/mutex_auto_lock.h" +#include "threading/semaphore.h" #include "clientmap.h" #include "settings.h" #include "nodedef.h" @@ -52,7 +52,7 @@ MinimapUpdateThread::~MinimapUpdateThread() bool MinimapUpdateThread::pushBlockUpdate(v3s16 pos, MinimapMapblock *data) { - JMutexAutoLock lock(m_queue_mutex); + MutexAutoLock lock(m_queue_mutex); // Find if block is already in queue. // If it is, update the data and quit. @@ -78,7 +78,7 @@ bool MinimapUpdateThread::pushBlockUpdate(v3s16 pos, MinimapMapblock *data) bool MinimapUpdateThread::popBlockUpdate(QueuedMinimapUpdate *update) { - JMutexAutoLock lock(m_queue_mutex); + MutexAutoLock lock(m_queue_mutex); if (m_update_queue.empty()) return false; @@ -256,13 +256,13 @@ Mapper::Mapper(IrrlichtDevice *device, Client *client) // Initialize and start thread m_minimap_update_thread = new MinimapUpdateThread(); m_minimap_update_thread->data = data; - m_minimap_update_thread->Start(); + m_minimap_update_thread->start(); } Mapper::~Mapper() { - m_minimap_update_thread->Stop(); - m_minimap_update_thread->Wait(); + m_minimap_update_thread->stop(); + m_minimap_update_thread->wait(); m_meshbuffer->drop(); @@ -290,7 +290,7 @@ MinimapMode Mapper::getMinimapMode() void Mapper::toggleMinimapShape() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); data->minimap_shape_round = !data->minimap_shape_round; g_settings->setBool("minimap_shape_round", data->minimap_shape_round); @@ -312,7 +312,7 @@ void Mapper::setMinimapMode(MinimapMode mode) if (mode >= MINIMAP_MODE_COUNT) return; - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); data->is_radar = modedefs[mode].is_radar; data->scan_height = modedefs[mode].scan_height; @@ -327,7 +327,7 @@ void Mapper::setPos(v3s16 pos) bool do_update = false; { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); if (pos != data->old_pos) { data->old_pos = data->pos; diff --git a/src/minimap.h b/src/minimap.h index 628be7489..dd1397d54 100644 --- a/src/minimap.h +++ b/src/minimap.h @@ -20,18 +20,19 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef MINIMAP_HEADER #define MINIMAP_HEADER -#include -#include -#include #include "irrlichttypes_extrabloated.h" #include "client.h" #include "voxel.h" -#include "jthread/jmutex.h" -#include "jthread/jsemaphore.h" +#include "threading/mutex.h" +#include "threading/semaphore.h" +#include +#include +#include #define MINIMAP_MAX_SX 512 #define MINIMAP_MAX_SY 512 + enum MinimapMode { MINIMAP_MODE_OFF, MINIMAP_MODE_SURFACEx1, @@ -90,6 +91,7 @@ struct QueuedMinimapUpdate { class MinimapUpdateThread : public UpdateThread { public: + MinimapUpdateThread() : UpdateThread("Minimap") {} virtual ~MinimapUpdateThread(); void getMap(v3s16 pos, s16 size, s16 height, bool radar); @@ -105,11 +107,10 @@ public: MinimapData *data; protected: - const char *getName() { return "MinimapUpdateThread"; } virtual void doUpdate(); private: - JMutex m_queue_mutex; + Mutex m_queue_mutex; std::deque m_update_queue; std::map m_blocks_cache; }; @@ -151,7 +152,7 @@ private: bool m_enable_shaders; u16 m_surface_mode_scan_height; f32 m_angle; - JMutex m_mutex; + Mutex m_mutex; }; #endif diff --git a/src/network/clientpackethandler.cpp b/src/network/clientpackethandler.cpp index 86091bc88..04f94c58b 100644 --- a/src/network/clientpackethandler.cpp +++ b/src/network/clientpackethandler.cpp @@ -621,7 +621,7 @@ void Client::handleCommand_AnnounceMedia(NetworkPacket* pkt) // Mesh update thread must be stopped while // updating content definitions - sanity_check(!m_mesh_update_thread.IsRunning()); + sanity_check(!m_mesh_update_thread.isRunning()); for (u16 i = 0; i < num_files; i++) { std::string name, sha1_base64; @@ -694,7 +694,7 @@ void Client::handleCommand_Media(NetworkPacket* pkt) // Mesh update thread must be stopped while // updating content definitions - sanity_check(!m_mesh_update_thread.IsRunning()); + sanity_check(!m_mesh_update_thread.isRunning()); for (u32 i=0; i < num_files; i++) { std::string name; @@ -720,7 +720,7 @@ void Client::handleCommand_NodeDef(NetworkPacket* pkt) // Mesh update thread must be stopped while // updating content definitions - sanity_check(!m_mesh_update_thread.IsRunning()); + sanity_check(!m_mesh_update_thread.isRunning()); // Decompress node definitions std::string datastring(pkt->getString(0), pkt->getSize()); @@ -747,7 +747,7 @@ void Client::handleCommand_ItemDef(NetworkPacket* pkt) // Mesh update thread must be stopped while // updating content definitions - sanity_check(!m_mesh_update_thread.IsRunning()); + sanity_check(!m_mesh_update_thread.isRunning()); // Decompress item definitions std::string datastring(pkt->getString(0), pkt->getSize()); diff --git a/src/network/connection.cpp b/src/network/connection.cpp index 7794ce10f..10f0d5543 100644 --- a/src/network/connection.cpp +++ b/src/network/connection.cpp @@ -42,10 +42,10 @@ namespace con #undef DEBUG_CONNECTION_KBPS #else /* this mutex is used to achieve log message consistency */ -JMutex log_message_mutex; +Mutex log_message_mutex; #define LOG(a) \ { \ - JMutexAutoLock loglock(log_message_mutex); \ + MutexAutoLock loglock(log_message_mutex); \ a; \ } #define PROFILE(a) a @@ -209,7 +209,7 @@ ReliablePacketBuffer::ReliablePacketBuffer(): m_list_size(0) {} void ReliablePacketBuffer::print() { - JMutexAutoLock listlock(m_list_mutex); + MutexAutoLock listlock(m_list_mutex); LOG(dout_con<<"Dump of ReliablePacketBuffer:" << std::endl); unsigned int index = 0; for(std::list::iterator i = m_list.begin(); @@ -223,7 +223,7 @@ void ReliablePacketBuffer::print() } bool ReliablePacketBuffer::empty() { - JMutexAutoLock listlock(m_list_mutex); + MutexAutoLock listlock(m_list_mutex); return m_list.empty(); } @@ -256,7 +256,7 @@ RPBSearchResult ReliablePacketBuffer::notFound() } bool ReliablePacketBuffer::getFirstSeqnum(u16& result) { - JMutexAutoLock listlock(m_list_mutex); + MutexAutoLock listlock(m_list_mutex); if (m_list.empty()) return false; BufferedPacket p = *m_list.begin(); @@ -266,7 +266,7 @@ bool ReliablePacketBuffer::getFirstSeqnum(u16& result) BufferedPacket ReliablePacketBuffer::popFirst() { - JMutexAutoLock listlock(m_list_mutex); + MutexAutoLock listlock(m_list_mutex); if (m_list.empty()) throw NotFoundException("Buffer is empty"); BufferedPacket p = *m_list.begin(); @@ -283,7 +283,7 @@ BufferedPacket ReliablePacketBuffer::popFirst() } BufferedPacket ReliablePacketBuffer::popSeqnum(u16 seqnum) { - JMutexAutoLock listlock(m_list_mutex); + MutexAutoLock listlock(m_list_mutex); RPBSearchResult r = findPacket(seqnum); if (r == notFound()) { LOG(dout_con<<"Sequence number: " << seqnum @@ -311,7 +311,7 @@ BufferedPacket ReliablePacketBuffer::popSeqnum(u16 seqnum) } void ReliablePacketBuffer::insert(BufferedPacket &p,u16 next_expected) { - JMutexAutoLock listlock(m_list_mutex); + MutexAutoLock listlock(m_list_mutex); if (p.data.getSize() < BASE_HEADER_SIZE + 3) { errorstream << "ReliablePacketBuffer::insert(): Invalid data size for " "reliable packet" << std::endl; @@ -411,7 +411,7 @@ void ReliablePacketBuffer::insert(BufferedPacket &p,u16 next_expected) void ReliablePacketBuffer::incrementTimeouts(float dtime) { - JMutexAutoLock listlock(m_list_mutex); + MutexAutoLock listlock(m_list_mutex); for(std::list::iterator i = m_list.begin(); i != m_list.end(); ++i) { @@ -423,7 +423,7 @@ void ReliablePacketBuffer::incrementTimeouts(float dtime) std::list ReliablePacketBuffer::getTimedOuts(float timeout, unsigned int max_packets) { - JMutexAutoLock listlock(m_list_mutex); + MutexAutoLock listlock(m_list_mutex); std::list timed_outs; for(std::list::iterator i = m_list.begin(); i != m_list.end(); ++i) @@ -446,7 +446,7 @@ std::list ReliablePacketBuffer::getTimedOuts(float timeout, IncomingSplitBuffer::~IncomingSplitBuffer() { - JMutexAutoLock listlock(m_map_mutex); + MutexAutoLock listlock(m_map_mutex); for(std::map::iterator i = m_buf.begin(); i != m_buf.end(); ++i) { @@ -459,7 +459,7 @@ IncomingSplitBuffer::~IncomingSplitBuffer() */ SharedBuffer IncomingSplitBuffer::insert(BufferedPacket &p, bool reliable) { - JMutexAutoLock listlock(m_map_mutex); + MutexAutoLock listlock(m_map_mutex); u32 headersize = BASE_HEADER_SIZE + 7; if (p.data.getSize() < headersize) { errorstream << "Invalid data size for split packet" << std::endl; @@ -546,7 +546,7 @@ void IncomingSplitBuffer::removeUnreliableTimedOuts(float dtime, float timeout) { std::list remove_queue; { - JMutexAutoLock listlock(m_map_mutex); + MutexAutoLock listlock(m_map_mutex); for(std::map::iterator i = m_buf.begin(); i != m_buf.end(); ++i) { @@ -562,7 +562,7 @@ void IncomingSplitBuffer::removeUnreliableTimedOuts(float dtime, float timeout) for(std::list::iterator j = remove_queue.begin(); j != remove_queue.end(); ++j) { - JMutexAutoLock listlock(m_map_mutex); + MutexAutoLock listlock(m_map_mutex); LOG(dout_con<<"NOTE: Removing timed out unreliable split packet"< 10.0) { { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); cur_kbps = (((float) current_bytes_transfered)/bpm_counter)/1024.0; current_bytes_transfered = 0; @@ -903,7 +903,7 @@ bool PeerHelper::operator!=(void* ptr) bool Peer::IncUseCount() { - JMutexAutoLock lock(m_exclusive_access_mutex); + MutexAutoLock lock(m_exclusive_access_mutex); if (!m_pending_deletion) { @@ -917,7 +917,7 @@ bool Peer::IncUseCount() void Peer::DecUseCount() { { - JMutexAutoLock lock(m_exclusive_access_mutex); + MutexAutoLock lock(m_exclusive_access_mutex); sanity_check(m_usage > 0); m_usage--; @@ -978,7 +978,7 @@ void Peer::RTTStatistics(float rtt, std::string profiler_id, bool Peer::isTimedOut(float timeout) { - JMutexAutoLock lock(m_exclusive_access_mutex); + MutexAutoLock lock(m_exclusive_access_mutex); u32 current_time = porting::getTimeMs(); float dtime = CALC_DTIME(m_last_timeout_check,current_time); @@ -992,7 +992,7 @@ bool Peer::isTimedOut(float timeout) void Peer::Drop() { { - JMutexAutoLock usage_lock(m_exclusive_access_mutex); + MutexAutoLock usage_lock(m_exclusive_access_mutex); m_pending_deletion = true; if (m_usage != 0) return; @@ -1051,7 +1051,7 @@ void UDPPeer::reportRTT(float rtt) if (timeout > RESEND_TIMEOUT_MAX) timeout = RESEND_TIMEOUT_MAX; - JMutexAutoLock usage_lock(m_exclusive_access_mutex); + MutexAutoLock usage_lock(m_exclusive_access_mutex); resend_timeout = timeout; } @@ -1255,8 +1255,9 @@ SharedBuffer UDPPeer::addSpiltPacket(u8 channel, /* Connection Threads */ /******************************************************************************/ -ConnectionSendThread::ConnectionSendThread( unsigned int max_packet_size, - float timeout) : +ConnectionSendThread::ConnectionSendThread(unsigned int max_packet_size, + float timeout) : + Thread("ConnectionSend"), m_connection(NULL), m_max_packet_size(max_packet_size), m_timeout(timeout), @@ -1266,11 +1267,9 @@ ConnectionSendThread::ConnectionSendThread( unsigned int max_packet_size, { } -void * ConnectionSendThread::Thread() +void * ConnectionSendThread::run() { - assert(m_connection != NULL); - ThreadStarted(); - log_register_thread("ConnectionSend"); + assert(m_connection); LOG(dout_con<getDesc() <<"ConnectionSend thread started"<getDesc() << "]"); - porting::setThreadName("ConnectionSend"); - /* if stop is requested don't stop immediately but try to send all */ /* packets first */ - while(!StopRequested() || packetsQueued()) { + while(!stopRequested() || packetsQueued()) { BEGIN_DEBUG_EXCEPTION_HANDLER PROFILE(ScopeProfiler sp(g_profiler, ThreadIdentifier.str(), SPT_AVG)); m_iteration_packets_avaialble = m_max_data_packets_per_iteration; /* wait for trigger or timeout */ - m_send_sleep_semaphore.Wait(50); + m_send_sleep_semaphore.wait(50); /* remove all triggers */ - while(m_send_sleep_semaphore.Wait(0)) {} + while(m_send_sleep_semaphore.wait(0)) {} lasttime = curtime; curtime = porting::getTimeMs(); @@ -1328,7 +1325,7 @@ void * ConnectionSendThread::Thread() void ConnectionSendThread::Trigger() { - m_send_sleep_semaphore.Post(); + m_send_sleep_semaphore.post(); } bool ConnectionSendThread::packetsQueued() @@ -1984,7 +1981,7 @@ void ConnectionSendThread::sendPackets(float dtime) } else if ( ( peer->m_increment_packets_remaining > 0) || - (StopRequested())) { + (stopRequested())) { rawSendAsPacket(packet.peer_id, packet.channelnum, packet.data, packet.reliable); peer->m_increment_packets_remaining--; @@ -2014,15 +2011,14 @@ void ConnectionSendThread::sendAsPacket(u16 peer_id, u8 channelnum, } ConnectionReceiveThread::ConnectionReceiveThread(unsigned int max_packet_size) : + Thread("ConnectionReceive"), m_connection(NULL) { } -void * ConnectionReceiveThread::Thread() +void * ConnectionReceiveThread::run() { - assert(m_connection != NULL); - ThreadStarted(); - log_register_thread("ConnectionReceive"); + assert(m_connection); LOG(dout_con<getDesc() <<"ConnectionReceive thread started"<getDesc() << "]"); - porting::setThreadName("ConnectionReceive"); - #ifdef DEBUG_CONNECTION_KBPS u32 curtime = porting::getTimeMs(); u32 lasttime = curtime; float debug_print_timer = 0.0; #endif - while(!StopRequested()) { + while(!stopRequested()) { BEGIN_DEBUG_EXCEPTION_HANDLER PROFILE(ScopeProfiler sp(g_profiler, ThreadIdentifier.str(), SPT_AVG)); @@ -2684,8 +2678,8 @@ Connection::Connection(u32 protocol_id, u32 max_packet_size, float timeout, m_sendThread.setParent(this); m_receiveThread.setParent(this); - m_sendThread.Start(); - m_receiveThread.Start(); + m_sendThread.start(); + m_receiveThread.start(); } @@ -2694,8 +2688,8 @@ Connection::~Connection() { m_shutting_down = true; // request threads to stop - m_sendThread.Stop(); - m_receiveThread.Stop(); + m_sendThread.stop(); + m_receiveThread.stop(); //TODO for some unkonwn reason send/receive threads do not exit as they're // supposed to be but wait on peer timeout. To speed up shutdown we reduce @@ -2703,8 +2697,8 @@ Connection::~Connection() m_sendThread.setPeerTimeout(0.5); // wait for threads to finish - m_sendThread.Wait(); - m_receiveThread.Wait(); + m_sendThread.wait(); + m_receiveThread.wait(); // Delete peers for(std::map::iterator @@ -2724,7 +2718,7 @@ void Connection::putEvent(ConnectionEvent &e) PeerHelper Connection::getPeer(u16 peer_id) { - JMutexAutoLock peerlock(m_peers_mutex); + MutexAutoLock peerlock(m_peers_mutex); std::map::iterator node = m_peers.find(peer_id); if (node == m_peers.end()) { @@ -2739,7 +2733,7 @@ PeerHelper Connection::getPeer(u16 peer_id) PeerHelper Connection::getPeerNoEx(u16 peer_id) { - JMutexAutoLock peerlock(m_peers_mutex); + MutexAutoLock peerlock(m_peers_mutex); std::map::iterator node = m_peers.find(peer_id); if (node == m_peers.end()) { @@ -2755,7 +2749,7 @@ PeerHelper Connection::getPeerNoEx(u16 peer_id) /* find peer_id for address */ u16 Connection::lookupPeer(Address& sender) { - JMutexAutoLock peerlock(m_peers_mutex); + MutexAutoLock peerlock(m_peers_mutex); std::map::iterator j; j = m_peers.begin(); for(; j != m_peers.end(); ++j) @@ -2794,7 +2788,7 @@ bool Connection::deletePeer(u16 peer_id, bool timeout) /* lock list as short as possible */ { - JMutexAutoLock peerlock(m_peers_mutex); + MutexAutoLock peerlock(m_peers_mutex); if (m_peers.find(peer_id) == m_peers.end()) return false; peer = m_peers[peer_id]; @@ -2852,7 +2846,7 @@ void Connection::Connect(Address address) bool Connection::Connected() { - JMutexAutoLock peerlock(m_peers_mutex); + MutexAutoLock peerlock(m_peers_mutex); if (m_peers.size() != 1) return false; @@ -2987,7 +2981,7 @@ u16 Connection::createPeer(Address& sender, MTProtocols protocol, int fd) /* Find an unused peer id */ - JMutexAutoLock lock(m_peers_mutex); + MutexAutoLock lock(m_peers_mutex); bool out_of_ids = false; for(;;) { // Check if exists @@ -3038,9 +3032,9 @@ u16 Connection::createPeer(Address& sender, MTProtocols protocol, int fd) void Connection::PrintInfo(std::ostream &out) { - m_info_mutex.Lock(); + m_info_mutex.lock(); out<id] = peer; m_peer_ids.push_back(peer->id); } diff --git a/src/network/connection.h b/src/network/connection.h index 15ea7e20f..fe2c9819d 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -349,7 +349,7 @@ private: u16 m_oldest_non_answered_ack; - JMutex m_list_mutex; + Mutex m_list_mutex; }; /* @@ -372,7 +372,7 @@ private: // Key is seqnum std::map m_buf; - JMutex m_map_mutex; + Mutex m_map_mutex; }; struct OutgoingPacket @@ -519,32 +519,32 @@ public: void UpdateTimers(float dtime, bool legacy_peer); const float getCurrentDownloadRateKB() - { JMutexAutoLock lock(m_internal_mutex); return cur_kbps; }; + { MutexAutoLock lock(m_internal_mutex); return cur_kbps; }; const float getMaxDownloadRateKB() - { JMutexAutoLock lock(m_internal_mutex); return max_kbps; }; + { MutexAutoLock lock(m_internal_mutex); return max_kbps; }; const float getCurrentLossRateKB() - { JMutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; }; + { MutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; }; const float getMaxLossRateKB() - { JMutexAutoLock lock(m_internal_mutex); return max_kbps_lost; }; + { MutexAutoLock lock(m_internal_mutex); return max_kbps_lost; }; const float getCurrentIncomingRateKB() - { JMutexAutoLock lock(m_internal_mutex); return cur_incoming_kbps; }; + { MutexAutoLock lock(m_internal_mutex); return cur_incoming_kbps; }; const float getMaxIncomingRateKB() - { JMutexAutoLock lock(m_internal_mutex); return max_incoming_kbps; }; + { MutexAutoLock lock(m_internal_mutex); return max_incoming_kbps; }; const float getAvgDownloadRateKB() - { JMutexAutoLock lock(m_internal_mutex); return avg_kbps; }; + { MutexAutoLock lock(m_internal_mutex); return avg_kbps; }; const float getAvgLossRateKB() - { JMutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; }; + { MutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; }; const float getAvgIncomingRateKB() - { JMutexAutoLock lock(m_internal_mutex); return avg_incoming_kbps; }; + { MutexAutoLock lock(m_internal_mutex); return avg_incoming_kbps; }; const unsigned int getWindowSize() const { return window_size; }; void setWindowSize(unsigned int size) { window_size = size; }; private: - JMutex m_internal_mutex; + Mutex m_internal_mutex; int window_size; u16 next_incoming_seqnum; @@ -675,7 +675,7 @@ class Peer { }; virtual ~Peer() { - JMutexAutoLock usage_lock(m_exclusive_access_mutex); + MutexAutoLock usage_lock(m_exclusive_access_mutex); FATAL_ERROR_IF(m_usage != 0, "Reference counting failure"); }; @@ -692,15 +692,15 @@ class Peer { virtual bool getAddress(MTProtocols type, Address& toset) = 0; void ResetTimeout() - {JMutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter=0.0; }; + {MutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter=0.0; }; bool isTimedOut(float timeout); void setSentWithID() - { JMutexAutoLock lock(m_exclusive_access_mutex); m_has_sent_with_id = true; }; + { MutexAutoLock lock(m_exclusive_access_mutex); m_has_sent_with_id = true; }; bool hasSentWithID() - { JMutexAutoLock lock(m_exclusive_access_mutex); return m_has_sent_with_id; }; + { MutexAutoLock lock(m_exclusive_access_mutex); return m_has_sent_with_id; }; unsigned int m_increment_packets_remaining; unsigned int m_increment_bytes_remaining; @@ -744,7 +744,7 @@ class Peer { bool IncUseCount(); void DecUseCount(); - JMutex m_exclusive_access_mutex; + Mutex m_exclusive_access_mutex; bool m_pending_deletion; @@ -826,10 +826,10 @@ protected: unsigned int maxtransfer); float getResendTimeout() - { JMutexAutoLock lock(m_exclusive_access_mutex); return resend_timeout; } + { MutexAutoLock lock(m_exclusive_access_mutex); return resend_timeout; } void setResendTimeout(float timeout) - { JMutexAutoLock lock(m_exclusive_access_mutex); resend_timeout = timeout; } + { MutexAutoLock lock(m_exclusive_access_mutex); resend_timeout = timeout; } bool Ping(float dtime,SharedBuffer& data); Channel channels[CHANNEL_COUNT]; @@ -910,14 +910,14 @@ struct ConnectionEvent } }; -class ConnectionSendThread : public JThread { +class ConnectionSendThread : public Thread { public: friend class UDPPeer; ConnectionSendThread(unsigned int max_packet_size, float timeout); - void * Thread (); + void *run(); void Trigger(); @@ -961,7 +961,7 @@ private: unsigned int m_max_packet_size; float m_timeout; std::queue m_outgoing_queue; - JSemaphore m_send_sleep_semaphore; + Semaphore m_send_sleep_semaphore; unsigned int m_iteration_packets_avaialble; unsigned int m_max_commands_per_iteration; @@ -969,24 +969,24 @@ private: unsigned int m_max_packets_requeued; }; -class ConnectionReceiveThread : public JThread { +class ConnectionReceiveThread : public Thread { public: ConnectionReceiveThread(unsigned int max_packet_size); - void * Thread (); + void *run(); - void setParent(Connection* parent) { - assert(parent != NULL); // Pre-condition + void setParent(Connection *parent) { + assert(parent); // Pre-condition m_connection = parent; } private: - void receive (); + void receive(); // Returns next data from a buffer if possible // If found, returns true; if not, false. // If found, sets peer_id and dst - bool getFromBuffers (u16 &peer_id, SharedBuffer &dst); + bool getFromBuffers(u16 &peer_id, SharedBuffer &dst); bool checkIncomingBuffers(Channel *channel, u16 &peer_id, SharedBuffer &dst); @@ -1054,7 +1054,7 @@ protected: std::list getPeerIDs() { - JMutexAutoLock peerlock(m_peers_mutex); + MutexAutoLock peerlock(m_peers_mutex); return m_peer_ids; } @@ -1075,12 +1075,12 @@ private: std::map m_peers; std::list m_peer_ids; - JMutex m_peers_mutex; + Mutex m_peers_mutex; ConnectionSendThread m_sendThread; ConnectionReceiveThread m_receiveThread; - JMutex m_info_mutex; + Mutex m_info_mutex; // Backwards compatibility PeerHandler *m_bc_peerhandler; diff --git a/src/particles.cpp b/src/particles.cpp index 15e2a6597..ab48bae9e 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -347,7 +347,7 @@ void ParticleManager::step(float dtime) void ParticleManager::stepSpawners (float dtime) { - JMutexAutoLock lock(m_spawner_list_lock); + MutexAutoLock lock(m_spawner_list_lock); for(std::map::iterator i = m_particle_spawners.begin(); i != m_particle_spawners.end();) @@ -367,7 +367,7 @@ void ParticleManager::stepSpawners (float dtime) void ParticleManager::stepParticles (float dtime) { - JMutexAutoLock lock(m_particle_list_lock); + MutexAutoLock lock(m_particle_list_lock); for(std::vector::iterator i = m_particles.begin(); i != m_particles.end();) { @@ -387,8 +387,8 @@ void ParticleManager::stepParticles (float dtime) void ParticleManager::clearAll () { - JMutexAutoLock lock(m_spawner_list_lock); - JMutexAutoLock lock2(m_particle_list_lock); + MutexAutoLock lock(m_spawner_list_lock); + MutexAutoLock lock2(m_particle_list_lock); for(std::map::iterator i = m_particle_spawners.begin(); i != m_particle_spawners.end();) @@ -411,7 +411,7 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, IGameDef *gamedef, scene::ISceneManager* smgr, LocalPlayer *player) { if (event->type == CE_DELETE_PARTICLESPAWNER) { - JMutexAutoLock lock(m_spawner_list_lock); + MutexAutoLock lock(m_spawner_list_lock); if (m_particle_spawners.find(event->delete_particlespawner.id) != m_particle_spawners.end()) { @@ -425,7 +425,7 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, IGameDef *gamedef, if (event->type == CE_ADD_PARTICLESPAWNER) { { - JMutexAutoLock lock(m_spawner_list_lock); + MutexAutoLock lock(m_spawner_list_lock); if (m_particle_spawners.find(event->add_particlespawner.id) != m_particle_spawners.end()) { @@ -465,7 +465,7 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, IGameDef *gamedef, delete event->add_particlespawner.maxacc; { - JMutexAutoLock lock(m_spawner_list_lock); + MutexAutoLock lock(m_spawner_list_lock); m_particle_spawners.insert( std::pair( event->add_particlespawner.id, @@ -568,6 +568,6 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s void ParticleManager::addParticle(Particle* toadd) { - JMutexAutoLock lock(m_particle_list_lock); + MutexAutoLock lock(m_particle_list_lock); m_particles.push_back(toadd); } diff --git a/src/particles.h b/src/particles.h index 2bc2e7bfa..0ad8d71b5 100644 --- a/src/particles.h +++ b/src/particles.h @@ -190,8 +190,8 @@ private: std::map m_particle_spawners; ClientEnvironment* m_env; - JMutex m_particle_list_lock; - JMutex m_spawner_list_lock; + Mutex m_particle_list_lock; + Mutex m_spawner_list_lock; }; #endif diff --git a/src/player.cpp b/src/player.cpp index cb2286ef6..3ee34d41f 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "player.h" #include -#include "jthread/jmutexautolock.h" +#include "threading/mutex_auto_lock.h" #include "util/numeric.h" #include "hud.h" #include "constants.h" @@ -217,7 +217,7 @@ void Player::deSerialize(std::istream &is, std::string playername) u32 Player::addHud(HudElement *toadd) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); u32 id = getFreeHudID(); @@ -231,7 +231,7 @@ u32 Player::addHud(HudElement *toadd) HudElement* Player::getHud(u32 id) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); if (id < hud.size()) return hud[id]; @@ -241,7 +241,7 @@ HudElement* Player::getHud(u32 id) HudElement* Player::removeHud(u32 id) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); HudElement* retval = NULL; if (id < hud.size()) { @@ -253,7 +253,7 @@ HudElement* Player::removeHud(u32 id) void Player::clearHud() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); while(!hud.empty()) { delete hud.back(); diff --git a/src/player.h b/src/player.h index 3a336afc4..ec30e59d2 100644 --- a/src/player.h +++ b/src/player.h @@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_bloated.h" #include "inventory.h" #include "constants.h" // BS -#include "jthread/jmutex.h" +#include "threading/mutex.h" #include #define PLAYERNAME_SIZE 20 @@ -413,7 +413,7 @@ private: // Protect some critical areas // hud for example can be modified by EmergeThread // and ServerThread - JMutex m_mutex; + Mutex m_mutex; }; diff --git a/src/porting.cpp b/src/porting.cpp index 44f1fcff1..cb9f3270b 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -129,130 +129,6 @@ void signal_handler_init(void) #endif -/* - Multithreading support -*/ -int getNumberOfProcessors() -{ -#if defined(_SC_NPROCESSORS_ONLN) - - return sysconf(_SC_NPROCESSORS_ONLN); - -#elif defined(__FreeBSD__) || defined(__APPLE__) - - unsigned int len, count; - len = sizeof(count); - return sysctlbyname("hw.ncpu", &count, &len, NULL, 0); - -#elif defined(_GNU_SOURCE) - - return get_nprocs(); - -#elif defined(_WIN32) - - SYSTEM_INFO sysinfo; - GetSystemInfo(&sysinfo); - return sysinfo.dwNumberOfProcessors; - -#elif defined(PTW32_VERSION) || defined(__hpux) - - return pthread_num_processors_np(); - -#else - - return 1; - -#endif -} - - -#ifndef __ANDROID__ -bool threadBindToProcessor(threadid_t tid, int pnumber) -{ -#if defined(_WIN32) - - HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, tid); - if (!hThread) - return false; - - bool success = SetThreadAffinityMask(hThread, 1 << pnumber) != 0; - - CloseHandle(hThread); - return success; - -#elif (defined(__FreeBSD__) && (__FreeBSD_version >= 702106)) \ - || defined(__linux) || defined(linux) - - cpu_set_t cpuset; - - CPU_ZERO(&cpuset); - CPU_SET(pnumber, &cpuset); - return pthread_setaffinity_np(tid, sizeof(cpuset), &cpuset) == 0; - -#elif defined(__sun) || defined(sun) - - return processor_bind(P_LWPID, MAKE_LWPID_PTHREAD(tid), - pnumber, NULL) == 0; - -#elif defined(_AIX) - - return bindprocessor(BINDTHREAD, (tid_t)tid, pnumber) == 0; - -#elif defined(__hpux) || defined(hpux) - - pthread_spu_t answer; - - return pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP, - &answer, pnumber, tid) == 0; - -#elif defined(__APPLE__) - - struct thread_affinity_policy tapol; - - thread_port_t threadport = pthread_mach_thread_np(tid); - tapol.affinity_tag = pnumber + 1; - return thread_policy_set(threadport, THREAD_AFFINITY_POLICY, - (thread_policy_t)&tapol, THREAD_AFFINITY_POLICY_COUNT) == KERN_SUCCESS; - -#else - - return false; - -#endif -} -#endif - -bool threadSetPriority(threadid_t tid, int prio) -{ -#if defined(_WIN32) - - HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, 0, tid); - if (!hThread) - return false; - - bool success = SetThreadPriority(hThread, prio) != 0; - - CloseHandle(hThread); - return success; - -#else - - struct sched_param sparam; - int policy; - - if (pthread_getschedparam(tid, &policy, &sparam) != 0) - return false; - - int min = sched_get_priority_min(policy); - int max = sched_get_priority_max(policy); - - sparam.sched_priority = min + prio * (max - min) / THREAD_PRIORITY_HIGHEST; - return pthread_setschedparam(tid, policy, &sparam) == 0; - -#endif -} - - /* Path mangler */ diff --git a/src/porting.h b/src/porting.h index 2a91fdd06..492c9d3a8 100644 --- a/src/porting.h +++ b/src/porting.h @@ -64,28 +64,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define _GNU_SOURCE #endif - #include - - #ifdef __FreeBSD__ - #include - typedef cpuset_t cpu_set_t; - #elif defined(__sun) || defined(sun) - #include - #include - #elif defined(_AIX) - #include - #elif __APPLE__ - #include - #include - #endif - #define sleep_ms(x) usleep(x*1000) - - #define THREAD_PRIORITY_LOWEST 0 - #define THREAD_PRIORITY_BELOW_NORMAL 1 - #define THREAD_PRIORITY_NORMAL 2 - #define THREAD_PRIORITY_ABOVE_NORMAL 3 - #define THREAD_PRIORITY_HIGHEST 4 #endif #ifdef _MSC_VER @@ -165,21 +144,6 @@ std::string getDataPath(const char *subpath); */ void initializePaths(); -/* - Get number of online processors in the system. -*/ -int getNumberOfProcessors(); - -/* - Set a thread's affinity to a particular processor. -*/ -bool threadBindToProcessor(threadid_t tid, int pnumber); - -/* - Set a thread's priority. -*/ -bool threadSetPriority(threadid_t tid, int prio); - /* Return system information e.g. "Linux/3.12.7 x86_64" @@ -311,59 +275,6 @@ inline u32 getDeltaMs(u32 old_time_ms, u32 new_time_ms) } } -#if defined(linux) || defined(__linux) - #include - - inline void setThreadName(const char *name) { - /* It would be cleaner to do this with pthread_setname_np, - * which was added to glibc in version 2.12, but some major - * distributions are still runing 2.11 and previous versions. - */ - prctl(PR_SET_NAME, name); - } -#elif defined(__FreeBSD__) || defined(__OpenBSD__) - #include - #include - - inline void setThreadName(const char *name) { - pthread_set_name_np(pthread_self(), name); - } -#elif defined(__NetBSD__) - #include - - inline void setThreadName(const char *name) { - pthread_setname_np(pthread_self(), name); - } -#elif defined(_MSC_VER) - typedef struct tagTHREADNAME_INFO { - DWORD dwType; // must be 0x1000 - LPCSTR szName; // pointer to name (in user addr space) - DWORD dwThreadID; // thread ID (-1=caller thread) - DWORD dwFlags; // reserved for future use, must be zero - } THREADNAME_INFO; - - inline void setThreadName(const char *name) { - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = name; - info.dwThreadID = -1; - info.dwFlags = 0; - __try { - RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *) &info); - } __except (EXCEPTION_CONTINUE_EXECUTION) {} - } -#elif defined(__APPLE__) - #include - - inline void setThreadName(const char *name) { - pthread_setname_np(name); - } -#elif defined(_WIN32) || defined(__GNU__) - inline void setThreadName(const char* name) {} -#else - #warning "Unrecognized platform, thread names will not be available." - inline void setThreadName(const char* name) {} -#endif #ifndef SERVER float getDisplayDensity(); diff --git a/src/porting_android.cpp b/src/porting_android.cpp index 6871ce465..06cc929dd 100644 --- a/src/porting_android.cpp +++ b/src/porting_android.cpp @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "porting_android.h" +#include "threading/thread.h" #include "config.h" #include "filesys.h" #include "log.h" @@ -39,30 +40,28 @@ void android_main(android_app *app) int retval = 0; porting::app_global = app; - porting::setThreadName("MainThread"); + Thread::setName("MainThread"); try { app_dummy(); - char *argv[] = { (char*) "minetest" }; + char *argv[] = {(char*) "minetest"}; main(sizeof(argv) / sizeof(argv[0]), argv); - } - catch(BaseException e) { + } catch (BaseException &e) { std::stringstream msg; msg << "Exception handled by main: " << e.what(); - const char* message = msg.str().c_str(); + const char *message = msg.str().c_str(); __android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME, "%s", message); errorstream << msg << std::endl; retval = -1; - } - catch(...) { + } catch (...) { __android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME, - "Some exception occured"); + "An unknown exception occured!"); errorstream << "Uncaught exception in main thread!" << std::endl; retval = -1; } porting::cleanupAndroid(); - errorstream << "Shutting down minetest." << std::endl; + errorstream << "Shutting down." << std::endl; exit(retval); } diff --git a/src/profiler.h b/src/profiler.h index 78d3b08e0..e8eac86b1 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -24,8 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -#include "jthread/jmutex.h" -#include "jthread/jmutexautolock.h" +#include "threading/mutex.h" +#include "threading/mutex_auto_lock.h" #include "util/timetaker.h" #include "util/numeric.h" // paging() #include "debug.h" // assert() @@ -49,7 +49,7 @@ public: void add(const std::string &name, float value) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); { /* No average shall have been used; mark add used as -2 */ std::map::iterator n = m_avgcounts.find(name); @@ -72,7 +72,7 @@ public: void avg(const std::string &name, float value) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); int &count = m_avgcounts[name]; assert(count != -2); @@ -82,7 +82,7 @@ public: void clear() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); for(std::map::iterator i = m_data.begin(); i != m_data.end(); ++i) @@ -114,7 +114,7 @@ public: void printPage(std::ostream &o, u32 page, u32 pagecount) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); u32 minindex, maxindex; paging(m_data.size(), page, pagecount, minindex, maxindex); @@ -159,7 +159,7 @@ public: void graphAdd(const std::string &id, float value) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); std::map::iterator i = m_graphvalues.find(id); if(i == m_graphvalues.end()) @@ -169,20 +169,20 @@ public: } void graphGet(GraphValues &result) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); result = m_graphvalues; m_graphvalues.clear(); } void remove(const std::string& name) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); m_avgcounts.erase(name); m_data.erase(name); } private: - JMutex m_mutex; + Mutex m_mutex; std::map m_data; std::map m_avgcounts; std::map m_graphvalues; diff --git a/src/quicktune.cpp b/src/quicktune.cpp index 2f9f987bd..b0e2dc6d5 100644 --- a/src/quicktune.cpp +++ b/src/quicktune.cpp @@ -18,8 +18,8 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "quicktune.h" -#include "jthread/jmutex.h" -#include "jthread/jmutexautolock.h" +#include "threading/mutex.h" +#include "threading/mutex_auto_lock.h" #include "util/string.h" std::string QuicktuneValue::getString() @@ -49,12 +49,12 @@ void QuicktuneValue::relativeAdd(float amount) static std::map g_values; static std::vector g_names; -JMutex *g_mutex = NULL; +Mutex *g_mutex = NULL; static void makeMutex() { if(!g_mutex){ - g_mutex = new JMutex(); + g_mutex = new Mutex(); } } @@ -66,7 +66,7 @@ std::vector getQuicktuneNames() QuicktuneValue getQuicktuneValue(const std::string &name) { makeMutex(); - JMutexAutoLock lock(*g_mutex); + MutexAutoLock lock(*g_mutex); std::map::iterator i = g_values.find(name); if(i == g_values.end()){ QuicktuneValue val; @@ -79,7 +79,7 @@ QuicktuneValue getQuicktuneValue(const std::string &name) void setQuicktuneValue(const std::string &name, const QuicktuneValue &val) { makeMutex(); - JMutexAutoLock lock(*g_mutex); + MutexAutoLock lock(*g_mutex); g_values[name] = val; g_values[name].modified = true; } @@ -87,7 +87,7 @@ void setQuicktuneValue(const std::string &name, const QuicktuneValue &val) void updateQuicktuneValue(const std::string &name, QuicktuneValue &val) { makeMutex(); - JMutexAutoLock lock(*g_mutex); + MutexAutoLock lock(*g_mutex); std::map::iterator i = g_values.find(name); if(i == g_values.end()){ g_values[name] = val; diff --git a/src/script/cpp_api/s_async.cpp b/src/script/cpp_api/s_async.cpp index c00b22f98..1e87e59f0 100644 --- a/src/script/cpp_api/s_async.cpp +++ b/src/script/cpp_api/s_async.cpp @@ -47,32 +47,31 @@ AsyncEngine::~AsyncEngine() // Request all threads to stop for (std::vector::iterator it = workerThreads.begin(); it != workerThreads.end(); it++) { - (*it)->Stop(); + (*it)->stop(); } // Wake up all threads for (std::vector::iterator it = workerThreads.begin(); it != workerThreads.end(); it++) { - jobQueueCounter.Post(); + jobQueueCounter.post(); } // Wait for threads to finish for (std::vector::iterator it = workerThreads.begin(); it != workerThreads.end(); it++) { - (*it)->Wait(); + (*it)->wait(); } // Force kill all threads for (std::vector::iterator it = workerThreads.begin(); it != workerThreads.end(); it++) { - (*it)->Kill(); delete *it; } - jobQueueMutex.Lock(); + jobQueueMutex.lock(); jobQueue.clear(); - jobQueueMutex.Unlock(); + jobQueueMutex.unlock(); workerThreads.clear(); } @@ -92,16 +91,17 @@ void AsyncEngine::initialize(unsigned int numEngines) initDone = true; for (unsigned int i = 0; i < numEngines; i++) { - AsyncWorkerThread *toAdd = new AsyncWorkerThread(this, i); + AsyncWorkerThread *toAdd = new AsyncWorkerThread(this, + std::string("AsyncWorker-") + itos(i)); workerThreads.push_back(toAdd); - toAdd->Start(); + toAdd->start(); } } /******************************************************************************/ unsigned int AsyncEngine::queueAsyncJob(std::string func, std::string params) { - jobQueueMutex.Lock(); + jobQueueMutex.lock(); LuaJobInfo toAdd; toAdd.id = jobIdCounter++; toAdd.serializedFunction = func; @@ -109,9 +109,9 @@ unsigned int AsyncEngine::queueAsyncJob(std::string func, std::string params) jobQueue.push_back(toAdd); - jobQueueCounter.Post(); + jobQueueCounter.post(); - jobQueueMutex.Unlock(); + jobQueueMutex.unlock(); return toAdd.id; } @@ -119,8 +119,8 @@ unsigned int AsyncEngine::queueAsyncJob(std::string func, std::string params) /******************************************************************************/ LuaJobInfo AsyncEngine::getJob() { - jobQueueCounter.Wait(); - jobQueueMutex.Lock(); + jobQueueCounter.wait(); + jobQueueMutex.lock(); LuaJobInfo retval; retval.valid = false; @@ -130,7 +130,7 @@ LuaJobInfo AsyncEngine::getJob() jobQueue.pop_front(); retval.valid = true; } - jobQueueMutex.Unlock(); + jobQueueMutex.unlock(); return retval; } @@ -138,16 +138,16 @@ LuaJobInfo AsyncEngine::getJob() /******************************************************************************/ void AsyncEngine::putJobResult(LuaJobInfo result) { - resultQueueMutex.Lock(); + resultQueueMutex.lock(); resultQueue.push_back(result); - resultQueueMutex.Unlock(); + resultQueueMutex.unlock(); } /******************************************************************************/ void AsyncEngine::step(lua_State *L, int errorhandler) { lua_getglobal(L, "core"); - resultQueueMutex.Lock(); + resultQueueMutex.lock(); while (!resultQueue.empty()) { LuaJobInfo jobDone = resultQueue.front(); resultQueue.pop_front(); @@ -166,14 +166,14 @@ void AsyncEngine::step(lua_State *L, int errorhandler) PCALL_RESL(L, lua_pcall(L, 2, 0, errorhandler)); } - resultQueueMutex.Unlock(); + resultQueueMutex.unlock(); lua_pop(L, 1); // Pop core } /******************************************************************************/ void AsyncEngine::pushFinishedJobs(lua_State* L) { // Result Table - resultQueueMutex.Lock(); + MutexAutoLock l(resultQueueMutex); unsigned int index = 1; lua_createtable(L, resultQueue.size(), 0); @@ -197,8 +197,6 @@ void AsyncEngine::pushFinishedJobs(lua_State* L) { lua_rawseti(L, top, index++); } - - resultQueueMutex.Unlock(); } /******************************************************************************/ @@ -214,10 +212,10 @@ void AsyncEngine::prepareEnvironment(lua_State* L, int top) /******************************************************************************/ AsyncWorkerThread::AsyncWorkerThread(AsyncEngine* jobDispatcher, - unsigned int threadNum) : + const std::string &name) : + Thread(name), ScriptApiBase(), - jobDispatcher(jobDispatcher), - threadnum(threadNum) + jobDispatcher(jobDispatcher) { lua_State *L = getStack(); @@ -235,27 +233,17 @@ AsyncWorkerThread::AsyncWorkerThread(AsyncEngine* jobDispatcher, /******************************************************************************/ AsyncWorkerThread::~AsyncWorkerThread() { - sanity_check(IsRunning() == false); + sanity_check(!isRunning()); } /******************************************************************************/ -void* AsyncWorkerThread::Thread() +void* AsyncWorkerThread::run() { - ThreadStarted(); - - // Register thread for error logging - char number[21]; - snprintf(number, sizeof(number), "%u", threadnum); - log_register_thread(std::string("AsyncWorkerThread_") + number); - - porting::setThreadName((std::string("AsyncWorkTh_") + number).c_str()); - lua_State *L = getStack(); std::string script = getServer()->getBuiltinLuaPath() + DIR_DELIM + "init.lua"; if (!loadScript(script)) { - errorstream - << "AsyncWorkerThread execution of async base environment failed!" + errorstream << "execution of async base environment failed!" << std::endl; abort(); } @@ -267,11 +255,11 @@ void* AsyncWorkerThread::Thread() } // Main loop - while (!StopRequested()) { + while (!stopRequested()) { // Wait for job LuaJobInfo toProcess = jobDispatcher->getJob(); - if (toProcess.valid == false || StopRequested()) { + if (toProcess.valid == false || stopRequested()) { continue; } @@ -310,8 +298,6 @@ void* AsyncWorkerThread::Thread() lua_pop(L, 1); // Pop core - log_deregister_thread(); - return 0; } diff --git a/src/script/cpp_api/s_async.h b/src/script/cpp_api/s_async.h index a6459c18d..7f8c72fae 100644 --- a/src/script/cpp_api/s_async.h +++ b/src/script/cpp_api/s_async.h @@ -24,9 +24,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -#include "jthread/jthread.h" -#include "jthread/jmutex.h" -#include "jthread/jsemaphore.h" +#include "threading/thread.h" +#include "threading/mutex.h" +#include "threading/semaphore.h" #include "debug.h" #include "lua.h" #include "cpp_api/s_base.h" @@ -52,24 +52,15 @@ struct LuaJobInfo { }; // Asynchronous working environment -class AsyncWorkerThread : public JThread, public ScriptApiBase { +class AsyncWorkerThread : public Thread, public ScriptApiBase { public: - /** - * default constructor - * @param pointer to job dispatcher - */ - AsyncWorkerThread(AsyncEngine* jobDispatcher, unsigned int threadNum); - + AsyncWorkerThread(AsyncEngine* jobDispatcher, const std::string &name); virtual ~AsyncWorkerThread(); - void *Thread(); + void *run(); private: AsyncEngine *jobDispatcher; - - // Thread number. Used for debug output - unsigned int threadnum; - }; // Asynchornous thread and job management @@ -148,13 +139,13 @@ private: unsigned int jobIdCounter; // Mutex to protect job queue - JMutex jobQueueMutex; + Mutex jobQueueMutex; // Job queue std::deque jobQueue; // Mutex to protect result queue - JMutex resultQueueMutex; + Mutex resultQueueMutex; // Result queue std::deque resultQueue; @@ -162,7 +153,7 @@ private: std::vector workerThreads; // Counter semaphore for job dispatching - JSemaphore jobQueueCounter; + Semaphore jobQueueCounter; }; #endif // CPP_API_ASYNC_EVENTS_HEADER diff --git a/src/script/cpp_api/s_base.h b/src/script/cpp_api/s_base.h index d653b5bac..744fca2d0 100644 --- a/src/script/cpp_api/s_base.h +++ b/src/script/cpp_api/s_base.h @@ -28,8 +28,8 @@ extern "C" { } #include "irrlichttypes.h" -#include "jthread/jmutex.h" -#include "jthread/jmutexautolock.h" +#include "threading/mutex.h" +#include "threading/mutex_auto_lock.h" #include "common/c_types.h" #include "common/c_internal.h" @@ -108,7 +108,7 @@ protected: void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj); void objectrefGet(lua_State *L, u16 id); - JMutex m_luastackmutex; + Mutex m_luastackmutex; std::string m_last_run_mod; // Stack index of Lua error handler int m_errorhandler; diff --git a/src/script/cpp_api/s_internal.h b/src/script/cpp_api/s_internal.h index 9999a584a..7daf8c03f 100644 --- a/src/script/cpp_api/s_internal.h +++ b/src/script/cpp_api/s_internal.h @@ -34,7 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "debug.h" // assert() class LockChecker { public: - LockChecker(bool* variable) { + LockChecker(bool *variable) { assert(*variable == false); m_variable = variable; @@ -44,7 +44,7 @@ public: *m_variable = false; } private: -bool* m_variable; + bool *m_variable; }; #define SCRIPTAPI_LOCK_CHECK LockChecker(&(this->m_locked)) @@ -53,7 +53,7 @@ bool* m_variable; #endif #define SCRIPTAPI_PRECHECKHEADER \ - JMutexAutoLock(this->m_luastackmutex); \ + MutexAutoLock(this->m_luastackmutex); \ SCRIPTAPI_LOCK_CHECK; \ realityCheck(); \ lua_State *L = getStack(); \ diff --git a/src/server.cpp b/src/server.cpp index dc7b101a6..009ea7b0e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "ban.h" #include "environment.h" #include "map.h" -#include "jthread/jmutexautolock.h" +#include "threading/mutex_auto_lock.h" #include "constants.h" #include "voxel.h" #include "config.h" @@ -71,35 +71,29 @@ public: {} }; -class ServerThread : public JThread +class ServerThread : public Thread { - Server *m_server; - public: ServerThread(Server *server): - JThread(), + Thread("Server"), m_server(server) - { - } + {} - void * Thread(); + void *run(); + +private: + Server *m_server; }; -void *ServerThread::Thread() +void *ServerThread::run() { - log_register_thread("ServerThread"); - DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER m_server->AsyncRunStep(true); - ThreadStarted(); - - porting::setThreadName("ServerThread"); - - while (!StopRequested()) { + while (!stopRequested()) { try { //TimeTaker timer("AsyncRunStep() + Receive()"); @@ -267,8 +261,8 @@ Server::Server( errorstream << std::endl; } - // Lock environment - JMutexAutoLock envlock(m_env_mutex); + //lock environment + MutexAutoLock envlock(m_env_mutex); // Load mapgen params from Settings m_emerge->loadMapgenParams(); @@ -379,7 +373,7 @@ Server::~Server() SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down"); { - JMutexAutoLock envlock(m_env_mutex); + MutexAutoLock envlock(m_env_mutex); // Execute script shutdown hooks m_script->on_shutdown(); @@ -447,14 +441,14 @@ void Server::start(Address bind_addr) << bind_addr.serializeString() <<"..."<Stop(); + m_thread->stop(); // Initialize connection m_con.SetTimeoutMs(30); m_con.Serve(bind_addr); // Start thread - m_thread->Start(); + m_thread->start(); // ASCII art for the win! actionstream @@ -477,9 +471,9 @@ void Server::stop() infostream<<"Server: Stopping and waiting threads"<Stop(); + m_thread->stop(); //m_emergethread.setRun(false); - m_thread->Wait(); + m_thread->wait(); //m_emergethread.stop(); infostream<<"Server: Threads stopped"< 2.0) dtime = 2.0; { - JMutexAutoLock lock(m_step_dtime_mutex); + MutexAutoLock lock(m_step_dtime_mutex); m_step_dtime += dtime; } // Throw if fatal error occurred in thread @@ -521,7 +515,7 @@ void Server::AsyncRunStep(bool initial_step) float dtime; { - JMutexAutoLock lock1(m_step_dtime_mutex); + MutexAutoLock lock1(m_step_dtime_mutex); dtime = m_step_dtime; } @@ -539,7 +533,7 @@ void Server::AsyncRunStep(bool initial_step) //infostream<<"Server::AsyncRunStep(): dtime="<getMaxLagEstimate(); max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes) @@ -590,7 +584,7 @@ void Server::AsyncRunStep(bool initial_step) static const float map_timer_and_unload_dtime = 2.92; if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) { - JMutexAutoLock lock(m_env_mutex); + MutexAutoLock lock(m_env_mutex); // Run Map's timers and unload unused data ScopeProfiler sp(g_profiler, "Server: map timer and unload"); m_env->getMap().timerUpdate(map_timer_and_unload_dtime, @@ -608,7 +602,7 @@ void Server::AsyncRunStep(bool initial_step) { m_liquid_transform_timer -= m_liquid_transform_every; - JMutexAutoLock lock(m_env_mutex); + MutexAutoLock lock(m_env_mutex); ScopeProfiler sp(g_profiler, "Server: liquid transform"); @@ -669,9 +663,9 @@ void Server::AsyncRunStep(bool initial_step) */ { //infostream<<"Server: Checking added and deleted active objects"< clients = m_clients.getClientList(); ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs"); @@ -792,14 +786,14 @@ void Server::AsyncRunStep(bool initial_step) << added_objects.size() << " added, " << "packet size is " << pktSize << std::endl; } - m_clients.Unlock(); + m_clients.unlock(); } /* Send object messages */ { - JMutexAutoLock envlock(m_env_mutex); + MutexAutoLock envlock(m_env_mutex); ScopeProfiler sp(g_profiler, "Server: sending object messages"); // Key = object id @@ -825,7 +819,7 @@ void Server::AsyncRunStep(bool initial_step) message_list->push_back(aom); } - m_clients.Lock(); + m_clients.lock(); std::map clients = m_clients.getClientList(); // Route data to every client for (std::map::iterator @@ -876,7 +870,7 @@ void Server::AsyncRunStep(bool initial_step) SendActiveObjectMessages(client->peer_id, unreliable_data, false); } } - m_clients.Unlock(); + m_clients.unlock(); // Clear buffered_messages for(std::map* >::iterator @@ -891,7 +885,7 @@ void Server::AsyncRunStep(bool initial_step) */ { // We will be accessing the environment - JMutexAutoLock lock(m_env_mutex); + MutexAutoLock lock(m_env_mutex); // Don't send too many at a time //u32 count = 0; @@ -1012,7 +1006,7 @@ void Server::AsyncRunStep(bool initial_step) if(counter >= g_settings->getFloat("server_map_save_interval")) { counter = 0.0; - JMutexAutoLock lock(m_env_mutex); + MutexAutoLock lock(m_env_mutex); ScopeProfiler sp(g_profiler, "Server: saving stuff"); @@ -1068,7 +1062,7 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id) { std::string playername = ""; PlayerSAO *playersao = NULL; - m_clients.Lock(); + m_clients.lock(); try { RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone); if (client != NULL) { @@ -1076,10 +1070,10 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id) playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version); } } catch (std::exception &e) { - m_clients.Unlock(); + m_clients.unlock(); throw; } - m_clients.Unlock(); + m_clients.unlock(); RemotePlayer *player = static_cast(m_env->getPlayer(playername.c_str())); @@ -1174,7 +1168,7 @@ void Server::ProcessData(NetworkPacket *pkt) { DSTACK(__FUNCTION_NAME); // Environment is locked first. - JMutexAutoLock envlock(m_env_mutex); + MutexAutoLock envlock(m_env_mutex); ScopeProfiler sp(g_profiler, "Server::ProcessData"); u32 peer_id = pkt->getPeerId(); @@ -1356,14 +1350,14 @@ void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend) void Server::SetBlocksNotSent(std::map& block) { std::vector clients = m_clients.getClientIDs(); - m_clients.Lock(); + m_clients.lock(); // Set the modified blocks unsent for all the clients for (std::vector::iterator i = clients.begin(); i != clients.end(); ++i) { if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i)) client->SetBlocksNotSent(block); } - m_clients.Unlock(); + m_clients.unlock(); } void Server::peerAdded(con::Peer *peer) @@ -1413,11 +1407,11 @@ bool Server::getClientInfo( ) { *state = m_clients.getClientState(peer_id); - m_clients.Lock(); + m_clients.lock(); RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid); if (client == NULL) { - m_clients.Unlock(); + m_clients.unlock(); return false; } @@ -1430,7 +1424,7 @@ bool Server::getClientInfo( *patch = client->getPatch(); *vers_string = client->getPatch(); - m_clients.Unlock(); + m_clients.unlock(); return true; } @@ -2098,7 +2092,7 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id, } NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1); - m_clients.Lock(); + m_clients.lock(); RemoteClient* client = m_clients.lockedGetClientNoEx(*i); if (client != 0) { pkt << p << n.param0 << n.param1 << n.param2 @@ -2112,7 +2106,7 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id, } } } - m_clients.Unlock(); + m_clients.unlock(); // Send as reliable if (pkt.getSize() > 0) @@ -2123,13 +2117,13 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id, void Server::setBlockNotSent(v3s16 p) { std::vector clients = m_clients.getClientIDs(); - m_clients.Lock(); + m_clients.lock(); for(std::vector::iterator i = clients.begin(); i != clients.end(); ++i) { RemoteClient *client = m_clients.lockedGetClientNoEx(*i); client->SetBlockNotSent(p); } - m_clients.Unlock(); + m_clients.unlock(); } void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version) @@ -2158,7 +2152,7 @@ void Server::SendBlocks(float dtime) { DSTACK(__FUNCTION_NAME); - JMutexAutoLock envlock(m_env_mutex); + MutexAutoLock envlock(m_env_mutex); //TODO check if one big lock could be faster then multiple small ones ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients"); @@ -2172,7 +2166,7 @@ void Server::SendBlocks(float dtime) std::vector clients = m_clients.getClientIDs(); - m_clients.Lock(); + m_clients.lock(); for(std::vector::iterator i = clients.begin(); i != clients.end(); ++i) { RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active); @@ -2183,7 +2177,7 @@ void Server::SendBlocks(float dtime) total_sending += client->SendingCount(); client->GetNextBlocks(m_env,m_emerge, dtime, queue); } - m_clients.Unlock(); + m_clients.unlock(); } // Sort. @@ -2191,7 +2185,7 @@ void Server::SendBlocks(float dtime) // Lowest is most important. std::sort(queue.begin(), queue.end()); - m_clients.Lock(); + m_clients.lock(); for(u32 i=0; iSentBlock(q.pos); total_sending++; } - m_clients.Unlock(); + m_clients.unlock(); } void Server::fillMediaCache() @@ -2702,7 +2696,7 @@ void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason) } } { - JMutexAutoLock env_lock(m_env_mutex); + MutexAutoLock env_lock(m_env_mutex); m_clients.DeleteClient(peer_id); } } diff --git a/src/server.h b/src/server.h index d16230967..26ec3ab73 100644 --- a/src/server.h +++ b/src/server.h @@ -516,7 +516,7 @@ private: // Environment ServerEnvironment *m_env; - JMutex m_env_mutex; + Mutex m_env_mutex; // server connection con::Connection m_con; @@ -557,7 +557,7 @@ private: // A buffer for time steps // step() increments and AsyncRunStep() run by m_thread reads it. float m_step_dtime; - JMutex m_step_dtime_mutex; + Mutex m_step_dtime_mutex; // current server step lag counter float m_lag; diff --git a/src/settings.cpp b/src/settings.cpp index e95bd436d..3d4d56fa3 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "irrlichttypes_bloated.h" #include "exceptions.h" -#include "jthread/jmutexautolock.h" +#include "threading/mutex_auto_lock.h" #include "strfnd.h" #include #include @@ -56,8 +56,8 @@ Settings & Settings::operator = (const Settings &other) if (&other == this) return *this; - JMutexAutoLock lock(m_mutex); - JMutexAutoLock lock2(other.m_mutex); + MutexAutoLock lock(m_mutex); + MutexAutoLock lock2(other.m_mutex); clearNoLock(); updateNoLock(other); @@ -155,7 +155,7 @@ bool Settings::readConfigFile(const char *filename) bool Settings::parseConfigLines(std::istream &is, const std::string &end) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); std::string line, name, value; @@ -194,7 +194,7 @@ bool Settings::parseConfigLines(std::istream &is, const std::string &end) void Settings::writeLines(std::ostream &os, u32 tab_depth) const { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); for (std::map::const_iterator it = m_settings.begin(); @@ -298,7 +298,7 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os, bool Settings::updateConfigFile(const char *filename) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); std::ifstream is(filename); std::ostringstream os(std::ios_base::binary); @@ -379,7 +379,7 @@ bool Settings::parseCommandLine(int argc, char *argv[], const SettingsEntry &Settings::getEntry(const std::string &name) const { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); std::map::const_iterator n; if ((n = m_settings.find(name)) == m_settings.end()) { @@ -562,7 +562,7 @@ bool Settings::getNoiseParamsFromGroup(const std::string &name, bool Settings::exists(const std::string &name) const { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); return (m_settings.find(name) != m_settings.end() || m_defaults.find(name) != m_defaults.end()); @@ -742,7 +742,7 @@ bool Settings::setEntry(const std::string &name, const void *data, return false; { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); SettingsEntry &entry = set_default ? m_defaults[name] : m_settings[name]; old_group = entry.group; @@ -878,7 +878,7 @@ bool Settings::setNoiseParams(const std::string &name, bool Settings::remove(const std::string &name) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); delete m_settings[name].group; return m_settings.erase(name); @@ -887,13 +887,13 @@ bool Settings::remove(const std::string &name) void Settings::clear() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); clearNoLock(); } void Settings::clearDefaults() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); clearDefaultsNoLock(); } @@ -902,7 +902,7 @@ void Settings::updateValue(const Settings &other, const std::string &name) if (&other == this) return; - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); try { std::string val = other.get(name); @@ -918,8 +918,8 @@ void Settings::update(const Settings &other) if (&other == this) return; - JMutexAutoLock lock(m_mutex); - JMutexAutoLock lock2(other.m_mutex); + MutexAutoLock lock(m_mutex); + MutexAutoLock lock2(other.m_mutex); updateNoLock(other); } @@ -982,13 +982,13 @@ void Settings::clearDefaultsNoLock() void Settings::registerChangedCallback(std::string name, setting_changed_callback cbf, void *userdata) { - JMutexAutoLock lock(m_callbackMutex); + MutexAutoLock lock(m_callbackMutex); m_callbacks[name].push_back(std::make_pair(cbf, userdata)); } void Settings::deregisterChangedCallback(std::string name, setting_changed_callback cbf, void *userdata) { - JMutexAutoLock lock(m_callbackMutex); + MutexAutoLock lock(m_callbackMutex); std::map > >::iterator iterToVector = m_callbacks.find(name); if (iterToVector != m_callbacks.end()) { @@ -1004,7 +1004,7 @@ void Settings::deregisterChangedCallback(std::string name, setting_changed_callb void Settings::doCallbacks(const std::string name) { - JMutexAutoLock lock(m_callbackMutex); + MutexAutoLock lock(m_callbackMutex); std::map > >::iterator iterToVector = m_callbacks.find(name); if (iterToVector != m_callbacks.end()) { diff --git a/src/settings.h b/src/settings.h index d41f134cd..80d41fd79 100644 --- a/src/settings.h +++ b/src/settings.h @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_bloated.h" #include "util/string.h" -#include "jthread/jmutex.h" +#include "threading/mutex.h" #include #include #include @@ -225,8 +225,8 @@ private: std::map > > m_callbacks; - mutable JMutex m_callbackMutex; - mutable JMutex m_mutex; // All methods that access m_settings/m_defaults directly should lock this. + mutable Mutex m_callbackMutex; + mutable Mutex m_mutex; // All methods that access m_settings/m_defaults directly should lock this. }; diff --git a/src/shader.cpp b/src/shader.cpp index 7e4f40810..e441883fb 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -328,7 +328,7 @@ private: // The first position contains a dummy shader. std::vector m_shaderinfo_cache; // The former container is behind this mutex - JMutex m_shaderinfo_cache_mutex; + Mutex m_shaderinfo_cache_mutex; // Queued shader fetches (to be processed by the main thread) RequestQueue m_get_shader_queue; @@ -469,7 +469,7 @@ u32 ShaderSource::getShaderIdDirect(const std::string &name, Add shader to caches (add dummy shaders too) */ - JMutexAutoLock lock(m_shaderinfo_cache_mutex); + MutexAutoLock lock(m_shaderinfo_cache_mutex); u32 id = m_shaderinfo_cache.size(); m_shaderinfo_cache.push_back(info); @@ -483,7 +483,7 @@ u32 ShaderSource::getShaderIdDirect(const std::string &name, ShaderInfo ShaderSource::getShaderInfo(u32 id) { - JMutexAutoLock lock(m_shaderinfo_cache_mutex); + MutexAutoLock lock(m_shaderinfo_cache_mutex); if(id >= m_shaderinfo_cache.size()) return ShaderInfo(); @@ -511,7 +511,7 @@ void ShaderSource::insertSourceShader(const std::string &name_of_shader, void ShaderSource::rebuildShaders() { - JMutexAutoLock lock(m_shaderinfo_cache_mutex); + MutexAutoLock lock(m_shaderinfo_cache_mutex); /*// Oh well... just clear everything, they'll load sometime. m_shaderinfo_cache.clear(); diff --git a/src/threading/CMakeLists.txt b/src/threading/CMakeLists.txt new file mode 100644 index 000000000..f3d0efc18 --- /dev/null +++ b/src/threading/CMakeLists.txt @@ -0,0 +1,6 @@ +set(JTHREAD_SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/mutex.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/thread.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/semaphore.cpp + PARENT_SCOPE) + diff --git a/src/threading/atomic.h b/src/threading/atomic.h new file mode 100644 index 000000000..486bc7950 --- /dev/null +++ b/src/threading/atomic.h @@ -0,0 +1,96 @@ +/* +Minetest +Copyright (C) 2015 ShadowNinja + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef THREADING_ATOMIC_H +#define THREADING_ATOMIC_H + + +#if __cplusplus >= 201103L + #include + template using Atomic = std::atomic; +#else + +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) +#define CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) +#if GCC_VERSION >= 407 || CLANG_VERSION >= 302 + #define ATOMIC_LOAD(T, v) return __atomic_load_n(&(v), __ATOMIC_SEQ_CST) + #define ATOMIC_STORE(T, v, x) __atomic_store (&(v), &(x), __ATOMIC_SEQ_CST); return x + #define ATOMIC_ADD_EQ(T, v, x) return __atomic_add_fetch(&(v), (x), __ATOMIC_SEQ_CST) + #define ATOMIC_SUB_EQ(T, v, x) return __atomic_sub_fetch(&(v), (x), __ATOMIC_SEQ_CST) + #define ATOMIC_POST_INC(T, v) return __atomic_fetch_add(&(v), 1, __ATOMIC_SEQ_CST) + #define ATOMIC_POST_DEC(T, v) return __atomic_fetch_sub(&(v), 1, __ATOMIC_SEQ_CST) +#else + #define ATOMIC_USE_LOCK + #include "threading/mutex.h" + + #define ATOMIC_LOCK_OP(T, op) do { \ + mutex.lock(); \ + T _val = (op); \ + mutex.unlock(); \ + return _val; \ + } while (0) + #define ATOMIC_LOAD(T, v) \ + if (sizeof(T) <= sizeof(void*)) return v; \ + else ATOMIC_LOCK_OP(T, v); + #define ATOMIC_STORE(T, v, x) \ + if (sizeof(T) <= sizeof(void*)) return v = x; \ + else ATOMIC_LOCK_OP(T, v = x); +# if GCC_VERSION >= 401 + #define ATOMIC_ADD_EQ(T, v, x) return __sync_add_and_fetch(&(v), (x)) + #define ATOMIC_SUB_EQ(T, v, x) return __sync_sub_and_fetch(&(v), (x)) + #define ATOMIC_POST_INC(T, v) return __sync_fetch_and_add(&(v), 1) + #define ATOMIC_POST_DEC(T, v) return __sync_fetch_and_sub(&(v), 1) +# else + #define ATOMIC_ADD_EQ(T, v, x) ATOMIC_LOCK_OP(T, v += x) + #define ATOMIC_SUB_EQ(T, v, x) ATOMIC_LOCK_OP(T, v -= x) + #define ATOMIC_POST_INC(T, v) ATOMIC_LOCK_OP(T, v++) + #define ATOMIC_POST_DEC(T, v) ATOMIC_LOCK_OP(T, v--) +# endif +#endif + + +template +class Atomic +{ + // Like C++11 std::enable_if, but defaults to char since C++03 doesn't support SFINAE + template struct enable_if { typedef char type; }; + template struct enable_if { typedef T_ type; }; +public: + Atomic(const T &v=0) : val(v) {} + + operator T () { ATOMIC_LOAD(T, val); } + T operator = (T x) { ATOMIC_STORE(T, val, x); } + T operator += (T x) { ATOMIC_ADD_EQ(T, val, x); } + T operator -= (T x) { ATOMIC_SUB_EQ(T, val, x); } + T operator ++ () { return *this += 1; } + T operator -- () { return *this -= 1; } + T operator ++ (int) { ATOMIC_POST_INC(T, val); } + T operator -- (int) { ATOMIC_POST_DEC(T, val); } + +private: + volatile T val; +#ifdef ATOMIC_USE_LOCK + typename enable_if::type mutex; +#endif +}; + +#endif // C++11 + +#endif + diff --git a/src/threading/event.h b/src/threading/event.h new file mode 100644 index 000000000..0105630e5 --- /dev/null +++ b/src/threading/event.h @@ -0,0 +1,57 @@ +/* +This file is a part of the JThread package, which contains some object- +oriented thread wrappers for different thread implementations. + +Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#ifndef THREADING_EVENT_H +#define THREADING_EVENT_H + +#ifdef _WIN32 + #include +#else + #include "threading/semaphore.h" +#endif + + +class Event { +public: +#ifdef _WIN32 + Event() { event = CreateEvent(NULL, false, false, NULL); } + ~Event() { CloseHandle(event); } + void wait() { WaitForSingleObject(event, INFINITE); } + void signal() { SetEvent(event); } +#else + void wait() { sem.wait(); } + void signal() { sem.post(); } +#endif + +private: +#ifdef _WIN32 + HANDLE event; +#else + Semaphore sem; +#endif +}; + +#endif + diff --git a/src/threading/mutex.cpp b/src/threading/mutex.cpp new file mode 100644 index 000000000..eb1c7d61d --- /dev/null +++ b/src/threading/mutex.cpp @@ -0,0 +1,83 @@ +/* +This file is a part of the JThread package, which contains some object- +oriented thread wrappers for different thread implementations. + +Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +// Windows std::mutex is much slower than the critical section API +#if __cplusplus < 201103L || defined(_WIN32) + +#include "threading/mutex.h" + +#ifndef _WIN32 + #include +#endif + +#define UNUSED(expr) do { (void)(expr); } while (0) + + +Mutex::Mutex() +{ +#ifdef _WIN32 + InitializeCriticalSection(&mutex); +#else + int ret = pthread_mutex_init(&mutex, NULL); + assert(!ret); + UNUSED(ret); +#endif +} + +Mutex::~Mutex() +{ +#ifdef _WIN32 + DeleteCriticalSection(&mutex); +#else + int ret = pthread_mutex_destroy(&mutex); + assert(!ret); + UNUSED(ret); +#endif +} + +void Mutex::lock() +{ +#ifdef _WIN32 + EnterCriticalSection(&mutex); +#else + int ret = pthread_mutex_lock(&mutex); + assert(!ret); + UNUSED(ret); +#endif +} + +void Mutex::unlock() +{ +#ifdef _WIN32 + LeaveCriticalSection(&mutex); +#else + int ret = pthread_mutex_unlock(&mutex); + assert(!ret); + UNUSED(ret); +#endif +} + +#endif + diff --git a/src/threading/mutex.h b/src/threading/mutex.h new file mode 100644 index 000000000..4c9af71bf --- /dev/null +++ b/src/threading/mutex.h @@ -0,0 +1,66 @@ +/* +This file is a part of the JThread package, which contains some object- +oriented thread wrappers for different thread implementations. + +Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#ifndef THREADING_MUTEX_H +#define THREADING_MUTEX_H + +// Windows std::mutex is much slower than the critical section API +#if __cplusplus >= 201103L && !defined(_WIN32) + #include + using Mutex = std::mutex; +#else + +#ifdef _WIN32 + #ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0501 + #endif + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include +#else // pthread + #include +#endif + + +class Mutex +{ +public: + Mutex(); + ~Mutex(); + void lock(); + void unlock(); + +private: +#ifdef _WIN32 + CRITICAL_SECTION mutex; +#else // pthread + pthread_mutex_t mutex; +#endif +}; + +#endif // C++11 + +#endif diff --git a/src/threading/mutex_auto_lock.h b/src/threading/mutex_auto_lock.h new file mode 100644 index 000000000..1c39349e5 --- /dev/null +++ b/src/threading/mutex_auto_lock.h @@ -0,0 +1,50 @@ +/* +This file is a part of the JThread package, which contains some object- +oriented thread wrappers for different thread implementations. + +Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#ifndef THREADING_MUTEX_AUTO_LOCK_H +#define THREADING_MUTEX_AUTO_LOCK_H + +#if __cplusplus >= 201103L + #include + using MutexAutoLock = std::lock_guard; +#else + +#include "threading/mutex.h" + + +class MutexAutoLock +{ +public: + MutexAutoLock(Mutex &m) : mutex(m) { mutex.lock(); } + ~MutexAutoLock() { mutex.unlock(); } + +private: + Mutex &mutex; +}; + +#endif + +#endif + diff --git a/src/threading/semaphore.cpp b/src/threading/semaphore.cpp new file mode 100644 index 000000000..00332eaa0 --- /dev/null +++ b/src/threading/semaphore.cpp @@ -0,0 +1,161 @@ +/* +Minetest +Copyright (C) 2013 sapier + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "threading/semaphore.h" + +#include +#include +#include + +#define UNUSED(expr) do { (void)(expr); } while (0) + +#ifdef _WIN32 + #define MAX_SEMAPHORE_COUNT LONG_MAX - 1 +#else + #include + #include + #include + #if defined(__MACH__) && defined(__APPLE__) + #include + #include + #include + #include + #include + + #undef sem_t + #undef sem_init + #undef sem_wait + #undef sem_post + #undef sem_destroy + #define sem_t semaphore_t + #define sem_init(s, p, c) semaphore_create(mach_task_self(), (s), 0, (c)) + #define sem_wait(s) semaphore_wait(*(s)) + #define sem_post(s) semaphore_signal(*(s)) + #define sem_destroy(s) semaphore_destroy(mach_task_self(), *(s)) + #endif +#endif + + +Semaphore::Semaphore(int val) +{ +#ifdef _WIN32 + semaphore = CreateSemaphore(NULL, val, MAX_SEMAPHORE_COUNT, NULL); +#else + int ret = sem_init(&semaphore, 0, val); + assert(!ret); + UNUSED(ret); +#endif +} + + +Semaphore::~Semaphore() +{ +#ifdef _WIN32 + CloseHandle(semaphore); +#else + int ret = sem_destroy(&semaphore); +#ifdef __ANDROID__ + // Workaround for broken bionic semaphore implementation! + assert(!ret || errno == EBUSY); +#else + assert(!ret); +#endif + UNUSED(ret); +#endif +} + + +void Semaphore::post(unsigned int num) +{ + assert(num > 0); +#ifdef _WIN32 + ReleaseSemaphore(semaphore, num, NULL); +#else + for (unsigned i = 0; i < num; i++) { + int ret = sem_post(&semaphore); + assert(!ret); + UNUSED(ret); + } +#endif +} + + +void Semaphore::wait() +{ +#ifdef _WIN32 + WaitForSingleObject(semaphore, INFINITE); +#else + int ret = sem_wait(&semaphore); + assert(!ret); + UNUSED(ret); +#endif +} + + +bool Semaphore::wait(unsigned int time_ms) +{ +#ifdef _WIN32 + unsigned int ret = WaitForSingleObject(semaphore, time_ms); + + if (ret == WAIT_OBJECT_0) { + return true; + } else { + assert(ret == WAIT_TIMEOUT); + return false; + } +#else +# if defined(__MACH__) && defined(__APPLE__) + mach_timespec_t wait_time; + wait_time.tv_sec = time_ms / 1000; + wait_time.tv_nsec = 1000000 * (time_ms % 1000); + + errno = 0; + int ret = semaphore_timedwait(semaphore, wait_time); + switch (ret) { + case KERN_OPERATION_TIMED_OUT: + errno = ETIMEDOUT; + break; + case KERN_ABORTED: + errno = EINTR; + break; + default: + if (ret) + errno = EINVAL; + } +# else + struct timespec wait_time; + struct timeval now; + + if (gettimeofday(&now, NULL) == -1) { + std::cerr << "Semaphore::wait(ms): Unable to get time with gettimeofday!" << std::endl; + abort(); + } + + wait_time.tv_nsec = ((time_ms % 1000) * 1000 * 1000) + (now.tv_usec * 1000); + wait_time.tv_sec = (time_ms / 1000) + (wait_time.tv_nsec / (1000 * 1000 * 1000)) + now.tv_sec; + wait_time.tv_nsec %= 1000 * 1000 * 1000; + + int ret = sem_timedwait(&semaphore, &wait_time); +# endif + + assert(!ret || (errno == ETIMEDOUT || errno == EINTR)); + return !ret; +#endif +} + diff --git a/src/threading/semaphore.h b/src/threading/semaphore.h new file mode 100644 index 000000000..58d758f2e --- /dev/null +++ b/src/threading/semaphore.h @@ -0,0 +1,52 @@ +/* +Minetest +Copyright (C) 2013 sapier + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef THREADING_SEMAPHORE_H +#define THREADING_SEMAPHORE_H + +#if defined(_WIN32) + #include +#elif defined(__MACH__) && defined(__APPLE__) + #include +#else + #include +#endif + + +class Semaphore { +public: + Semaphore(int val=0); + ~Semaphore(); + + void post(unsigned int num=1); + void wait(); + bool wait(unsigned int time_ms); + +private: +#if defined(WIN32) + HANDLE semaphore; +#elif defined(__MACH__) && defined(__APPLE__) + semaphore_t semaphore; +#else + sem_t semaphore; +#endif +}; + +#endif + diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp new file mode 100644 index 000000000..a1cb720af --- /dev/null +++ b/src/threading/thread.cpp @@ -0,0 +1,354 @@ +/* +This file is a part of the JThread package, which contains some object- +oriented thread wrappers for different thread implementations. + +Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#include "threading/thread.h" +#include "threading/mutex_auto_lock.h" +#include "log.h" + +#if __cplusplus >= 201103L + #include +#else + #define UNUSED(expr) do { (void)(expr); } while (0) +# ifdef _WIN32 +# ifndef _WIN32_WCE + #include +# endif +# else + #include + #include + #include + #include + + // For getNumberOfProcessors + #include +# if defined(__FreeBSD__) || defined(__APPLE__) + #include + #include +# elif defined(_GNU_SOURCE) + #include +# endif +# endif +#endif + + +// For setName +#if defined(linux) || defined(__linux) + #include +#elif defined(__FreeBSD__) || defined(__OpenBSD__) + #include +#elif defined(_MSC_VER) + struct THREADNAME_INFO { + DWORD dwType; // Must be 0x1000 + LPCSTR szName; // Pointer to name (in user addr space) + DWORD dwThreadID; // Thread ID (-1=caller thread) + DWORD dwFlags; // Reserved for future use, must be zero + }; +#endif + +// For bindToProcessor +#if __FreeBSD_version >= 702106 + typedef cpuset_t cpu_set_t; +#elif defined(__linux) || defined(linux) + #include +#elif defined(__sun) || defined(sun) + #include + #include + #include +#elif defined(_AIX) + #include +#elif defined(__APPLE__) + #include + #include +#endif + + +Thread::Thread(const std::string &name) : + name(name), + retval(NULL), + request_stop(false), + running(false) +#if __cplusplus >= 201103L + , thread(NULL) +#elif !defined(_WIN32) + , started(false) +#endif +{} + + +void Thread::wait() +{ +#if __cplusplus >= 201103L + if (!thread || !thread->joinable()) + return; + thread->join(); +#elif defined(_WIN32) + if (!running) + return; + WaitForSingleObject(thread, INFINITE); +#else // pthread + void *status; + if (!started) + return; + int ret = pthread_join(thread, &status); + assert(!ret); + UNUSED(ret); + started = false; +#endif +} + + +bool Thread::start() +{ + if (running) + return false; + request_stop = false; + +#if __cplusplus >= 201103L + MutexAutoLock l(continue_mutex); + thread = new std::thread(theThread, this); +#elif defined(_WIN32) + MutexAutoLock l(continue_mutex); +# ifdef _WIN32_WCE + thread = CreateThread(NULL, 0, theThread, this, 0, &thread_id); +# else + thread = (HANDLE)_beginthreadex(NULL, 0, theThread, this, 0, &thread_id); +# endif + if (!thread) + return false; +#else + int status; + + MutexAutoLock l(continue_mutex); + + status = pthread_create(&thread, NULL, theThread, this); + + if (status) + return false; +#endif + +#if __cplusplus < 201103L + // Wait until running + while (!running) { +# ifdef _WIN32 + Sleep(1); + } +# else + struct timespec req, rem; + req.tv_sec = 0; + req.tv_nsec = 1000000; + nanosleep(&req, &rem); + } + started = true; +# endif +#endif + return true; +} + + +bool Thread::kill() +{ +#ifdef _WIN32 + if (!running) + return false; + TerminateThread(getThreadHandle(), 0); + CloseHandle(getThreadHandle()); +#else + if (!running) { + wait(); + return false; + } +# ifdef __ANDROID__ + pthread_kill(getThreadHandle(), SIGKILL); +# else + pthread_cancel(getThreadHandle()); +# endif + wait(); +#endif +#if __cplusplus >= 201103L + delete thread; +#endif + running = false; + return true; +} + + +bool Thread::isSameThread() +{ +#if __cplusplus >= 201103L + return thread->get_id() == std::this_thread::get_id(); +#elif defined(_WIN32) + return GetCurrentThreadId() == thread_id; +#else + return pthread_equal(pthread_self(), thread); +#endif +} + + +#if __cplusplus >= 201103L +void Thread::theThread(Thread *th) +#elif defined(_WIN32_WCE) +DWORD WINAPI Thread::theThread(void *param) +#elif defined(_WIN32) +UINT __stdcall Thread::theThread(void *param) +#else +void *Thread::theThread(void *param) +#endif +{ +#if __cplusplus < 201103L + Thread *th = static_cast(param); +#endif + th->running = true; + + th->setName(); + log_register_thread(th->name); + + th->retval = th->run(); + + log_deregister_thread(); + + th->running = false; +#if __cplusplus < 201103L +# ifdef _WIN32 + CloseHandle(th->thread); +# endif + return NULL; +#endif +} + + +void Thread::setName(const std::string &name) +{ +#if defined(linux) || defined(__linux) + /* It would be cleaner to do this with pthread_setname_np, + * which was added to glibc in version 2.12, but some major + * distributions are still runing 2.11 and previous versions. + */ + prctl(PR_SET_NAME, name.c_str()); +#elif defined(__FreeBSD__) || defined(__OpenBSD__) + pthread_set_name_np(pthread_self(), name.c_str()); +#elif defined(__NetBSD__) + pthread_setname_np(pthread_self(), name.c_str()); +#elif defined(__APPLE__) + pthread_setname_np(name.c_str()); +#elif defined(_MSC_VER) + // Windows itself doesn't support thread names, + // but the MSVC debugger does... + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name.c_str(); + info.dwThreadID = -1; + info.dwFlags = 0; + __try { + RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR *)&info); + } __except (EXCEPTION_CONTINUE_EXECUTION) { + } +#elif defined(_WIN32) || defined(__GNU__) + // These platforms are known to not support thread names. + // Silently ignore the request. +#else + #warning "Unrecognized platform, thread names will not be available." +#endif +} + + +unsigned int Thread::getNumberOfProcessors() +{ +#if __cplusplus >= 201103L + return std::thread::hardware_concurrency(); +#elif defined(_SC_NPROCESSORS_ONLN) + return sysconf(_SC_NPROCESSORS_ONLN); +#elif defined(__FreeBSD__) || defined(__APPLE__) + unsigned int len, count; + len = sizeof(count); + return sysctlbyname("hw.ncpu", &count, &len, NULL, 0); +#elif defined(_GNU_SOURCE) + return get_nprocs(); +#elif defined(_WIN32) + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; +#elif defined(PTW32_VERSION) || defined(__hpux) + return pthread_num_processors_np(); +#else + return 1; +#endif +} + + +bool Thread::bindToProcessor(unsigned int num) +{ +#if defined(__ANDROID__) + return false; +#elif defined(_WIN32) + return SetThreadAffinityMask(getThreadHandle(), 1 << num); +#elif __FreeBSD_version >= 702106 || defined(__linux) || defined(linux) + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(num, &cpuset); + return pthread_setaffinity_np(getThreadHandle(), sizeof(cpuset), + &cpuset) == 0; +#elif defined(__sun) || defined(sun) + return processor_bind(P_LWPID, MAKE_LWPID_PTHREAD(getThreadHandle()), + num, NULL) == 0 +#elif defined(_AIX) + return bindprocessor(BINDTHREAD, (tid_t) getThreadHandle(), pnumber) == 0; +#elif defined(__hpux) || defined(hpux) + pthread_spu_t answer; + + return pthread_processor_bind_np(PTHREAD_BIND_ADVISORY_NP, + &answer, num, getThreadHandle()) == 0; +#elif defined(__APPLE__) + struct thread_affinity_policy tapol; + + thread_port_t threadport = pthread_mach_thread_np(getThreadHandle()); + tapol.affinity_tag = num + 1; + return thread_policy_set(threadport, THREAD_AFFINITY_POLICY, + (thread_policy_t)&tapol, + THREAD_AFFINITY_POLICY_COUNT) == KERN_SUCCESS; +#else + return false; +#endif +} + + +bool Thread::setPriority(int prio) +{ +#if defined(_WIN32) + return SetThreadPriority(getThreadHandle(), prio); +#else + struct sched_param sparam; + int policy; + + if (pthread_getschedparam(getThreadHandle(), &policy, &sparam) != 0) + return false; + + int min = sched_get_priority_min(policy); + int max = sched_get_priority_max(policy); + + sparam.sched_priority = min + prio * (max - min) / THREAD_PRIORITY_HIGHEST; + return pthread_setschedparam(getThreadHandle(), policy, &sparam) == 0; +#endif +} + diff --git a/src/threading/thread.h b/src/threading/thread.h new file mode 100644 index 000000000..275bc9b6d --- /dev/null +++ b/src/threading/thread.h @@ -0,0 +1,119 @@ +/* +This file is a part of the JThread package, which contains some object- +oriented thread wrappers for different thread implementations. + +Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com) + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +*/ + +#ifndef THREADING_THREAD_H +#define THREADING_THREAD_H + +#include "threading/atomic.h" +#include "threading/mutex.h" + +#include +#if __cplusplus >= 201103L + #include +#endif + +#ifndef _WIN32 +enum { + THREAD_PRIORITY_LOWEST, + THREAD_PRIORITY_BELOW_NORMAL, + THREAD_PRIORITY_NORMAL, + THREAD_PRIORITY_ABOVE_NORMAL, + THREAD_PRIORITY_HIGHEST, +}; +#endif + + +class Thread +{ +public: + Thread(const std::string &name="Unnamed"); + virtual ~Thread() { kill(); } + + bool start(); + inline void stop() { request_stop = true; } + bool kill(); + + inline bool isRunning() { return running; } + inline bool stopRequested() { return request_stop; } + void *getReturnValue() { return running ? NULL : retval; } + bool isSameThread(); + + static unsigned int getNumberOfProcessors(); + bool bindToProcessor(unsigned int); + bool setPriority(int); + + /* + * Wait for thread to finish. + * Note: this does not stop a thread, you have to do this on your own. + * Returns immediately if the thread is not started. + */ + void wait(); + + static void setName(const std::string &name); + +protected: + std::string name; + + virtual void *run() = 0; + +private: + void setName() { setName(name); } + + void *retval; + Atomic request_stop; + Atomic running; + Mutex continue_mutex; + +#if __cplusplus >= 201103L + static void theThread(Thread *th); + + std::thread *thread; + std::thread::native_handle_type getThreadHandle() const + { return thread->native_handle(); } +#else +# if defined(WIN32) || defined(_WIN32_WCE) +# ifdef _WIN32_WCE + DWORD thread_id; + static DWORD WINAPI theThread(void *param); +# else + UINT thread_id; + static UINT __stdcall theThread(void *param); +# endif + + HANDLE thread; + HANDLE getThreadHandle() const { return thread; } +# else // pthread + static void *theThread(void *param); + + pthread_t thread; + pthread_t getThreadHandle() const { return thread; } + + Atomic started; +# endif +#endif +}; + +#endif + diff --git a/src/threads.h b/src/threads.h index 503fa6abf..bc3bf571d 100644 --- a/src/threads.h +++ b/src/threads.h @@ -20,9 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef THREADS_HEADER #define THREADS_HEADER -#include "jthread/jmutex.h" +#include "threading/mutex.h" -#if (defined(WIN32) || defined(_WIN32_WCE)) +#if defined(WIN32) || defined(_WIN32_WCE) typedef DWORD threadid_t; #else typedef pthread_t threadid_t; @@ -30,7 +30,7 @@ typedef pthread_t threadid_t; inline threadid_t get_current_thread_id() { -#if (defined(WIN32) || defined(_WIN32_WCE)) +#if defined(WIN32) || defined(_WIN32_WCE) return GetCurrentThreadId(); #else return pthread_self(); diff --git a/src/unittest/CMakeLists.txt b/src/unittest/CMakeLists.txt index bdff14f05..a07ed8ba5 100644 --- a/src/unittest/CMakeLists.txt +++ b/src/unittest/CMakeLists.txt @@ -17,6 +17,7 @@ set (UNITTEST_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/test_serialization.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_settings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_socket.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test_threading.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_utilities.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_voxelalgorithms.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_voxelmanipulator.cpp diff --git a/src/unittest/test_threading.cpp b/src/unittest/test_threading.cpp new file mode 100644 index 000000000..a5d98f0a6 --- /dev/null +++ b/src/unittest/test_threading.cpp @@ -0,0 +1,85 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "test.h" + +#include "threading/atomic.h" +#include "threading/semaphore.h" +#include "threading/thread.h" + + +class TestThreading : public TestBase { +public: + TestThreading() { TestManager::registerTestModule(this); } + const char *getName() { return "TestThreading"; } + void runTests(IGameDef *); + void testAtomicSemaphoreThread(); +}; + +static TestThreading g_test_instance; + +void TestThreading::runTests(IGameDef *) +{ + TEST(testAtomicSemaphoreThread); +} + + +class AtomicTestThread : public Thread +{ +public: + AtomicTestThread(Atomic &v, Semaphore &trigger) : + Thread("AtomicTest"), + val(v), + trigger(trigger) + {} +private: + void *run() + { + trigger.wait(); + for (u32 i = 0; i < 0x10000; ++i) + ++val; + return NULL; + } + Atomic &val; + Semaphore &trigger; +}; + + +void TestThreading::testAtomicSemaphoreThread() +{ + Atomic val; + Semaphore trigger; + static const u8 num_threads = 4; + + AtomicTestThread *threads[num_threads]; + for (u8 i = 0; i < num_threads; ++i) { + threads[i] = new AtomicTestThread(val, trigger); + UASSERT(threads[i]->start()); + } + + trigger.post(num_threads); + + for (u8 i = 0; i < num_threads; ++i) { + threads[i]->wait(); + delete threads[i]; + } + + UASSERT(val == num_threads * 0x10000); +} + diff --git a/src/util/container.h b/src/util/container.h index 267d54c16..7f66b89ac 100644 --- a/src/util/container.h +++ b/src/util/container.h @@ -22,9 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "../irrlichttypes.h" #include "../exceptions.h" -#include "../jthread/jmutex.h" -#include "../jthread/jmutexautolock.h" -#include "../jthread/jsemaphore.h" +#include "../threading/mutex.h" +#include "../threading/mutex_auto_lock.h" +#include "../threading/semaphore.h" #include #include #include @@ -81,111 +81,47 @@ template class MutexedMap { public: - MutexedMap() - { - } + MutexedMap() {} void set(const Key &name, const Value &value) { - JMutexAutoLock lock(m_mutex); - + MutexAutoLock lock(m_mutex); m_values[name] = value; } - bool get(const Key &name, Value *result) + bool get(const Key &name, Value *result) const { - JMutexAutoLock lock(m_mutex); - - typename std::map::iterator n; - n = m_values.find(name); - - if(n == m_values.end()) + MutexAutoLock lock(m_mutex); + typename std::map::const_iterator n = + m_values.find(name); + if (n == m_values.end()) return false; - - if(result != NULL) + if (result) *result = n->second; - return true; } - std::vector getValues() + std::vector getValues() const { + MutexAutoLock lock(m_mutex); std::vector result; - for(typename std::map::iterator - i = m_values.begin(); - i != m_values.end(); ++i){ - result.push_back(i->second); + for (typename std::map::const_iterator + it = m_values.begin(); + it != m_values.end(); ++it){ + result.push_back(it->second); } return result; } - void clear () - { - m_values.clear(); - } + void clear() { m_values.clear(); } private: std::map m_values; - JMutex m_mutex; + mutable Mutex m_mutex; }; -/* -Generates ids for comparable values. -Id=0 is reserved for "no value". -Is fast at: -- Returning value by id (very fast) -- Returning id by value -- Generating a new id for a value - -Is not able to: -- Remove an id/value pair (is possible to implement but slow) -*/ -template -class MutexedIdGenerator -{ -public: - MutexedIdGenerator() - { - } - - // Returns true if found - bool getValue(u32 id, T &value) - { - if(id == 0) - return false; - JMutexAutoLock lock(m_mutex); - if(m_id_to_value.size() < id) - return false; - value = m_id_to_value[id-1]; - return true; - } - - // If id exists for value, returns the id. - // Otherwise generates an id for the value. - u32 getId(const T &value) - { - JMutexAutoLock lock(m_mutex); - typename std::map::iterator n; - n = m_value_to_id.find(value); - if(n != m_value_to_id.end()) - return n->second; - m_id_to_value.push_back(value); - u32 new_id = m_id_to_value.size(); - m_value_to_id.insert(value, new_id); - return new_id; - } - -private: - JMutex m_mutex; - // Values are stored here at id-1 position (id 1 = [0]) - std::vector m_id_to_value; - std::map m_value_to_id; -}; - -/* -Thread-safe FIFO queue (well, actually a FILO also) -*/ +// Thread-safe Double-ended queue template class MutexedQueue @@ -194,19 +130,18 @@ public: template friend class RequestQueue; - MutexedQueue() - { - } - bool empty() + MutexedQueue() {} + bool empty() const { - JMutexAutoLock lock(m_mutex); - return (m_queue.size() == 0); + MutexAutoLock lock(m_mutex); + return m_queue.empty(); } + void push_back(T t) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); m_queue.push_back(t); - m_size.Post(); + m_signal.post(); } /* this version of pop_front returns a empty element of T on timeout. @@ -214,37 +149,35 @@ public: */ T pop_frontNoEx(u32 wait_time_max_ms) { - if (m_size.Wait(wait_time_max_ms)) { - JMutexAutoLock lock(m_mutex); + if (m_signal.wait(wait_time_max_ms)) { + MutexAutoLock lock(m_mutex); T t = m_queue.front(); m_queue.pop_front(); return t; - } - else { + } else { return T(); } } T pop_front(u32 wait_time_max_ms) { - if (m_size.Wait(wait_time_max_ms)) { - JMutexAutoLock lock(m_mutex); + if (m_signal.wait(wait_time_max_ms)) { + MutexAutoLock lock(m_mutex); T t = m_queue.front(); m_queue.pop_front(); return t; - } - else { + } else { throw ItemNotFoundException("MutexedQueue: queue is empty"); } } T pop_frontNoEx() { - m_size.Wait(); + m_signal.wait(); - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); T t = m_queue.front(); m_queue.pop_front(); @@ -253,14 +186,13 @@ public: T pop_back(u32 wait_time_max_ms=0) { - if (m_size.Wait(wait_time_max_ms)) { - JMutexAutoLock lock(m_mutex); + if (m_signal.wait(wait_time_max_ms)) { + MutexAutoLock lock(m_mutex); T t = m_queue.back(); m_queue.pop_back(); return t; - } - else { + } else { throw ItemNotFoundException("MutexedQueue: queue is empty"); } } @@ -268,25 +200,24 @@ public: /* this version of pop_back returns a empty element of T on timeout. * Make sure default constructor of T creates a recognizable "empty" element */ - T pop_backNoEx(u32 wait_time_max_ms=0) + T pop_backNoEx(u32 wait_time_max_ms) { - if (m_size.Wait(wait_time_max_ms)) { - JMutexAutoLock lock(m_mutex); + if (m_signal.wait(wait_time_max_ms)) { + MutexAutoLock lock(m_mutex); T t = m_queue.back(); m_queue.pop_back(); return t; - } - else { + } else { return T(); } } T pop_backNoEx() { - m_size.Wait(); + m_signal.wait(); - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); T t = m_queue.back(); m_queue.pop_back(); @@ -294,19 +225,13 @@ public: } protected: - JMutex & getMutex() - { - return m_mutex; - } + Mutex &getMutex() { return m_mutex; } - std::deque & getQueue() - { - return m_queue; - } + std::deque &getQueue() { return m_queue; } std::deque m_queue; - JMutex m_mutex; - JSemaphore m_size; + mutable Mutex m_mutex; + Semaphore m_signal; }; template diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index 3fd1c9cf9..bfd5d6e38 100644 --- a/src/util/numeric.cpp +++ b/src/util/numeric.cpp @@ -23,17 +23,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "../constants.h" // BS, MAP_BLOCKSIZE #include "../noise.h" // PseudoRandom, PcgRandom -#include "../jthread/jmutexautolock.h" +#include "../threading/mutex_auto_lock.h" #include #include std::map > FacePositionCache::m_cache; -JMutex FacePositionCache::m_cache_mutex; +Mutex FacePositionCache::m_cache_mutex; // Calculate the borders of a "d-radius" cube // TODO: Make it work without mutex and data races, probably thread-local std::vector FacePositionCache::getFacePositions(u16 d) { - JMutexAutoLock cachelock(m_cache_mutex); + MutexAutoLock cachelock(m_cache_mutex); if (m_cache.find(d) != m_cache.end()) return m_cache[d]; diff --git a/src/util/numeric.h b/src/util/numeric.h index 9fe08434f..8a17d892d 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "../irr_v2d.h" #include "../irr_v3d.h" #include "../irr_aabb3d.h" -#include "../jthread/jmutex.h" +#include "../threading/mutex.h" #include #include #include @@ -42,7 +42,7 @@ public: private: static void generateFacePosition(u16 d); static std::map > m_cache; - static JMutex m_cache_mutex; + static Mutex m_cache_mutex; }; class IndentationRaiser diff --git a/src/util/thread.h b/src/util/thread.h index b3a5e68a2..a32871aab 100644 --- a/src/util/thread.h +++ b/src/util/thread.h @@ -21,9 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #define UTIL_THREAD_HEADER #include "../irrlichttypes.h" -#include "../jthread/jthread.h" -#include "../jthread/jmutex.h" -#include "../jthread/jmutexautolock.h" +#include "../threading/thread.h" +#include "../threading/mutex.h" +#include "../threading/mutex_auto_lock.h" #include "porting.h" #include "log.h" @@ -36,27 +36,27 @@ public: T get() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); return m_value; } void set(T value) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); m_value = value; } // You'll want to grab this in a SharedPtr - JMutexAutoLock *getLock() + MutexAutoLock *getLock() { - return new JMutexAutoLock(m_mutex); + return new MutexAutoLock(m_mutex); } // You pretty surely want to grab the lock when accessing this T m_value; private: - JMutex m_mutex; + Mutex m_mutex; }; /* @@ -118,7 +118,7 @@ public: typename std::list >::iterator j; { - JMutexAutoLock lock(m_queue.getMutex()); + MutexAutoLock lock(m_queue.getMutex()); /* If the caller is already on the list, only update CallerData @@ -192,44 +192,33 @@ private: MutexedQueue > m_queue; }; -class UpdateThread : public JThread { +class UpdateThread : public Thread +{ public: - UpdateThread() {} - virtual ~UpdateThread() {} + UpdateThread(const std::string &name) : Thread(name + "Update") {} + ~UpdateThread() {} - void deferUpdate() - { - m_update_sem.Post(); - } + void deferUpdate() { m_update_sem.post(); } - void Stop() + void stop() { - JThread::Stop(); + Thread::stop(); // give us a nudge - m_update_sem.Post(); + m_update_sem.post(); } - void *Thread() + void *run() { - ThreadStarted(); - - const char *thread_name = getName(); - log_register_thread(thread_name); - porting::setThreadName(thread_name); - DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER - while (!StopRequested()) { - m_update_sem.Wait(); - - // Empty the queue, just in case doUpdate() is expensive - while (m_update_sem.GetValue()) - m_update_sem.Wait(); + while (!stopRequested()) { + m_update_sem.wait(); + // Set semaphore to 0 + while (m_update_sem.wait(0)); - if (StopRequested()) - break; + if (stopRequested()) break; doUpdate(); } @@ -241,10 +230,9 @@ public: protected: virtual void doUpdate() = 0; - virtual const char *getName() = 0; private: - JSemaphore m_update_sem; + Semaphore m_update_sem; }; #endif -- cgit v1.2.3