diff --git a/.gitignore b/.gitignore index 7b2b030afd8dab49c9bfe3555fd4c00f7e99f3fd..77b6a2b00b7142299f6639bd90c0896c22d0f45f 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 61ba1d0f0110742b9a0c8741a8a7cb916e432dae..cf7094ca8580388f2318f5aff3e75ddaa9985ab4 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 614e819080306f68473c0ce8c6e3268044e92855..2d52de68b48e890aed5415c30eb7040fe5d600b3 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 7c1a68d458af2d330150198c8d812dc1d79df0c9..108319953ad069341d193ea086ca507ddde0c031 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 <fstream> -#include "jthread/jmutexautolock.h" +#include "threading/mutex_auto_lock.h" #include <sstream> #include <set> #include "strfnd.h" @@ -48,7 +48,7 @@ BanManager::~BanManager() void BanManager::load() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); infostream<<"BanManager: loading from "<<m_banfilepath<<std::endl; std::ifstream is(m_banfilepath.c_str(), std::ios::binary); if(is.good() == false) @@ -73,7 +73,7 @@ void BanManager::load() void BanManager::save() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); infostream << "BanManager: saving to " << m_banfilepath << std::endl; std::ostringstream ss(std::ios_base::binary); @@ -90,13 +90,13 @@ void BanManager::save() bool BanManager::isIpBanned(const std::string &ip) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); return m_ips.find(ip) != m_ips.end(); } std::string BanManager::getBanDescription(const std::string &ip_or_name) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); std::string s = ""; for (StringMap::iterator it = m_ips.begin(); it != m_ips.end(); ++it) { if (it->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 5db7179defef48165f2be7e85cb314ed4ac5e5c8..d1a49cb154a4f96dfcd40886282b92eec4586186 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 <map> +#include <string> class BanManager { @@ -40,7 +42,7 @@ class BanManager 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 946f4f1c48116447128534a9dfdd5b7b33c9604c..2a253fd756e900ece28189bb4c6680199dfd37b3 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 <algorithm> #include <sstream> #include <IFileSystem.h> -#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<QueuedMeshUpdate*>::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<QueuedMeshUpdate*>::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"<<std::endl; - m_mesh_update_thread.Start(); + m_mesh_update_thread.start(); m_state = LC_Ready; sendReady(); diff --git a/src/client.h b/src/client.h index 547edfeabe48d308617ab1fe54888a1833fb411e..75fd0c9842fc99b3c3e9e88e4ee3b4dc52405fa1 100644 --- a/src/client.h +++ b/src/client.h @@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "network/connection.h" #include "environment.h" #include "irrlichttypes_extrabloated.h" -#include "jthread/jmutex.h" +#include "threading/mutex.h" #include <ostream> #include <map> #include <set> @@ -89,14 +89,14 @@ class MeshUpdateQueue u32 size() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); return m_queue.size(); } private: std::vector<QueuedMeshUpdate*> m_queue; std::set<v3s16> m_urgents; - JMutex m_mutex; + Mutex m_mutex; }; struct MeshUpdateResult @@ -119,19 +119,14 @@ class MeshUpdateThread : public UpdateThread 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<MeshUpdateResult> m_queue_out; v3s16 m_camera_offset; diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index bad5c384c3cdbd1c138b1fdd28077489898d6e7f..60eb216741988afdc3a20ef614cff23bdb3d2d98 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 a28b40c65119cfb7c26558912a55ce442768efd4..1f1e9d38c60eadbe892f30891e55e222478de01a 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -414,7 +414,7 @@ class TextureSource : public IWritableTextureSource // Maps a texture name to an index in the former. std::map<std::string, u32> 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<std::string, u32, u8, u8> 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<std::string, u32>::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<std::string, u32>::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 3330e0af916e1690e90c14304cc5ef70b8b08c9d..d4efe60ef50451bbbf4438bc1564bea47d783893 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<u16, RemoteClient*>::iterator i = m_clients.begin(); @@ -609,7 +609,7 @@ ClientInterface::~ClientInterface() std::vector<u16> ClientInterface::getClientIDs(ClientState min_state) { std::vector<u16> reply; - JMutexAutoLock clientslock(m_clients_mutex); + MutexAutoLock clientslock(m_clients_mutex); for(std::map<u16, RemoteClient*>::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<u16, RemoteClient*>::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<u16, RemoteClient*>::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<u16, RemoteClient*>::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<u16, RemoteClient*>::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<u16, RemoteClient*>::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<u16, RemoteClient*>::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<u16, RemoteClient*>::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<u16, RemoteClient*>::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<u16, RemoteClient*>::iterator n; diff --git a/src/clientiface.h b/src/clientiface.h index f6c4294e2b335c5823082d2c096b9dddb7109dfb..9be8bda617a652e2543440782af9fbe47023b10b 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 <list> @@ -487,10 +487,8 @@ class ClientInterface { 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<u16, RemoteClient*>& getClientList() { return m_clients; } @@ -501,14 +499,14 @@ class ClientInterface { // Connection con::Connection* m_con; - JMutex m_clients_mutex; + Mutex m_clients_mutex; // Connected clients (behind the con mutex) std::map<u16, RemoteClient*> m_clients; std::vector<std::string> 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 288a12135f0836ee7af796d5e858aa7adfa622bf..b890e338b8fd47faff14c88862520c7539980e7f 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 492e23fa5e98d61c5066ffb831bc580090777c32..54d1dc96d97a538ce95948541ea9e1b854cc82e9 100644 --- a/src/clientmap.h +++ b/src/clientmap.h @@ -89,7 +89,7 @@ class ClientMap : public Map, public scene::ISceneNode 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 @@ class ClientMap : public Map, public scene::ISceneNode v3f m_camera_direction; f32 m_camera_fov; v3s16 m_camera_offset; - JMutex m_camera_mutex; + Mutex m_camera_mutex; std::map<v3s16, MapBlock*> m_drawlist; diff --git a/src/debug.cpp b/src/debug.cpp index ae2ffadc3e2e5de24f5ff1f946ec80834529345d..3608f42d2315254f829a105ee22766332d30a3ce 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 <stdlib.h> #include <cstring> #include <map> -#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<threadid_t, DebugStack*> 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:"<<std::endl; @@ -251,7 +251,7 @@ void debug_stacks_print_to(std::ostream &os) void debug_stacks_print() { - JMutexAutoLock lock(g_debug_stacks_mutex); + MutexAutoLock lock(g_debug_stacks_mutex); DEBUGPRINT("Debug stacks:\n"); @@ -273,7 +273,7 @@ DebugStacker::DebugStacker(const char *text) { threadid_t threadid = get_current_thread_id(); - JMutexAutoLock lock(g_debug_stacks_mutex); + MutexAutoLock lock(g_debug_stacks_mutex); std::map<threadid_t, DebugStack*>::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 d6bda731a2e8ad21e907d527e805e60f2e2e0ee2..0844707836ded07650d93ef4787acdffdb844d17 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 <iostream> #include <queue> -#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 @@ class EmergeThread : public JThread std::queue<v3s16> blockqueue; EmergeThread(Server *server, int ethreadid): - JThread(), m_server(server), map(NULL), emerge(NULL), @@ -81,9 +80,10 @@ class EmergeThread : public JThread 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<v3s16, BlockEmergeData *>::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 1653199ecbb15d5f59fb83b4c79b7cfab3a79d59..2ed21bb063ec25948ff8e53a9b40513bc1bcf714 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -86,7 +86,7 @@ class EmergeManager { std::set<u32> gen_notify_on_deco_ids; //// Block emerge queue data structures - JMutex queuemutex; + Mutex queuemutex; std::map<v3s16, BlockEmergeData *> blocks_enqueued; std::map<u16, u16> peer_queue_count; diff --git a/src/environment.cpp b/src/environment.cpp index dbbfc6f1ff9d9bef1746d8c7edd78954c93a78bc..baeb3a3c6f02724fb49fb16502b98118ba29b896 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 c7069431678983ed4294580e6c8d8e5e23bf5525..6ace12671838976c1c9b7c648a621ca357af8673 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 @@ class Environment 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 56cdad2b112df13a59268c7668c7ee5df4819ccd..6040b1b3b302778774b09ea4bb8d29fae0895a23 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 <list> #include <map> #include <errno.h> -#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<unsigned long, std::queue<HTTPFetchResult> > 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<unsigned long, std::queue<HTTPFetchResult> >::iterator @@ -390,7 +390,7 @@ HTTPFetchOngoing::~HTTPFetchOngoing() } -class CurlFetchThread : public JThread +class CurlFetchThread : public Thread { protected: enum RequestType { @@ -414,7 +414,8 @@ class CurlFetchThread : public JThread std::list<HTTPFetchRequest> 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 @@ class CurlFetchThread : public JThread } } - 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 @@ class CurlFetchThread : public JThread 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"<<std::endl; - g_httpfetch_thread->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 cebb35caa69caf98d40eb7c232e398754ca6fe8a..0000000000000000000000000000000000000000 --- 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/jevent.h b/src/jthread/jevent.h deleted file mode 100644 index 9ea7ebde87d21d5371791e221b0abb6e17e0b8bf..0000000000000000000000000000000000000000 --- 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 <windows.h> -#elif defined(__MACH__) && defined(__APPLE__) -#include <mach/mach.h> -#include <mach/task.h> -#include <mach/semaphore.h> -#include <sys/semaphore.h> -#else -#include <semaphore.h> -#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 e57cd8a435f14217b53d4b371bde40a8890cb3d6..0000000000000000000000000000000000000000 --- 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 <process.h> - #endif // _WIN32_WCE - #include <winsock2.h> - #include <windows.h> - // CriticalSection is way faster than the alternative - #define JMUTEX_CRITICALSECTION -#else // using pthread - #include <pthread.h> -#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 6020a5c336d62c5e4b318cfda05cf2c6cf0b676a..0000000000000000000000000000000000000000 --- 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/jthread.h b/src/jthread/jthread.h deleted file mode 100644 index 89743a3e3857eab100e739f8d63f9ab0ee14fe92..0000000000000000000000000000000000000000 --- 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 <atomic> -#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 e1d40f4c151f9a3803d5be6086875e1c0d8663bd..0000000000000000000000000000000000000000 --- 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 <assert.h> -#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 0551b972815a4dcadf6fb2ec271352c9650f9122..0000000000000000000000000000000000000000 --- 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 <assert.h> -#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 15281ba64cb24db127d597f7a8d6ce031c9435d2..0000000000000000000000000000000000000000 --- 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 <assert.h> -#include <errno.h> -#include <sys/time.h> -#include "jthread/jsemaphore.h" -#if defined(__MACH__) && defined(__APPLE__) -#include <unistd.h> -#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 414d8fde593b2976b9e2b6c22b731747e93d31c8..0000000000000000000000000000000000000000 --- 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 <assert.h> -#include <sys/time.h> -#include <time.h> -#include <stdlib.h> - -#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 67b468f01ee9c0d4ac449cd41e0b4015b2ff08e0..0000000000000000000000000000000000000000 --- 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 b9f5e0e73a79f822dbfd174aed8d482941ba9e7a..0000000000000000000000000000000000000000 --- 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 <assert.h> -#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 27a11e8198756e5033f81ad13a0e46d7d5517b38..0000000000000000000000000000000000000000 --- 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 b523d664cb99deb497c2d8ae8da7e084234cd349..0000000000000000000000000000000000000000 --- 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 <assert.h> -#define UNUSED(expr) do { (void)(expr); } while (0) -#ifndef _WIN32_WCE - #include <process.h> -#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 e6d80db34e2a0a9747a3e34dc684f9b96a999fdf..9dc574d01c5e8e0b30a04b692d92cd1fe1df9cad 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 <sstream> #include <algorithm> #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<ILogOutput*> log_outputs[LMT_NUM_VALUES]; -std::map<threadid_t, std::string> log_threadnames; -JMutex log_threadnamemutex; +std::map<threadid_t, std::string> 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<ILogOutput *>::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<threadid_t, std::string>::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 1d73b40253003a6a37140e33daae2375cd13a61e..56ba7fac996b7cd73b0a6d1b7e67ed72f92c1e8d 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 43057f3a54fc5ece599d870bf098249bd3d65052..1f84c4d7b7a51b2cac3a4ab74f8c73dd4b60ad7f 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 0d669392991827a1741844ee597252c6321c333f..f11a71518a75709ebedb5d719bee719479071a78 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<CutoffData>::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<CutoffData>::iterator i = cutoffs.begin(); i != cutoffs.end(); ++i) { diff --git a/src/mg_decoration.h b/src/mg_decoration.h index 056748918c2dc0d24b73551b08e880154a0d9325..c712ce7c8e5dfb672950457dda810804c9e19c30 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -84,7 +84,7 @@ class Decoration : public ObjDef, public NodeResolver { std::set<u8> biomes; //std::list<CutoffData> cutoffs; - //JMutex cutoff_mutex; + //Mutex cutoff_mutex; }; class DecoSimple : public Decoration { diff --git a/src/minimap.cpp b/src/minimap.cpp index d1fb3867db4150c720145a3574e2cf9f1a6f13ec..7eb7247cab41e5fa10b4a0b6c4cfc3943f329625 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 <math.h> #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 628be7489e2af73c1a370155d7b23f50e6cddc6d..dd1397d54c18b4f19102eca204b810f55785c2cc 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 <map> -#include <string> -#include <vector> #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 <map> +#include <string> +#include <vector> #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 @@ class MinimapUpdateThread : public UpdateThread { MinimapData *data; protected: - const char *getName() { return "MinimapUpdateThread"; } virtual void doUpdate(); private: - JMutex m_queue_mutex; + Mutex m_queue_mutex; std::deque<QueuedMinimapUpdate> m_update_queue; std::map<v3s16, MinimapMapblock *> m_blocks_cache; }; @@ -151,7 +152,7 @@ class Mapper { 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 86091bc880d1c7d84ba9c50e17e4792516c01183..04f94c58b2985ecdfef4d51538914e3755c89693 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 7794ce10fb2d48552a47329e99030583dbd8919d..10f0d55433f5a6e87da4978ccb35f11d364de2e0 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<BufferedPacket>::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<BufferedPacket>::iterator i = m_list.begin(); i != m_list.end(); ++i) { @@ -423,7 +423,7 @@ void ReliablePacketBuffer::incrementTimeouts(float dtime) std::list<BufferedPacket> ReliablePacketBuffer::getTimedOuts(float timeout, unsigned int max_packets) { - JMutexAutoLock listlock(m_list_mutex); + MutexAutoLock listlock(m_list_mutex); std::list<BufferedPacket> timed_outs; for(std::list<BufferedPacket>::iterator i = m_list.begin(); i != m_list.end(); ++i) @@ -446,7 +446,7 @@ std::list<BufferedPacket> ReliablePacketBuffer::getTimedOuts(float timeout, IncomingSplitBuffer::~IncomingSplitBuffer() { - JMutexAutoLock listlock(m_map_mutex); + MutexAutoLock listlock(m_map_mutex); for(std::map<u16, IncomingSplitPacket*>::iterator i = m_buf.begin(); i != m_buf.end(); ++i) { @@ -459,7 +459,7 @@ IncomingSplitBuffer::~IncomingSplitBuffer() */ SharedBuffer<u8> 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<u16> remove_queue; { - JMutexAutoLock listlock(m_map_mutex); + MutexAutoLock listlock(m_map_mutex); for(std::map<u16, IncomingSplitPacket*>::iterator i = m_buf.begin(); i != m_buf.end(); ++i) { @@ -562,7 +562,7 @@ void IncomingSplitBuffer::removeUnreliableTimedOuts(float dtime, float timeout) for(std::list<u16>::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"<<std::endl); delete m_buf[*j]; m_buf.erase(*j); @@ -605,13 +605,13 @@ Channel::~Channel() u16 Channel::readNextIncomingSeqNum() { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); return next_incoming_seqnum; } u16 Channel::incNextIncomingSeqNum() { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); u16 retval = next_incoming_seqnum; next_incoming_seqnum++; return retval; @@ -619,18 +619,18 @@ u16 Channel::incNextIncomingSeqNum() u16 Channel::readNextSplitSeqNum() { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); return next_outgoing_split_seqnum; } void Channel::setNextSplitSeqNum(u16 seqnum) { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); next_outgoing_split_seqnum = seqnum; } u16 Channel::getOutgoingSequenceNumber(bool& successful) { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); u16 retval = next_outgoing_seqnum; u16 lowest_unacked_seqnumber; @@ -670,7 +670,7 @@ u16 Channel::getOutgoingSequenceNumber(bool& successful) u16 Channel::readOutgoingSequenceNumber() { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); return next_outgoing_seqnum; } @@ -686,32 +686,32 @@ bool Channel::putBackSequenceNumber(u16 seqnum) void Channel::UpdateBytesSent(unsigned int bytes, unsigned int packets) { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); current_bytes_transfered += bytes; current_packet_successfull += packets; } void Channel::UpdateBytesReceived(unsigned int bytes) { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); current_bytes_received += bytes; } void Channel::UpdateBytesLost(unsigned int bytes) { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); current_bytes_lost += bytes; } void Channel::UpdatePacketLossCounter(unsigned int count) { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); current_packet_loss += count; } void Channel::UpdatePacketTooLateCounter() { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); current_packet_too_late++; } @@ -731,7 +731,7 @@ void Channel::UpdateTimers(float dtime,bool legacy_peer) bool reasonable_amount_of_data_transmitted = false; { - JMutexAutoLock internal(m_internal_mutex); + MutexAutoLock internal(m_internal_mutex); packet_loss = current_packet_loss; //packet_too_late = current_packet_too_late; packets_successfull = current_packet_successfull; @@ -802,7 +802,7 @@ void Channel::UpdateTimers(float dtime,bool legacy_peer) if (bpm_counter > 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<u8> 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<<m_connection->getDesc() <<"ConnectionSend thread started"<<std::endl); @@ -1281,21 +1280,19 @@ void * ConnectionSendThread::Thread() PROFILE(std::stringstream ThreadIdentifier); PROFILE(ThreadIdentifier << "ConnectionSend: [" << m_connection->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<<m_connection->getDesc() <<"ConnectionReceive thread started"<<std::endl); @@ -2030,15 +2026,13 @@ void * ConnectionReceiveThread::Thread() PROFILE(std::stringstream ThreadIdentifier); PROFILE(ThreadIdentifier << "ConnectionReceive: [" << m_connection->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<u16, Peer*>::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<u16, Peer*>::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<u16, Peer*>::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<u16, Peer*>::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<<getDesc()<<": "; - m_info_mutex.Unlock(); + m_info_mutex.unlock(); } void Connection::PrintInfo() @@ -3091,7 +3085,7 @@ UDPPeer* Connection::createServerPeer(Address& address) UDPPeer *peer = new UDPPeer(PEER_ID_SERVER, address, this); { - JMutexAutoLock lock(m_peers_mutex); + MutexAutoLock lock(m_peers_mutex); m_peers[peer->id] = peer; m_peer_ids.push_back(peer->id); } diff --git a/src/network/connection.h b/src/network/connection.h index 15ea7e20ff267cfd8237014f2f2ff230f9bdb204..fe2c9819d3e82c8b82c4947ce7141c6202567225 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -349,7 +349,7 @@ class ReliablePacketBuffer u16 m_oldest_non_answered_ack; - JMutex m_list_mutex; + Mutex m_list_mutex; }; /* @@ -372,7 +372,7 @@ class IncomingSplitBuffer // Key is seqnum std::map<u16, IncomingSplitPacket*> m_buf; - JMutex m_map_mutex; + Mutex m_map_mutex; }; struct OutgoingPacket @@ -519,32 +519,32 @@ class Channel 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 @@ class UDPPeer : public Peer 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<u8>& 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 @@ class ConnectionSendThread : public JThread { unsigned int m_max_packet_size; float m_timeout; std::queue<OutgoingPacket> 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 @@ class ConnectionSendThread : public JThread { 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<u8> &dst); + bool getFromBuffers(u16 &peer_id, SharedBuffer<u8> &dst); bool checkIncomingBuffers(Channel *channel, u16 &peer_id, SharedBuffer<u8> &dst); @@ -1054,7 +1054,7 @@ class Connection std::list<u16> getPeerIDs() { - JMutexAutoLock peerlock(m_peers_mutex); + MutexAutoLock peerlock(m_peers_mutex); return m_peer_ids; } @@ -1075,12 +1075,12 @@ class Connection std::map<u16, Peer*> m_peers; std::list<u16> 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 15e2a6597b952bec34dbafcdf9269a25a080599f..ab48bae9e3c0b4c4a2cf39c639bb970173fbffa8 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<u32, ParticleSpawner*>::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<Particle*>::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<u32, ParticleSpawner*>::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<u32, ParticleSpawner*>( 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 2bc2e7bfa813200943a85001c5ee375de58b9fca..0ad8d71b5a860cdbd14a5106ec458518bdcacebd 100644 --- a/src/particles.h +++ b/src/particles.h @@ -190,8 +190,8 @@ friend class ParticleSpawner; std::map<u32, ParticleSpawner*> 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 cb2286ef63ee049cfca07d96cd52a593d60839a4..3ee34d41f0b594124df8e2dc337878f0a2f17c57 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 <fstream> -#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 3a336afc41323f300cc15ea9ce4e11c95319ee51..ec30e59d2982494f923282ded08649adba5e85d2 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 <list> #define PLAYERNAME_SIZE 20 @@ -413,7 +413,7 @@ class Player // 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 44f1fcff1d3a20ec388e283af9dbc4c954992e94..cb9f3270bea76533a9214d8dce50fd25701eccbb 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 2a91fdd063245816e02f55a9e390002ec220830f..492c9d3a8d5e6326a6173e203a7835f4600da972 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 <sched.h> - - #ifdef __FreeBSD__ - #include <pthread_np.h> - typedef cpuset_t cpu_set_t; - #elif defined(__sun) || defined(sun) - #include <sys/types.h> - #include <sys/processor.h> - #elif defined(_AIX) - #include <sys/processor.h> - #elif __APPLE__ - #include <mach/mach_init.h> - #include <mach/thread_policy.h> - #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 <sys/prctl.h> - - 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 <pthread.h> - #include <pthread_np.h> - - inline void setThreadName(const char *name) { - pthread_set_name_np(pthread_self(), name); - } -#elif defined(__NetBSD__) - #include <pthread.h> - - 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 <pthread.h> - - 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 6871ce465b7cfac9a2c0e16e028e047a80407024..06cc929ddf1dd241ff563ed9de0020a3bf21a049 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 78d3b08e06493052362b3d443d946e72d7832a23..e8eac86b13e5b8c0ddf130b11fb3d99233331f2e 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 <string> #include <map> -#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 @@ class Profiler 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<std::string, int>::iterator n = m_avgcounts.find(name); @@ -72,7 +72,7 @@ class Profiler 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 @@ class Profiler void clear() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); for(std::map<std::string, float>::iterator i = m_data.begin(); i != m_data.end(); ++i) @@ -114,7 +114,7 @@ class Profiler 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 @@ class Profiler void graphAdd(const std::string &id, float value) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); std::map<std::string, float>::iterator i = m_graphvalues.find(id); if(i == m_graphvalues.end()) @@ -169,20 +169,20 @@ class Profiler } 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<std::string, float> m_data; std::map<std::string, int> m_avgcounts; std::map<std::string, float> m_graphvalues; diff --git a/src/quicktune.cpp b/src/quicktune.cpp index 2f9f987bdb039adf78b0131c14326e83d3626b22..b0e2dc6d5bbd731889f488ce1960ba761dc42b04 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<std::string, QuicktuneValue> g_values; static std::vector<std::string> 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<std::string> getQuicktuneNames() QuicktuneValue getQuicktuneValue(const std::string &name) { makeMutex(); - JMutexAutoLock lock(*g_mutex); + MutexAutoLock lock(*g_mutex); std::map<std::string, QuicktuneValue>::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<std::string, QuicktuneValue>::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 c00b22f986256f4dbca071332f82de95e1fa7ccf..1e87e59f008a7aba32401e4a28b49c9fa9eb52e2 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<AsyncWorkerThread *>::iterator it = workerThreads.begin(); it != workerThreads.end(); it++) { - (*it)->Stop(); + (*it)->stop(); } // Wake up all threads for (std::vector<AsyncWorkerThread *>::iterator it = workerThreads.begin(); it != workerThreads.end(); it++) { - jobQueueCounter.Post(); + jobQueueCounter.post(); } // Wait for threads to finish for (std::vector<AsyncWorkerThread *>::iterator it = workerThreads.begin(); it != workerThreads.end(); it++) { - (*it)->Wait(); + (*it)->wait(); } // Force kill all threads for (std::vector<AsyncWorkerThread *>::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 a6459c18db35c04feb5abfda2329ee5a548da410..7f8c72faedd331a866ec1b1c00e266daf6d40122 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 <deque> #include <map> -#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 @@ class AsyncEngine { unsigned int jobIdCounter; // Mutex to protect job queue - JMutex jobQueueMutex; + Mutex jobQueueMutex; // Job queue std::deque<LuaJobInfo> jobQueue; // Mutex to protect result queue - JMutex resultQueueMutex; + Mutex resultQueueMutex; // Result queue std::deque<LuaJobInfo> resultQueue; @@ -162,7 +153,7 @@ class AsyncEngine { std::vector<AsyncWorkerThread*> 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 d653b5bacb8d70b7f6edf5859ef316cc92f94275..744fca2d093da07e06ed2da4b65fb6849a105f7f 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 @@ class ScriptApiBase { 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 9999a584a77266475acea4a267ec5442e4f4bb58..7daf8c03f02c60c2195239c7e40be9d9ff7df13a 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 @@ class LockChecker { *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 dc7b101a619d6b51679562f03be947ac54158b27..009ea7b0e63754aacef1ae74e51c120c55239616 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 @@ class ClientNotFoundException : public BaseException {} }; -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() <<"..."<<std::endl; // Stop thread if already running - m_thread->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"<<std::endl; // Stop threads (set run=false first so both start stopping) - m_thread->Stop(); + m_thread->stop(); //m_emergethread.setRun(false); - m_thread->Wait(); + m_thread->wait(); //m_emergethread.stop(); infostream<<"Server: Threads stopped"<<std::endl; @@ -492,7 +486,7 @@ void Server::step(float dtime) if(dtime > 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="<<dtime<<std::endl; { - JMutexAutoLock lock1(m_step_dtime_mutex); + MutexAutoLock lock1(m_step_dtime_mutex); m_step_dtime -= dtime; } @@ -570,7 +564,7 @@ void Server::AsyncRunStep(bool initial_step) } { - JMutexAutoLock lock(m_env_mutex); + MutexAutoLock lock(m_env_mutex); // Figure out and report maximum lag to environment float max_lag = m_env->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"<<std::endl; - JMutexAutoLock envlock(m_env_mutex); + MutexAutoLock envlock(m_env_mutex); - m_clients.Lock(); + m_clients.lock(); std::map<u16, RemoteClient*> 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<u16, RemoteClient*> clients = m_clients.getClientList(); // Route data to every client for (std::map<u16, RemoteClient*>::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<u16, std::vector<ActiveObjectMessage>* >::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<RemotePlayer*>(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<v3s16, MapBlock *>& block) { std::vector<u16> clients = m_clients.getClientIDs(); - m_clients.Lock(); + m_clients.lock(); // Set the modified blocks unsent for all the clients for (std::vector<u16>::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<u16> clients = m_clients.getClientIDs(); - m_clients.Lock(); + m_clients.lock(); for(std::vector<u16>::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<u16> clients = m_clients.getClientIDs(); - m_clients.Lock(); + m_clients.lock(); for(std::vector<u16>::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; i<queue.size(); i++) { //TODO: Calculate limit dynamically @@ -2221,7 +2215,7 @@ void Server::SendBlocks(float dtime) client->SentBlock(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 d16230967eb3eb25ee3cb1cf122e98c08f50dbc9..26ec3ab73a42e52c8adbdb6ed0b9eba237e7af91 100644 --- a/src/server.h +++ b/src/server.h @@ -516,7 +516,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, // Environment ServerEnvironment *m_env; - JMutex m_env_mutex; + Mutex m_env_mutex; // server connection con::Connection m_con; @@ -557,7 +557,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, // 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 e95bd436d527dcda81df3d98186380880ca90712..3d4d56fa3dc5a02b26210ae79f8e521a056d87e8 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 <iostream> #include <fstream> @@ -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<std::string, SettingsEntry>::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<std::string, SettingsEntry>::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<std::string, std::vector<std::pair<setting_changed_callback, void*> > >::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<std::string, std::vector<std::pair<setting_changed_callback, void*> > >::iterator iterToVector = m_callbacks.find(name); if (iterToVector != m_callbacks.end()) { diff --git a/src/settings.h b/src/settings.h index d41f134cd26c2246061b3e7534c9924290097e53..80d41fd790f18b5c66a387a577c5ea0e2702f04f 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 <string> #include <map> #include <list> @@ -225,8 +225,8 @@ class Settings { std::map<std::string, std::vector<std::pair<setting_changed_callback,void*> > > 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 7e4f4081061419e3454b22209692534fdcaa9595..e441883fb1a249f251185a7228eafb67334d8ca4 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -328,7 +328,7 @@ class ShaderSource : public IWritableShaderSource, public IShaderConstantSetterR // The first position contains a dummy shader. std::vector<ShaderInfo> 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<std::string, u32, u8, u8> 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 0000000000000000000000000000000000000000..f3d0efc18085eff6107e3595e2680f42f80f1907 --- /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 0000000000000000000000000000000000000000..486bc79503c2db388331f15bdb6fd435693f716b --- /dev/null +++ b/src/threading/atomic.h @@ -0,0 +1,96 @@ +/* +Minetest +Copyright (C) 2015 ShadowNinja <shadowninja@minetest.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 THREADING_ATOMIC_H +#define THREADING_ATOMIC_H + + +#if __cplusplus >= 201103L + #include <atomic> + template<typename T> using Atomic = std::atomic<T>; +#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<typename T> +class Atomic +{ + // Like C++11 std::enable_if, but defaults to char since C++03 doesn't support SFINAE + template<bool B, typename T_ = void> struct enable_if { typedef char type; }; + template<typename T_> struct enable_if<true, T_> { 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<sizeof(T) <= sizeof(void*), Mutex>::type mutex; +#endif +}; + +#endif // C++11 + +#endif + diff --git a/src/threading/event.h b/src/threading/event.h new file mode 100644 index 0000000000000000000000000000000000000000..0105630e5dbaf897965eb308bd4d80ee5153bb32 --- /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 <windows.h> +#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 0000000000000000000000000000000000000000..eb1c7d61d65b8493c64fe25e9ea6b6ae5a46f302 --- /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 <cassert> +#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 0000000000000000000000000000000000000000..4c9af71bfebc5394d505ccd9fb99d969bcb8fd12 --- /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 <mutex> + 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 <windows.h> +#else // pthread + #include <pthread.h> +#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/jthread/LICENSE.MIT b/src/threading/mutex_auto_lock.h similarity index 52% rename from src/jthread/LICENSE.MIT rename to src/threading/mutex_auto_lock.h index 2aa4fd57b5583cba3ff75c0996ac3a8abda85a6e..1c39349e50bd22fa4a4cf4ca37d3d716c4c922ce 100644 --- a/src/jthread/LICENSE.MIT +++ b/src/threading/mutex_auto_lock.h @@ -1,4 +1,8 @@ -The license of JThread: +/* +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"), @@ -7,14 +11,40 @@ 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 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, +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. +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 <mutex> + using MutexAutoLock = std::lock_guard<std::mutex>; +#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 0000000000000000000000000000000000000000..00332eaa03dc0f540578f86d51523a3296fdad94 --- /dev/null +++ b/src/threading/semaphore.cpp @@ -0,0 +1,161 @@ +/* +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 "threading/semaphore.h" + +#include <iostream> +#include <cstdlib> +#include <cassert> + +#define UNUSED(expr) do { (void)(expr); } while (0) + +#ifdef _WIN32 + #define MAX_SEMAPHORE_COUNT LONG_MAX - 1 +#else + #include <cerrno> + #include <sys/time.h> + #include <pthread.h> + #if defined(__MACH__) && defined(__APPLE__) + #include <mach/mach.h> + #include <mach/task.h> + #include <mach/semaphore.h> + #include <sys/semaphore.h> + #include <unistd.h> + + #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/jthread/jsemaphore.h b/src/threading/semaphore.h similarity index 57% rename from src/jthread/jsemaphore.h rename to src/threading/semaphore.h index 32e9bc2f27eb108ce6820a63c0fc0d4e9b127bdf..58d758f2ebad41c55c396b4a50842b6b5885358b 100644 --- a/src/jthread/jsemaphore.h +++ b/src/threading/semaphore.h @@ -1,6 +1,6 @@ /* Minetest -Copyright (C) 2013 sapier, < sapier AT gmx DOT net > +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 @@ -17,48 +17,36 @@ 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_ +#ifndef THREADING_SEMAPHORE_H +#define THREADING_SEMAPHORE_H -#if defined(WIN32) -#include <windows.h> -#include <assert.h> -#define MAX_SEMAPHORE_COUNT 1024 +#if defined(_WIN32) + #include <windows.h> #elif defined(__MACH__) && defined(__APPLE__) -#include <pthread.h> -#include <mach/mach.h> -#include <mach/task.h> -#include <mach/semaphore.h> -#include <sys/semaphore.h> -#include <errno.h> -#include <time.h> + #include <mach/semaphore.h> #else -#include <pthread.h> -#include <semaphore.h> + #include <semaphore.h> #endif -class JSemaphore { -public: - JSemaphore(); - ~JSemaphore(); - JSemaphore(int initval); - void Post(); - void Wait(); - bool Wait(unsigned int time_ms); +class Semaphore { +public: + Semaphore(int val=0); + ~Semaphore(); - int GetValue(); + void post(unsigned int num=1); + void wait(); + bool wait(unsigned int time_ms); private: #if defined(WIN32) - HANDLE m_hSemaphore; + HANDLE semaphore; #elif defined(__MACH__) && defined(__APPLE__) - semaphore_t m_semaphore; - int semcount; + semaphore_t semaphore; #else - sem_t m_semaphore; + sem_t semaphore; #endif }; +#endif -#endif /* JSEMAPHORE_H_ */ diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1cb720afac976bdbf8c827964cacd3f5e71b196 --- /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 <chrono> +#else + #define UNUSED(expr) do { (void)(expr); } while (0) +# ifdef _WIN32 +# ifndef _WIN32_WCE + #include <process.h> +# endif +# else + #include <ctime> + #include <cassert> + #include <cstdlib> + #include <sys/time.h> + + // For getNumberOfProcessors + #include <unistd.h> +# if defined(__FreeBSD__) || defined(__APPLE__) + #include <sys/types.h> + #include <sys/sysctl.h> +# elif defined(_GNU_SOURCE) + #include <sys/sysinfo.h> +# endif +# endif +#endif + + +// For setName +#if defined(linux) || defined(__linux) + #include <sys/prctl.h> +#elif defined(__FreeBSD__) || defined(__OpenBSD__) + #include <pthread_np.h> +#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 <sched.h> +#elif defined(__sun) || defined(sun) + #include <sys/types.h> + #include <sys/processor.h> + #include <sys/procset.h> +#elif defined(_AIX) + #include <sys/processor.h> +#elif defined(__APPLE__) + #include <mach/mach_init.h> + #include <mach/thread_policy.h> +#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<Thread *>(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 0000000000000000000000000000000000000000..275bc9b6da5c06d4c0e5800edcf4839a81266ac8 --- /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 <string> +#if __cplusplus >= 201103L + #include <thread> +#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<bool> request_stop; + Atomic<bool> 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<bool> started; +# endif +#endif +}; + +#endif + diff --git a/src/threads.h b/src/threads.h index 503fa6abf32f3fa6d9d2f1f1d9e2117f50ca3e88..bc3bf571d2d8a44aafdadd2b6b6f3dfa6a86e5c7 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 bdff14f05c9c1c8e3b4b4404925ab18f81c0f789..a07ed8ba5ace062530eb72ff6125f013f6ee2369 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 0000000000000000000000000000000000000000..a5d98f0a6f2d627c22636ea8c83b055601de4ff5 --- /dev/null +++ b/src/unittest/test_threading.cpp @@ -0,0 +1,85 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com> + +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<u32> &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<u32> &val; + Semaphore &trigger; +}; + + +void TestThreading::testAtomicSemaphoreThread() +{ + Atomic<u32> 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 267d54c16632cce645aee9df2db856b831d3cc0e..7f66b89ac303531ea1fe20f2733498280624bc2e 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 <list> #include <vector> #include <map> @@ -81,111 +81,47 @@ template<typename Key, typename Value> 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<Key, Value>::iterator n; - n = m_values.find(name); - - if(n == m_values.end()) + MutexAutoLock lock(m_mutex); + typename std::map<Key, Value>::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<Value> getValues() + std::vector<Value> getValues() const { + MutexAutoLock lock(m_mutex); std::vector<Value> result; - for(typename std::map<Key, Value>::iterator - i = m_values.begin(); - i != m_values.end(); ++i){ - result.push_back(i->second); + for (typename std::map<Key, Value>::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<Key, Value> 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<typename T> -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<T, u32>::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<T> m_id_to_value; - std::map<T, u32> m_value_to_id; -}; - -/* -Thread-safe FIFO queue (well, actually a FILO also) -*/ +// Thread-safe Double-ended queue template<typename T> class MutexedQueue @@ -194,19 +130,18 @@ class MutexedQueue template<typename Key, typename U, typename Caller, typename CallerData> 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 @@ class MutexedQueue */ 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 @@ class MutexedQueue 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 @@ class MutexedQueue /* 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 @@ class MutexedQueue } protected: - JMutex & getMutex() - { - return m_mutex; - } + Mutex &getMutex() { return m_mutex; } - std::deque<T> & getQueue() - { - return m_queue; - } + std::deque<T> &getQueue() { return m_queue; } std::deque<T> m_queue; - JMutex m_mutex; - JSemaphore m_size; + mutable Mutex m_mutex; + Semaphore m_signal; }; template<typename K, typename V> diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index 3fd1c9cf9ef44574f12760eef69d1a586511ee2e..bfd5d6e387f3b972e9662a0c90a36c91d9518d8e 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 <string.h> #include <iostream> std::map<u16, std::vector<v3s16> > 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<v3s16> 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 9fe08434f5df6af6b6132accf0cd01600bdb718d..8a17d892d1855d5c1a87f185d1c68734f272d375 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 <list> #include <map> #include <vector> @@ -42,7 +42,7 @@ class FacePositionCache private: static void generateFacePosition(u16 d); static std::map<u16, std::vector<v3s16> > 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 b3a5e68a2179ca20d70ca63bbcf771eeee8a0b93..a32871aab87dfcb1f956c6d4ec86e8a0382c2b3e 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 @@ class MutexedVariable { 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 @@ class RequestQueue { typename std::list<CallerInfo<Caller, CallerData, Key, T> >::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 @@ class RequestQueue { MutexedQueue<GetRequest<Key, T, Caller, CallerData> > 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 @@ class UpdateThread : public JThread { protected: virtual void doUpdate() = 0; - virtual const char *getName() = 0; private: - JSemaphore m_update_sem; + Semaphore m_update_sem; }; #endif