forked from Mirrorlandia_minetest/minetest
Clean up threading
* Rename everything. * Strip J prefix. * Change UpperCamelCase functions to lowerCamelCase. * Remove global (!) semaphore count mutex on OSX. * Remove semaphore count getter (unused, unsafe, depended on internal API functions on Windows, and used a hack on OSX). * Add `Atomic<type>`. * Make `Thread` handle thread names. * Add support for C++11 multi-threading. * Combine pthread and win32 sources. * Remove `ThreadStarted` (unused, unneeded). * Move some includes from the headers to the sources. * Move all of `Event` into its header (allows inlining with no new includes). * Make `Event` use `Semaphore` (except on Windows). * Move some porting functions into `Thread`. * Integrate logging with `Thread`. * Add threading test.
This commit is contained in:
parent
6a1047d8c1
commit
e4bff8be94
46
.gitignore
vendored
46
.gitignore
vendored
@ -36,45 +36,18 @@ doc/html/
|
||||
doc/doxygen_*
|
||||
|
||||
## Build files
|
||||
CMakeFiles/*
|
||||
src/CMakeFiles/*
|
||||
src/Makefile
|
||||
src/android_version_githash.h
|
||||
src/android_version.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/
|
||||
CMakeFiles
|
||||
Makefile
|
||||
!build/android/Makefile
|
||||
cmake_install.cmake
|
||||
CMakeCache.txt
|
||||
CPackConfig.cmake
|
||||
CPackSourceConfig.cmake
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
src/android_version.h
|
||||
src/android_version_githash.h
|
||||
src/cmake_config.h
|
||||
src/cmake_config_githash.h
|
||||
src/lua/build/
|
||||
locale/
|
||||
.directory
|
||||
.kdev4/
|
||||
@ -82,6 +55,7 @@ locale/
|
||||
*.kdev4
|
||||
*.layout
|
||||
*.o
|
||||
*.a
|
||||
|
||||
## Android build files
|
||||
build/android/assets
|
||||
|
@ -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
|
||||
# Threading
|
||||
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
|
||||
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
|
||||
|
@ -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)
|
||||
|
18
src/ban.cpp
18
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;
|
||||
}
|
||||
|
||||
|
@ -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 @@ public:
|
||||
void remove(const std::string &ip_or_name);
|
||||
bool isModified();
|
||||
private:
|
||||
JMutex m_mutex;
|
||||
Mutex m_mutex;
|
||||
std::string m_banfilepath;
|
||||
StringMap m_ips;
|
||||
bool m_modified;
|
||||
|
@ -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();
|
||||
|
13
src/client.h
13
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 @@ public:
|
||||
|
||||
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 @@ private:
|
||||
MeshUpdateQueue m_queue_in;
|
||||
|
||||
protected:
|
||||
const char *getName()
|
||||
{ return "MeshUpdateThread"; }
|
||||
virtual void doUpdate();
|
||||
|
||||
public:
|
||||
|
||||
MeshUpdateThread()
|
||||
{
|
||||
}
|
||||
MeshUpdateThread() : UpdateThread("Mesh") {}
|
||||
|
||||
void enqueueUpdate(v3s16 p, MeshMakeData *data,
|
||||
bool ack_block_to_server, bool urgent);
|
||||
|
||||
MutexedQueue<MeshUpdateResult> m_queue_out;
|
||||
|
||||
v3s16 m_camera_offset;
|
||||
|
@ -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
|
||||
|
@ -414,7 +414,7 @@ private:
|
||||
// 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);
|
||||
|
@ -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;
|
||||
|
@ -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 @@ public:
|
||||
|
||||
protected:
|
||||
//TODO find way to avoid this functions
|
||||
void Lock()
|
||||
{ m_clients_mutex.Lock(); }
|
||||
void Unlock()
|
||||
{ m_clients_mutex.Unlock(); }
|
||||
void lock() { m_clients_mutex.lock(); }
|
||||
void unlock() { m_clients_mutex.unlock(); }
|
||||
|
||||
std::map<u16, RemoteClient*>& getClientList()
|
||||
{ return m_clients; }
|
||||
@ -501,14 +499,14 @@ private:
|
||||
|
||||
// Connection
|
||||
con::Connection* m_con;
|
||||
JMutex m_clients_mutex;
|
||||
Mutex m_clients_mutex;
|
||||
// Connected clients (behind the con mutex)
|
||||
std::map<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;
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
|
||||
void updateCamera(v3f pos, v3f dir, f32 fov, v3s16 offset)
|
||||
{
|
||||
JMutexAutoLock lock(m_camera_mutex);
|
||||
MutexAutoLock lock(m_camera_mutex);
|
||||
m_camera_position = pos;
|
||||
m_camera_direction = dir;
|
||||
m_camera_fov = fov;
|
||||
@ -149,7 +149,7 @@ private:
|
||||
v3f m_camera_direction;
|
||||
f32 m_camera_fov;
|
||||
v3s16 m_camera_offset;
|
||||
JMutex m_camera_mutex;
|
||||
Mutex m_camera_mutex;
|
||||
|
||||
std::map<v3s16, MapBlock*> m_drawlist;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 @@ public:
|
||||
std::queue<v3s16> blockqueue;
|
||||
|
||||
EmergeThread(Server *server, int ethreadid):
|
||||
JThread(),
|
||||
m_server(server),
|
||||
map(NULL),
|
||||
emerge(NULL),
|
||||
@ -81,9 +80,10 @@ public:
|
||||
enable_mapgen_debug_info(false),
|
||||
id(ethreadid)
|
||||
{
|
||||
name = "Emerge-" + itos(id);
|
||||
}
|
||||
|
||||
void *Thread();
|
||||
void *run();
|
||||
bool popBlockEmerge(v3s16 *pos, u8 *flags);
|
||||
bool getBlockOrStartGen(v3s16 p, MapBlock **b,
|
||||
BlockMakeData *data, bool allow_generate);
|
||||
@ -112,7 +112,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef)
|
||||
// some other misc thread
|
||||
s16 nthreads = 0;
|
||||
if (!g_settings->getS16NoEx("num_emerge_threads", nthreads))
|
||||
nthreads = porting::getNumberOfProcessors() - 2;
|
||||
nthreads = Thread::getNumberOfProcessors() - 2;
|
||||
if (nthreads < 1)
|
||||
nthreads = 1;
|
||||
|
||||
@ -141,9 +141,9 @@ EmergeManager::~EmergeManager()
|
||||
{
|
||||
for (u32 i = 0; i != emergethread.size(); i++) {
|
||||
if (threads_active) {
|
||||
emergethread[i]->Stop();
|
||||
emergethread[i]->stop();
|
||||
emergethread[i]->qevent.signal();
|
||||
emergethread[i]->Wait();
|
||||
emergethread[i]->wait();
|
||||
}
|
||||
delete emergethread[i];
|
||||
delete mapgen[i];
|
||||
@ -196,7 +196,7 @@ void EmergeManager::initMapgens()
|
||||
Mapgen *EmergeManager::getCurrentMapgen()
|
||||
{
|
||||
for (u32 i = 0; i != emergethread.size(); i++) {
|
||||
if (emergethread[i]->IsSameThread())
|
||||
if (emergethread[i]->isSameThread())
|
||||
return emergethread[i]->mapgen;
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ void EmergeManager::startThreads()
|
||||
return;
|
||||
|
||||
for (u32 i = 0; i != emergethread.size(); i++)
|
||||
emergethread[i]->Start();
|
||||
emergethread[i]->start();
|
||||
|
||||
threads_active = true;
|
||||
}
|
||||
@ -223,13 +223,13 @@ void EmergeManager::stopThreads()
|
||||
|
||||
// Request thread stop in parallel
|
||||
for (u32 i = 0; i != emergethread.size(); i++) {
|
||||
emergethread[i]->Stop();
|
||||
emergethread[i]->stop();
|
||||
emergethread[i]->qevent.signal();
|
||||
}
|
||||
|
||||
// Then do the waiting for each
|
||||
for (u32 i = 0; i != emergethread.size(); i++)
|
||||
emergethread[i]->Wait();
|
||||
emergethread[i]->wait();
|
||||
|
||||
threads_active = false;
|
||||
}
|
||||
@ -247,7 +247,7 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate
|
||||
flags |= BLOCK_EMERGE_ALLOWGEN;
|
||||
|
||||
{
|
||||
JMutexAutoLock queuelock(queuemutex);
|
||||
MutexAutoLock queuelock(queuemutex);
|
||||
|
||||
count = blocks_enqueued.size();
|
||||
if (count >= qlimit_total)
|
||||
@ -360,7 +360,7 @@ MapgenSpecificParams *EmergeManager::createMapgenParams(const std::string &mgnam
|
||||
bool EmergeThread::popBlockEmerge(v3s16 *pos, u8 *flags)
|
||||
{
|
||||
std::map<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;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ public:
|
||||
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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "util/numeric.h"
|
||||
#include "mapnode.h"
|
||||
#include "mapblock.h"
|
||||
#include "jthread/jmutex.h"
|
||||
#include "threading/mutex.h"
|
||||
#include "network/networkprotocol.h" // for AccessDeniedCode
|
||||
|
||||
class ServerEnvironment;
|
||||
@ -127,8 +127,8 @@ protected:
|
||||
bool m_cache_enable_shaders;
|
||||
|
||||
private:
|
||||
JMutex m_timeofday_lock;
|
||||
JMutex m_time_lock;
|
||||
Mutex m_timeofday_lock;
|
||||
Mutex m_time_lock;
|
||||
|
||||
};
|
||||
|
||||
|
@ -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 @@ protected:
|
||||
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 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
void * Thread()
|
||||
void *run()
|
||||
{
|
||||
ThreadStarted();
|
||||
log_register_thread("CurlFetchThread");
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
porting::setThreadName("CurlFetchThread");
|
||||
|
||||
CurlHandlePool pool;
|
||||
|
||||
m_multi = curl_multi_init();
|
||||
@ -631,7 +628,7 @@ protected:
|
||||
|
||||
FATAL_ERROR_IF(!m_all_ongoing.empty(), "Expected empty");
|
||||
|
||||
while (!StopRequested()) {
|
||||
while (!stopRequested()) {
|
||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
/*
|
||||
@ -719,9 +716,9 @@ void httpfetch_cleanup()
|
||||
{
|
||||
verbosestream<<"httpfetch_cleanup: cleaning up"<<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);
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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_ */
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
22
src/log.cpp
22
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);
|
||||
|
@ -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);
|
||||
|
@ -96,7 +96,7 @@ MapBlock::~MapBlock()
|
||||
{
|
||||
#ifndef SERVER
|
||||
{
|
||||
//JMutexAutoLock lock(mesh_mutex);
|
||||
//MutexAutoLock lock(mesh_mutex);
|
||||
|
||||
if(mesh)
|
||||
{
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -84,7 +84,7 @@ public:
|
||||
|
||||
std::set<u8> biomes;
|
||||
//std::list<CutoffData> cutoffs;
|
||||
//JMutex cutoff_mutex;
|
||||
//Mutex cutoff_mutex;
|
||||
};
|
||||
|
||||
class DecoSimple : public Decoration {
|
||||
|
@ -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;
|
||||
|
@ -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 @@ public:
|
||||
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 @@ private:
|
||||
bool m_enable_shaders;
|
||||
u16 m_surface_mode_scan_height;
|
||||
f32 m_angle;
|
||||
JMutex m_mutex;
|
||||
Mutex m_mutex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -1257,6 +1257,7 @@ SharedBuffer<u8> UDPPeer::addSpiltPacket(u8 channel,
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ private:
|
||||
|
||||
u16 m_oldest_non_answered_ack;
|
||||
|
||||
JMutex m_list_mutex;
|
||||
Mutex m_list_mutex;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -372,7 +372,7 @@ private:
|
||||
// Key is seqnum
|
||||
std::map<u16, IncomingSplitPacket*> m_buf;
|
||||
|
||||
JMutex m_map_mutex;
|
||||
Mutex m_map_mutex;
|
||||
};
|
||||
|
||||
struct OutgoingPacket
|
||||
@ -519,32 +519,32 @@ public:
|
||||
void UpdateTimers(float dtime, bool legacy_peer);
|
||||
|
||||
const float getCurrentDownloadRateKB()
|
||||
{ JMutexAutoLock lock(m_internal_mutex); return cur_kbps; };
|
||||
{ MutexAutoLock lock(m_internal_mutex); return cur_kbps; };
|
||||
const float getMaxDownloadRateKB()
|
||||
{ JMutexAutoLock lock(m_internal_mutex); return max_kbps; };
|
||||
{ MutexAutoLock lock(m_internal_mutex); return max_kbps; };
|
||||
|
||||
const float getCurrentLossRateKB()
|
||||
{ JMutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; };
|
||||
{ MutexAutoLock lock(m_internal_mutex); return cur_kbps_lost; };
|
||||
const float getMaxLossRateKB()
|
||||
{ JMutexAutoLock lock(m_internal_mutex); return max_kbps_lost; };
|
||||
{ MutexAutoLock lock(m_internal_mutex); return max_kbps_lost; };
|
||||
|
||||
const float getCurrentIncomingRateKB()
|
||||
{ JMutexAutoLock lock(m_internal_mutex); return cur_incoming_kbps; };
|
||||
{ MutexAutoLock lock(m_internal_mutex); return cur_incoming_kbps; };
|
||||
const float getMaxIncomingRateKB()
|
||||
{ JMutexAutoLock lock(m_internal_mutex); return max_incoming_kbps; };
|
||||
{ MutexAutoLock lock(m_internal_mutex); return max_incoming_kbps; };
|
||||
|
||||
const float getAvgDownloadRateKB()
|
||||
{ JMutexAutoLock lock(m_internal_mutex); return avg_kbps; };
|
||||
{ MutexAutoLock lock(m_internal_mutex); return avg_kbps; };
|
||||
const float getAvgLossRateKB()
|
||||
{ JMutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; };
|
||||
{ MutexAutoLock lock(m_internal_mutex); return avg_kbps_lost; };
|
||||
const float getAvgIncomingRateKB()
|
||||
{ JMutexAutoLock lock(m_internal_mutex); return avg_incoming_kbps; };
|
||||
{ MutexAutoLock lock(m_internal_mutex); return avg_incoming_kbps; };
|
||||
|
||||
const unsigned int getWindowSize() const { return window_size; };
|
||||
|
||||
void setWindowSize(unsigned int size) { window_size = size; };
|
||||
private:
|
||||
JMutex m_internal_mutex;
|
||||
Mutex m_internal_mutex;
|
||||
int window_size;
|
||||
|
||||
u16 next_incoming_seqnum;
|
||||
@ -675,7 +675,7 @@ class Peer {
|
||||
};
|
||||
|
||||
virtual ~Peer() {
|
||||
JMutexAutoLock usage_lock(m_exclusive_access_mutex);
|
||||
MutexAutoLock usage_lock(m_exclusive_access_mutex);
|
||||
FATAL_ERROR_IF(m_usage != 0, "Reference counting failure");
|
||||
};
|
||||
|
||||
@ -692,15 +692,15 @@ class Peer {
|
||||
virtual bool getAddress(MTProtocols type, Address& toset) = 0;
|
||||
|
||||
void ResetTimeout()
|
||||
{JMutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter=0.0; };
|
||||
{MutexAutoLock lock(m_exclusive_access_mutex); m_timeout_counter=0.0; };
|
||||
|
||||
bool isTimedOut(float timeout);
|
||||
|
||||
void setSentWithID()
|
||||
{ JMutexAutoLock lock(m_exclusive_access_mutex); m_has_sent_with_id = true; };
|
||||
{ MutexAutoLock lock(m_exclusive_access_mutex); m_has_sent_with_id = true; };
|
||||
|
||||
bool hasSentWithID()
|
||||
{ JMutexAutoLock lock(m_exclusive_access_mutex); return m_has_sent_with_id; };
|
||||
{ MutexAutoLock lock(m_exclusive_access_mutex); return m_has_sent_with_id; };
|
||||
|
||||
unsigned int m_increment_packets_remaining;
|
||||
unsigned int m_increment_bytes_remaining;
|
||||
@ -744,7 +744,7 @@ class Peer {
|
||||
bool IncUseCount();
|
||||
void DecUseCount();
|
||||
|
||||
JMutex m_exclusive_access_mutex;
|
||||
Mutex m_exclusive_access_mutex;
|
||||
|
||||
bool m_pending_deletion;
|
||||
|
||||
@ -826,10 +826,10 @@ protected:
|
||||
unsigned int maxtransfer);
|
||||
|
||||
float getResendTimeout()
|
||||
{ JMutexAutoLock lock(m_exclusive_access_mutex); return resend_timeout; }
|
||||
{ MutexAutoLock lock(m_exclusive_access_mutex); return resend_timeout; }
|
||||
|
||||
void setResendTimeout(float timeout)
|
||||
{ JMutexAutoLock lock(m_exclusive_access_mutex); resend_timeout = timeout; }
|
||||
{ MutexAutoLock lock(m_exclusive_access_mutex); resend_timeout = timeout; }
|
||||
bool Ping(float dtime,SharedBuffer<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 @@ private:
|
||||
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,14 +969,14 @@ private:
|
||||
unsigned int m_max_packets_requeued;
|
||||
};
|
||||
|
||||
class ConnectionReceiveThread : public JThread {
|
||||
class ConnectionReceiveThread : public Thread {
|
||||
public:
|
||||
ConnectionReceiveThread(unsigned int max_packet_size);
|
||||
|
||||
void * Thread ();
|
||||
void *run();
|
||||
|
||||
void setParent(Connection *parent) {
|
||||
assert(parent != NULL); // Pre-condition
|
||||
assert(parent); // Pre-condition
|
||||
m_connection = parent;
|
||||
}
|
||||
|
||||
@ -1054,7 +1054,7 @@ protected:
|
||||
|
||||
std::list<u16> getPeerIDs()
|
||||
{
|
||||
JMutexAutoLock peerlock(m_peers_mutex);
|
||||
MutexAutoLock peerlock(m_peers_mutex);
|
||||
return m_peer_ids;
|
||||
}
|
||||
|
||||
@ -1075,12 +1075,12 @@ private:
|
||||
|
||||
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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -190,8 +190,8 @@ private:
|
||||
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
|
||||
|
@ -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();
|
||||
|
@ -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 @@ private:
|
||||
// Protect some critical areas
|
||||
// hud for example can be modified by EmergeThread
|
||||
// and ServerThread
|
||||
JMutex m_mutex;
|
||||
Mutex m_mutex;
|
||||
};
|
||||
|
||||
|
||||
|
124
src/porting.cpp
124
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
|
||||
*/
|
||||
|
@ -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();
|
||||
|
@ -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"};
|
||||
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();
|
||||
__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);
|
||||
}
|
||||
|
||||
|
@ -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 @@ public:
|
||||
|
||||
void add(const std::string &name, float value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
{
|
||||
/* No average shall have been used; mark add used as -2 */
|
||||
std::map<std::string, int>::iterator n = m_avgcounts.find(name);
|
||||
@ -72,7 +72,7 @@ public:
|
||||
|
||||
void avg(const std::string &name, float value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
int &count = m_avgcounts[name];
|
||||
|
||||
assert(count != -2);
|
||||
@ -82,7 +82,7 @@ public:
|
||||
|
||||
void clear()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
for(std::map<std::string, float>::iterator
|
||||
i = m_data.begin();
|
||||
i != m_data.end(); ++i)
|
||||
@ -114,7 +114,7 @@ public:
|
||||
|
||||
void printPage(std::ostream &o, u32 page, u32 pagecount)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
u32 minindex, maxindex;
|
||||
paging(m_data.size(), page, pagecount, minindex, maxindex);
|
||||
@ -159,7 +159,7 @@ public:
|
||||
|
||||
void graphAdd(const std::string &id, float value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
std::map<std::string, float>::iterator i =
|
||||
m_graphvalues.find(id);
|
||||
if(i == m_graphvalues.end())
|
||||
@ -169,20 +169,20 @@ public:
|
||||
}
|
||||
void graphGet(GraphValues &result)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
result = m_graphvalues;
|
||||
m_graphvalues.clear();
|
||||
}
|
||||
|
||||
void remove(const std::string& name)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
m_avgcounts.erase(name);
|
||||
m_data.erase(name);
|
||||
}
|
||||
|
||||
private:
|
||||
JMutex m_mutex;
|
||||
Mutex m_mutex;
|
||||
std::map<std::string, float> m_data;
|
||||
std::map<std::string, int> m_avgcounts;
|
||||
std::map<std::string, float> m_graphvalues;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 @@ private:
|
||||
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 @@ private:
|
||||
std::vector<AsyncWorkerThread*> workerThreads;
|
||||
|
||||
// Counter semaphore for job dispatching
|
||||
JSemaphore jobQueueCounter;
|
||||
Semaphore jobQueueCounter;
|
||||
};
|
||||
|
||||
#endif // CPP_API_ASYNC_EVENTS_HEADER
|
||||
|
@ -28,8 +28,8 @@ extern "C" {
|
||||
}
|
||||
|
||||
#include "irrlichttypes.h"
|
||||
#include "jthread/jmutex.h"
|
||||
#include "jthread/jmutexautolock.h"
|
||||
#include "threading/mutex.h"
|
||||
#include "threading/mutex_auto_lock.h"
|
||||
#include "common/c_types.h"
|
||||
#include "common/c_internal.h"
|
||||
|
||||
@ -108,7 +108,7 @@ protected:
|
||||
void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj);
|
||||
void objectrefGet(lua_State *L, u16 id);
|
||||
|
||||
JMutex m_luastackmutex;
|
||||
Mutex m_luastackmutex;
|
||||
std::string m_last_run_mod;
|
||||
// Stack index of Lua error handler
|
||||
int m_errorhandler;
|
||||
|
@ -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(); \
|
||||
|
106
src/server.cpp
106
src/server.cpp
@ -26,7 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "ban.h"
|
||||
#include "environment.h"
|
||||
#include "map.h"
|
||||
#include "jthread/jmutexautolock.h"
|
||||
#include "threading/mutex_auto_lock.h"
|
||||
#include "constants.h"
|
||||
#include "voxel.h"
|
||||
#include "config.h"
|
||||
@ -71,35 +71,29 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
class ServerThread : public JThread
|
||||
class ServerThread : public Thread
|
||||
{
|
||||
Server *m_server;
|
||||
|
||||
public:
|
||||
|
||||
ServerThread(Server *server):
|
||||
JThread(),
|
||||
Thread("Server"),
|
||||
m_server(server)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void * Thread();
|
||||
void *run();
|
||||
|
||||
private:
|
||||
Server *m_server;
|
||||
};
|
||||
|
||||
void *ServerThread::Thread()
|
||||
void *ServerThread::run()
|
||||
{
|
||||
log_register_thread("ServerThread");
|
||||
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
BEGIN_DEBUG_EXCEPTION_HANDLER
|
||||
|
||||
m_server->AsyncRunStep(true);
|
||||
|
||||
ThreadStarted();
|
||||
|
||||
porting::setThreadName("ServerThread");
|
||||
|
||||
while (!StopRequested()) {
|
||||
while (!stopRequested()) {
|
||||
try {
|
||||
//TimeTaker timer("AsyncRunStep() + Receive()");
|
||||
|
||||
@ -267,8 +261,8 @@ Server::Server(
|
||||
errorstream << std::endl;
|
||||
}
|
||||
|
||||
// Lock environment
|
||||
JMutexAutoLock envlock(m_env_mutex);
|
||||
//lock environment
|
||||
MutexAutoLock envlock(m_env_mutex);
|
||||
|
||||
// Load mapgen params from Settings
|
||||
m_emerge->loadMapgenParams();
|
||||
@ -379,7 +373,7 @@ Server::~Server()
|
||||
SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");
|
||||
|
||||
{
|
||||
JMutexAutoLock envlock(m_env_mutex);
|
||||
MutexAutoLock envlock(m_env_mutex);
|
||||
|
||||
// Execute script shutdown hooks
|
||||
m_script->on_shutdown();
|
||||
@ -447,14 +441,14 @@ void Server::start(Address bind_addr)
|
||||
<< bind_addr.serializeString() <<"..."<<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);
|
||||
}
|
||||
}
|
||||
|
@ -516,7 +516,7 @@ private:
|
||||
|
||||
// Environment
|
||||
ServerEnvironment *m_env;
|
||||
JMutex m_env_mutex;
|
||||
Mutex m_env_mutex;
|
||||
|
||||
// server connection
|
||||
con::Connection m_con;
|
||||
@ -557,7 +557,7 @@ private:
|
||||
// A buffer for time steps
|
||||
// step() increments and AsyncRunStep() run by m_thread reads it.
|
||||
float m_step_dtime;
|
||||
JMutex m_step_dtime_mutex;
|
||||
Mutex m_step_dtime_mutex;
|
||||
|
||||
// current server step lag counter
|
||||
float m_lag;
|
||||
|
@ -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())
|
||||
{
|
||||
|
@ -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 @@ private:
|
||||
|
||||
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.
|
||||
|
||||
};
|
||||
|
||||
|
@ -328,7 +328,7 @@ private:
|
||||
// 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();
|
||||
|
6
src/threading/CMakeLists.txt
Normal file
6
src/threading/CMakeLists.txt
Normal file
@ -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)
|
||||
|
96
src/threading/atomic.h
Normal file
96
src/threading/atomic.h
Normal file
@ -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
|
||||
|
57
src/threading/event.h
Normal file
57
src/threading/event.h
Normal file
@ -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
|
||||
|
83
src/threading/mutex.cpp
Normal file
83
src/threading/mutex.cpp
Normal file
@ -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
|
||||
|
66
src/threading/mutex.h
Normal file
66
src/threading/mutex.h
Normal file
@ -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
|
@ -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
|
||||
|
161
src/threading/semaphore.cpp
Normal file
161
src/threading/semaphore.cpp
Normal file
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
#if defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include <assert.h>
|
||||
#define MAX_SEMAPHORE_COUNT 1024
|
||||
#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>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#endif
|
||||
|
||||
class JSemaphore {
|
||||
|
||||
class Semaphore {
|
||||
public:
|
||||
JSemaphore();
|
||||
~JSemaphore();
|
||||
JSemaphore(int initval);
|
||||
Semaphore(int val=0);
|
||||
~Semaphore();
|
||||
|
||||
void Post();
|
||||
void Wait();
|
||||
bool Wait(unsigned int time_ms);
|
||||
|
||||
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_ */
|
354
src/threading/thread.cpp
Normal file
354
src/threading/thread.cpp
Normal file
@ -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
|
||||
}
|
||||
|
119
src/threading/thread.h
Normal file
119
src/threading/thread.h
Normal file
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
85
src/unittest/test_threading.cpp
Normal file
85
src/unittest/test_threading.cpp
Normal file
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
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 @@ public:
|
||||
template<typename Key, typename U, typename Caller, typename CallerData>
|
||||
friend class RequestQueue;
|
||||
|
||||
MutexedQueue()
|
||||
MutexedQueue() {}
|
||||
bool empty() const
|
||||
{
|
||||
MutexAutoLock lock(m_mutex);
|
||||
return m_queue.empty();
|
||||
}
|
||||
bool empty()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
return (m_queue.size() == 0);
|
||||
}
|
||||
|
||||
void push_back(T t)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
m_queue.push_back(t);
|
||||
m_size.Post();
|
||||
m_signal.post();
|
||||
}
|
||||
|
||||
/* this version of pop_front returns a empty element of T on timeout.
|
||||
@ -214,37 +149,35 @@ public:
|
||||
*/
|
||||
T pop_frontNoEx(u32 wait_time_max_ms)
|
||||
{
|
||||
if (m_size.Wait(wait_time_max_ms)) {
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
if (m_signal.wait(wait_time_max_ms)) {
|
||||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
T t = m_queue.front();
|
||||
m_queue.pop_front();
|
||||
return t;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return T();
|
||||
}
|
||||
}
|
||||
|
||||
T pop_front(u32 wait_time_max_ms)
|
||||
{
|
||||
if (m_size.Wait(wait_time_max_ms)) {
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
if (m_signal.wait(wait_time_max_ms)) {
|
||||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
T t = m_queue.front();
|
||||
m_queue.pop_front();
|
||||
return t;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
throw ItemNotFoundException("MutexedQueue: queue is empty");
|
||||
}
|
||||
}
|
||||
|
||||
T pop_frontNoEx()
|
||||
{
|
||||
m_size.Wait();
|
||||
m_signal.wait();
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
T t = m_queue.front();
|
||||
m_queue.pop_front();
|
||||
@ -253,14 +186,13 @@ public:
|
||||
|
||||
T pop_back(u32 wait_time_max_ms=0)
|
||||
{
|
||||
if (m_size.Wait(wait_time_max_ms)) {
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
if (m_signal.wait(wait_time_max_ms)) {
|
||||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
T t = m_queue.back();
|
||||
m_queue.pop_back();
|
||||
return t;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
throw ItemNotFoundException("MutexedQueue: queue is empty");
|
||||
}
|
||||
}
|
||||
@ -268,25 +200,24 @@ public:
|
||||
/* this version of pop_back returns a empty element of T on timeout.
|
||||
* Make sure default constructor of T creates a recognizable "empty" element
|
||||
*/
|
||||
T pop_backNoEx(u32 wait_time_max_ms=0)
|
||||
T pop_backNoEx(u32 wait_time_max_ms)
|
||||
{
|
||||
if (m_size.Wait(wait_time_max_ms)) {
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
if (m_signal.wait(wait_time_max_ms)) {
|
||||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
T t = m_queue.back();
|
||||
m_queue.pop_back();
|
||||
return t;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return T();
|
||||
}
|
||||
}
|
||||
|
||||
T pop_backNoEx()
|
||||
{
|
||||
m_size.Wait();
|
||||
m_signal.wait();
|
||||
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
|
||||
T t = m_queue.back();
|
||||
m_queue.pop_back();
|
||||
@ -294,19 +225,13 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
JMutex & getMutex()
|
||||
{
|
||||
return m_mutex;
|
||||
}
|
||||
Mutex &getMutex() { return m_mutex; }
|
||||
|
||||
std::deque<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>
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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 @@ public:
|
||||
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
|
||||
|
@ -21,9 +21,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define UTIL_THREAD_HEADER
|
||||
|
||||
#include "../irrlichttypes.h"
|
||||
#include "../jthread/jthread.h"
|
||||
#include "../jthread/jmutex.h"
|
||||
#include "../jthread/jmutexautolock.h"
|
||||
#include "../threading/thread.h"
|
||||
#include "../threading/mutex.h"
|
||||
#include "../threading/mutex_auto_lock.h"
|
||||
#include "porting.h"
|
||||
#include "log.h"
|
||||
|
||||
@ -36,27 +36,27 @@ public:
|
||||
|
||||
T get()
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void set(T value)
|
||||
{
|
||||
JMutexAutoLock lock(m_mutex);
|
||||
MutexAutoLock lock(m_mutex);
|
||||
m_value = value;
|
||||
}
|
||||
|
||||
// You'll want to grab this in a SharedPtr
|
||||
JMutexAutoLock *getLock()
|
||||
MutexAutoLock *getLock()
|
||||
{
|
||||
return new JMutexAutoLock(m_mutex);
|
||||
return new MutexAutoLock(m_mutex);
|
||||
}
|
||||
|
||||
// You pretty surely want to grab the lock when accessing this
|
||||
T m_value;
|
||||
|
||||
private:
|
||||
JMutex m_mutex;
|
||||
Mutex m_mutex;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -118,7 +118,7 @@ public:
|
||||
typename std::list<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 @@ private:
|
||||
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();
|
||||
while (!stopRequested()) {
|
||||
m_update_sem.wait();
|
||||
// Set semaphore to 0
|
||||
while (m_update_sem.wait(0));
|
||||
|
||||
// Empty the queue, just in case doUpdate() is expensive
|
||||
while (m_update_sem.GetValue())
|
||||
m_update_sem.Wait();
|
||||
|
||||
if (StopRequested())
|
||||
break;
|
||||
if (stopRequested()) break;
|
||||
|
||||
doUpdate();
|
||||
}
|
||||
@ -241,10 +230,9 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void doUpdate() = 0;
|
||||
virtual const char *getName() = 0;
|
||||
|
||||
private:
|
||||
JSemaphore m_update_sem;
|
||||
Semaphore m_update_sem;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user