* 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.
doc/doxygen_*
## Build files
-CMakeFiles/*
-src/CMakeFiles/*
-src/Makefile
-src/android_version_githash.h
+CMakeFiles
+Makefile
+!build/android/Makefile
+cmake_install.cmake
+CMakeCache.txt
+CPackConfig.cmake
+CPackSourceConfig.cmake
src/android_version.h
+src/android_version_githash.h
src/cmake_config.h
src/cmake_config_githash.h
-src/cmake_install.cmake
-src/script/CMakeFiles/*
-src/script/common/CMakeFiles/*
-src/script/cpp_api/CMakeFiles/*
-src/script/lua_api/CMakeFiles/*
-src/util/CMakeFiles/*
-src/unittest/CMakeFiles/*
-src/jthread/CMakeFiles/*
-src/jthread/Makefile
-src/jthread/cmake_config.h
-src/jthread/cmake_install.cmake
-src/jthread/libjthread.a
-src/json/libjson.a
src/lua/build/
-src/lua/CMakeFiles/
-src/cguittfont/CMakeFiles/
-src/cguittfont/libcguittfont.a
-src/cguittfont/cmake_install.cmake
-src/cguittfont/Makefile
-src/gmp/CMakeFiles/
-src/gmp/libgmp.a
-src/json/CMakeFiles/
-src/json/libjsoncpp.a
-src/sqlite/CMakeFiles/*
-src/sqlite/libsqlite3.a
-src/client/CMakeFiles/
-src/network/CMakeFiles/
-CMakeCache.txt
-CPackConfig.cmake
-CPackSourceConfig.cmake
-Makefile
-cmake_install.cmake
locale/
.directory
.kdev4/
*.kdev4
*.layout
*.o
+*.a
## Android build files
build/android/assets
jni/src/lua/src/lzio.c \
jni/src/lua/src/print.c
-# sqlite
+# SQLite3
LOCAL_SRC_FILES += deps/sqlite/sqlite3.c
-# jthread
-LOCAL_SRC_FILES += \
- jni/src/jthread/pthread/jevent.cpp \
- jni/src/jthread/pthread/jmutex.cpp \
- jni/src/jthread/pthread/jsemaphore.cpp \
- jni/src/jthread/pthread/jthread.cpp
+# Threading
+LOCAL_SRC_FILES += \
+ jni/src/threading/Mutex.cpp \
+ jni/src/threading/Semaphore.cpp \
+ jni/src/threading/Thread.cpp
-# json
+# JSONCPP
LOCAL_SRC_FILES += jni/src/json/jsoncpp.cpp
LOCAL_SHARED_LIBRARIES := iconv openal ogg vorbis gmp
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
-add_subdirectory(jthread)
+add_subdirectory(threading)
add_subdirectory(network)
add_subdirectory(script)
add_subdirectory(unittest)
#include "ban.h"
#include <fstream>
-#include "jthread/jmutexautolock.h"
+#include "threading/mutex_auto_lock.h"
#include <sstream>
#include <set>
#include "strfnd.h"
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)
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);
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
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 "";
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++);
bool BanManager::isModified()
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
return m_modified;
}
#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
{
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;
#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"
MeshUpdateQueue::~MeshUpdateQueue()
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
for(std::vector<QueuedMeshUpdate*>::iterator
i = m_queue.begin();
assert(data); // pre-condition
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
if(urgent)
m_urgents.insert(p);
// 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
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;
bool Client::isShutdown()
{
- if (!m_mesh_update_thread.IsRunning()) return true;
+ if (!m_mesh_update_thread.isRunning()) return true;
return false;
}
{
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;
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();
}
// 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();
#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>
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
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;
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
// 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;
/*
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())
/*
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()) {
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);
std::string TextureSource::getTextureName(u32 id)
{
- JMutexAutoLock lock(m_textureinfo_cache_mutex);
+ MutexAutoLock lock(m_textureinfo_cache_mutex);
if (id >= m_textureinfo_cache.size())
{
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;
void TextureSource::rebuildImagesAndTextures()
{
- JMutexAutoLock lock(m_textureinfo_cache_mutex);
+ MutexAutoLock lock(m_textureinfo_cache_mutex);
video::IVideoDriver* driver = m_device->getVideoDriver();
sanity_check(driver);
Delete clients
*/
{
- JMutexAutoLock clientslock(m_clients_mutex);
+ MutexAutoLock clientslock(m_clients_mutex);
for(std::map<u16, RemoteClient*>::iterator
i = m_clients.begin();
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();
infostream << "* " << player->getName() << "\t";
{
- JMutexAutoLock clientslock(m_clients_mutex);
+ MutexAutoLock clientslock(m_clients_mutex);
RemoteClient* client = lockedGetClientNoEx(*i);
if(client != NULL)
client->PrintInfo(infostream);
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) {
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
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
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
void ClientInterface::DeleteClient(u16 peer_id)
{
- JMutexAutoLock conlock(m_clients_mutex);
+ MutexAutoLock conlock(m_clients_mutex);
// Error check
std::map<u16, RemoteClient*>::iterator n;
void ClientInterface::CreateClient(u16 peer_id)
{
- JMutexAutoLock conlock(m_clients_mutex);
+ MutexAutoLock conlock(m_clients_mutex);
// Error check
std::map<u16, RemoteClient*>::iterator n;
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;
u16 ClientInterface::getProtocolVersion(u16 peer_id)
{
- JMutexAutoLock conlock(m_clients_mutex);
+ MutexAutoLock conlock(m_clients_mutex);
// Error check
std::map<u16, RemoteClient*>::iterator n;
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;
#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>
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; }
// 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;
ClientMap::~ClientMap()
{
- /*JMutexAutoLock lock(mesh_mutex);
+ /*MutexAutoLock lock(mesh_mutex);
if(mesh != NULL)
{
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;
}
}
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.
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++;
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
// 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
Get the meshbuffers of the block
*/
{
- //JMutexAutoLock lock(block->mesh_mutex);
+ //MutexAutoLock lock(block->mesh_mutex);
MapBlockMesh *mapBlockMesh = block->mesh;
assert(mapBlockMesh);
// 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));
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;
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;
#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
}
std::map<threadid_t, DebugStack*> g_debug_stacks;
-JMutex g_debug_stacks_mutex;
+Mutex g_debug_stacks_mutex;
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;
void debug_stacks_print()
{
- JMutexAutoLock lock(g_debug_stacks_mutex);
+ MutexAutoLock lock(g_debug_stacks_mutex);
DEBUGPRINT("Debug stacks:\n");
{
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);
DebugStacker::~DebugStacker()
{
- JMutexAutoLock lock(g_debug_stacks_mutex);
+ MutexAutoLock lock(g_debug_stacks_mutex);
if(m_overflowed == true)
return;
#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"
{"singlenode", new MapgenFactorySinglenode},
};
-class EmergeThread : public JThread
+class EmergeThread : public Thread
{
public:
Server *m_server;
std::queue<v3s16> blockqueue;
EmergeThread(Server *server, int ethreadid):
- JThread(),
m_server(server),
map(NULL),
emerge(NULL),
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);
// 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;
{
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];
Mapgen *EmergeManager::getCurrentMapgen()
{
for (u32 i = 0; i != emergethread.size(); i++) {
- if (emergethread[i]->IsSameThread())
+ if (emergethread[i]->isSameThread())
return emergethread[i]->mapgen;
}
return;
for (u32 i = 0; i != emergethread.size(); i++)
- emergethread[i]->Start();
+ emergethread[i]->start();
threads_active = true;
}
// 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;
}
flags |= BLOCK_EMERGE_ALLOWGEN;
{
- JMutexAutoLock queuelock(queuemutex);
+ MutexAutoLock queuelock(queuemutex);
count = blocks_enqueued.size();
if (count >= qlimit_total)
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;
{
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)
}
-void *EmergeThread::Thread()
+void *EmergeThread::run()
{
- ThreadStarted();
- log_register_thread("EmergeThread" + itos(id));
DSTACK(__FUNCTION_NAME);
BEGIN_DEBUG_EXCEPTION_HANDLER
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();
{
//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);
}
{
- JMutexAutoLock queuelock(emerge->queuemutex);
+ MutexAutoLock queuelock(emerge->queuemutex);
while (!blockqueue.empty())
{
v3s16 p = blockqueue.front();
}
END_DEBUG_EXCEPTION_HANDLER(errorstream)
- log_deregister_thread();
return NULL;
}
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;
#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<<")"
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;
}
#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;
bool m_cache_enable_shaders;
private:
- JMutex m_timeofday_lock;
- JMutex m_time_lock;
+ Mutex m_timeofday_lock;
+ Mutex m_time_lock;
};
#include <list>
#include <map>
#include <errno.h>
-#include "jthread/jevent.h"
+#include "threading/event.h"
#include "config.h"
#include "exceptions.h"
#include "debug.h"
#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()
{
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);
}
}
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;
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
}
-class CurlFetchThread : public JThread
+class CurlFetchThread : public Thread
{
protected:
enum RequestType {
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;
}
}
- void * Thread()
+ void *run()
{
- ThreadStarted();
- log_register_thread("CurlFetchThread");
DSTACK(__FUNCTION_NAME);
- porting::setThreadName("CurlFetchThread");
-
CurlHandlePool pool;
m_multi = curl_multi_init();
FATAL_ERROR_IF(!m_all_ongoing.empty(), "Expected empty");
- while (!StopRequested()) {
+ while (!stopRequested()) {
BEGIN_DEBUG_EXCEPTION_HANDLER
/*
{
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();
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);
}
}
+++ /dev/null
-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)
-
+++ /dev/null
-The license of JThread:
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-IN THE SOFTWARE.
-
+++ /dev/null
-/*
-
- 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_ */
+++ /dev/null
-/*
-
- 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
+++ /dev/null
-/*
-
- 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
+++ /dev/null
-/*
-Minetest
-Copyright (C) 2013 sapier, < sapier AT gmx DOT net >
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation; either version 2.1 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef JSEMAPHORE_H_
-#define JSEMAPHORE_H_
-
-#if defined(WIN32)
-#include <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 {
-public:
- JSemaphore();
- ~JSemaphore();
- JSemaphore(int initval);
-
- void Post();
- void Wait();
- bool Wait(unsigned int time_ms);
-
- int GetValue();
-
-private:
-#if defined(WIN32)
- HANDLE m_hSemaphore;
-#elif defined(__MACH__) && defined(__APPLE__)
- semaphore_t m_semaphore;
- int semcount;
-#else
- sem_t m_semaphore;
-#endif
-};
-
-
-#endif /* JSEMAPHORE_H_ */
+++ /dev/null
-/*
-
- 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
-
+++ /dev/null
-/*
-
- 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);
-}
+++ /dev/null
-/*
-
- 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);
-}
+++ /dev/null
-/*
-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;
-}
-
+++ /dev/null
-/*
-
- 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();
-}
-
+++ /dev/null
-/*
-
- 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);
-}
+++ /dev/null
-/*
-
- 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;
-}
-
+++ /dev/null
-/*
-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;
-}
-
+++ /dev/null
-/*
-
- 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();
-}
-
#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"
#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)
{
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) {
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)
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);
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);
{
#ifndef SERVER
{
- //JMutexAutoLock lock(mesh_mutex);
+ //MutexAutoLock lock(mesh_mutex);
if(mesh)
{
#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
}
// 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;
// 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) {
std::set<u8> biomes;
//std::list<CutoffData> cutoffs;
- //JMutex cutoff_mutex;
+ //Mutex cutoff_mutex;
};
class DecoSimple : public Decoration {
#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"
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.
bool MinimapUpdateThread::popBlockUpdate(QueuedMinimapUpdate *update)
{
- JMutexAutoLock lock(m_queue_mutex);
+ MutexAutoLock lock(m_queue_mutex);
if (m_update_queue.empty())
return false;
// 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();
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);
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;
bool do_update = false;
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
if (pos != data->old_pos) {
data->old_pos = data->pos;
#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,
class MinimapUpdateThread : public UpdateThread {
public:
+ MinimapUpdateThread() : UpdateThread("Minimap") {}
virtual ~MinimapUpdateThread();
void getMap(v3s16 pos, s16 size, s16 height, bool radar);
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;
};
bool m_enable_shaders;
u16 m_surface_mode_scan_height;
f32 m_angle;
- JMutex m_mutex;
+ Mutex m_mutex;
};
#endif
// 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;
// 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;
// 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());
// 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());
#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
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();
}
bool ReliablePacketBuffer::empty()
{
- JMutexAutoLock listlock(m_list_mutex);
+ MutexAutoLock listlock(m_list_mutex);
return m_list.empty();
}
}
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();
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();
}
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
}
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;
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)
{
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)
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)
{
*/
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;
{
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)
{
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);
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;
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;
u16 Channel::readOutgoingSequenceNumber()
{
- JMutexAutoLock internal(m_internal_mutex);
+ MutexAutoLock internal(m_internal_mutex);
return next_outgoing_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++;
}
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;
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;
bool Peer::IncUseCount()
{
- JMutexAutoLock lock(m_exclusive_access_mutex);
+ MutexAutoLock lock(m_exclusive_access_mutex);
if (!m_pending_deletion)
{
void Peer::DecUseCount()
{
{
- JMutexAutoLock lock(m_exclusive_access_mutex);
+ MutexAutoLock lock(m_exclusive_access_mutex);
sanity_check(m_usage > 0);
m_usage--;
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);
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;
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;
}
/* Connection Threads */
/******************************************************************************/
-ConnectionSendThread::ConnectionSendThread( unsigned int max_packet_size,
- float timeout) :
+ConnectionSendThread::ConnectionSendThread(unsigned int max_packet_size,
+ float timeout) :
+ Thread("ConnectionSend"),
m_connection(NULL),
m_max_packet_size(max_packet_size),
m_timeout(timeout),
{
}
-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);
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();
void ConnectionSendThread::Trigger()
{
- m_send_sleep_semaphore.Post();
+ m_send_sleep_semaphore.post();
}
bool ConnectionSendThread::packetsQueued()
}
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--;
}
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);
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));
m_sendThread.setParent(this);
m_receiveThread.setParent(this);
- m_sendThread.Start();
- m_receiveThread.Start();
+ m_sendThread.start();
+ m_receiveThread.start();
}
{
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
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
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()) {
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()) {
/* 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)
/* 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];
bool Connection::Connected()
{
- JMutexAutoLock peerlock(m_peers_mutex);
+ MutexAutoLock peerlock(m_peers_mutex);
if (m_peers.size() != 1)
return false;
/*
Find an unused peer id
*/
- JMutexAutoLock lock(m_peers_mutex);
+ MutexAutoLock lock(m_peers_mutex);
bool out_of_ids = false;
for(;;) {
// Check if exists
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()
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);
}
u16 m_oldest_non_answered_ack;
- JMutex m_list_mutex;
+ Mutex m_list_mutex;
};
/*
// Key is seqnum
std::map<u16, IncomingSplitPacket*> m_buf;
- JMutex m_map_mutex;
+ Mutex m_map_mutex;
};
struct OutgoingPacket
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;
};
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");
};
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;
bool IncUseCount();
void DecUseCount();
- JMutex m_exclusive_access_mutex;
+ Mutex m_exclusive_access_mutex;
bool m_pending_deletion;
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];
}
};
-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();
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;
unsigned int m_max_packets_requeued;
};
-class ConnectionReceiveThread : public JThread {
+class ConnectionReceiveThread : public Thread {
public:
ConnectionReceiveThread(unsigned int max_packet_size);
- void * Thread ();
+ void *run();
- void setParent(Connection* parent) {
- assert(parent != NULL); // Pre-condition
+ void setParent(Connection *parent) {
+ assert(parent); // Pre-condition
m_connection = parent;
}
private:
- void receive ();
+ void receive();
// Returns next data from a buffer if possible
// If found, returns true; if not, false.
// If found, sets peer_id and dst
- bool getFromBuffers (u16 &peer_id, SharedBuffer<u8> &dst);
+ bool getFromBuffers(u16 &peer_id, SharedBuffer<u8> &dst);
bool checkIncomingBuffers(Channel *channel, u16 &peer_id,
SharedBuffer<u8> &dst);
std::list<u16> getPeerIDs()
{
- JMutexAutoLock peerlock(m_peers_mutex);
+ MutexAutoLock peerlock(m_peers_mutex);
return m_peer_ids;
}
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;
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();)
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();)
{
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();)
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())
{
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())
{
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,
void ParticleManager::addParticle(Particle* toadd)
{
- JMutexAutoLock lock(m_particle_list_lock);
+ MutexAutoLock lock(m_particle_list_lock);
m_particles.push_back(toadd);
}
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
#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"
u32 Player::addHud(HudElement *toadd)
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
u32 id = getFreeHudID();
HudElement* Player::getHud(u32 id)
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
if (id < hud.size())
return hud[id];
HudElement* Player::removeHud(u32 id)
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
HudElement* retval = NULL;
if (id < hud.size()) {
void Player::clearHud()
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
while(!hud.empty()) {
delete hud.back();
#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
// Protect some critical areas
// hud for example can be modified by EmergeThread
// and ServerThread
- JMutex m_mutex;
+ Mutex m_mutex;
};
#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
*/
#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
*/
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"
}
}
-#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();
#include "porting.h"
#include "porting_android.h"
+#include "threading/thread.h"
#include "config.h"
#include "filesys.h"
#include "log.h"
int retval = 0;
porting::app_global = app;
- porting::setThreadName("MainThread");
+ Thread::setName("MainThread");
try {
app_dummy();
- char *argv[] = { (char*) "minetest" };
+ char *argv[] = {(char*) "minetest"};
main(sizeof(argv) / sizeof(argv[0]), argv);
- }
- catch(BaseException e) {
+ } catch (BaseException &e) {
std::stringstream msg;
msg << "Exception handled by main: " << e.what();
- const char* message = msg.str().c_str();
+ const char *message = msg.str().c_str();
__android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME, "%s", message);
errorstream << msg << std::endl;
retval = -1;
- }
- catch(...) {
+ } catch (...) {
__android_log_print(ANDROID_LOG_ERROR, PROJECT_NAME,
- "Some exception occured");
+ "An unknown exception occured!");
errorstream << "Uncaught exception in main thread!" << std::endl;
retval = -1;
}
porting::cleanupAndroid();
- errorstream << "Shutting down minetest." << std::endl;
+ errorstream << "Shutting down." << std::endl;
exit(retval);
}
#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()
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);
void avg(const std::string &name, float value)
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
int &count = m_avgcounts[name];
assert(count != -2);
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)
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);
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())
}
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;
*/
#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()
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();
}
}
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;
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;
}
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;
// 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();
}
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;
jobQueue.push_back(toAdd);
- jobQueueCounter.Post();
+ jobQueueCounter.post();
- jobQueueMutex.Unlock();
+ jobQueueMutex.unlock();
return toAdd.id;
}
/******************************************************************************/
LuaJobInfo AsyncEngine::getJob()
{
- jobQueueCounter.Wait();
- jobQueueMutex.Lock();
+ jobQueueCounter.wait();
+ jobQueueMutex.lock();
LuaJobInfo retval;
retval.valid = false;
jobQueue.pop_front();
retval.valid = true;
}
- jobQueueMutex.Unlock();
+ jobQueueMutex.unlock();
return retval;
}
/******************************************************************************/
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();
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);
lua_rawseti(L, top, index++);
}
-
- resultQueueMutex.Unlock();
}
/******************************************************************************/
/******************************************************************************/
AsyncWorkerThread::AsyncWorkerThread(AsyncEngine* jobDispatcher,
- unsigned int threadNum) :
+ const std::string &name) :
+ Thread(name),
ScriptApiBase(),
- jobDispatcher(jobDispatcher),
- threadnum(threadNum)
+ jobDispatcher(jobDispatcher)
{
lua_State *L = getStack();
/******************************************************************************/
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();
}
}
// Main loop
- while (!StopRequested()) {
+ while (!stopRequested()) {
// Wait for job
LuaJobInfo toProcess = jobDispatcher->getJob();
- if (toProcess.valid == false || StopRequested()) {
+ if (toProcess.valid == false || stopRequested()) {
continue;
}
lua_pop(L, 1); // Pop core
- log_deregister_thread();
-
return 0;
}
#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"
};
// 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
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;
std::vector<AsyncWorkerThread*> workerThreads;
// Counter semaphore for job dispatching
- JSemaphore jobQueueCounter;
+ Semaphore jobQueueCounter;
};
#endif // CPP_API_ASYNC_EVENTS_HEADER
}
#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"
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;
#include "debug.h" // assert()
class LockChecker {
public:
- LockChecker(bool* variable) {
+ LockChecker(bool *variable) {
assert(*variable == false);
m_variable = variable;
*m_variable = false;
}
private:
-bool* m_variable;
+ bool *m_variable;
};
#define SCRIPTAPI_LOCK_CHECK LockChecker(&(this->m_locked))
#endif
#define SCRIPTAPI_PRECHECKHEADER \
- JMutexAutoLock(this->m_luastackmutex); \
+ MutexAutoLock(this->m_luastackmutex); \
SCRIPTAPI_LOCK_CHECK; \
realityCheck(); \
lua_State *L = getStack(); \
#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"
{}
};
-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()");
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();
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();
<< 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
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;
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
float dtime;
{
- JMutexAutoLock lock1(m_step_dtime_mutex);
+ MutexAutoLock lock1(m_step_dtime_mutex);
dtime = m_step_dtime;
}
//infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
{
- JMutexAutoLock lock1(m_step_dtime_mutex);
+ MutexAutoLock lock1(m_step_dtime_mutex);
m_step_dtime -= dtime;
}
}
{
- 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)
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,
{
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");
*/
{
//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");
<< 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
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
SendActiveObjectMessages(client->peer_id, unreliable_data, false);
}
}
- m_clients.Unlock();
+ m_clients.unlock();
// Clear buffered_messages
for(std::map<u16, std::vector<ActiveObjectMessage>* >::iterator
*/
{
// 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;
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");
{
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) {
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()));
{
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();
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)
)
{
*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;
}
*patch = client->getPatch();
*vers_string = client->getPatch();
- m_clients.Unlock();
+ m_clients.unlock();
return true;
}
}
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
}
}
}
- m_clients.Unlock();
+ m_clients.unlock();
// Send as reliable
if (pkt.getSize() > 0)
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)
{
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");
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);
total_sending += client->SendingCount();
client->GetNextBlocks(m_env,m_emerge, dtime, queue);
}
- m_clients.Unlock();
+ m_clients.unlock();
}
// Sort.
// 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
client->SentBlock(q.pos);
total_sending++;
}
- m_clients.Unlock();
+ m_clients.unlock();
}
void Server::fillMediaCache()
}
}
{
- JMutexAutoLock env_lock(m_env_mutex);
+ MutexAutoLock env_lock(m_env_mutex);
m_clients.DeleteClient(peer_id);
}
}
// Environment
ServerEnvironment *m_env;
- JMutex m_env_mutex;
+ Mutex m_env_mutex;
// server connection
con::Connection m_con;
// 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;
#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>
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);
bool Settings::parseConfigLines(std::istream &is, const std::string &end)
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
std::string line, name, value;
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();
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);
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()) {
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());
return false;
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
SettingsEntry &entry = set_default ? m_defaults[name] : m_settings[name];
old_group = entry.group;
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);
void Settings::clear()
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
clearNoLock();
}
void Settings::clearDefaults()
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
clearDefaultsNoLock();
}
if (&other == this)
return;
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
try {
std::string val = other.get(name);
if (&other == this)
return;
- JMutexAutoLock lock(m_mutex);
- JMutexAutoLock lock2(other.m_mutex);
+ MutexAutoLock lock(m_mutex);
+ MutexAutoLock lock2(other.m_mutex);
updateNoLock(other);
}
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())
{
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())
{
#include "irrlichttypes_bloated.h"
#include "util/string.h"
-#include "jthread/jmutex.h"
+#include "threading/mutex.h"
#include <string>
#include <map>
#include <list>
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.
};
// 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;
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);
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();
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();
--- /dev/null
+set(JTHREAD_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/mutex.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/thread.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/semaphore.cpp
+ PARENT_SCOPE)
+
--- /dev/null
+/*
+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
+
--- /dev/null
+/*
+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
+
--- /dev/null
+/*
+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
+
--- /dev/null
+/*
+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
--- /dev/null
+/*
+This file is a part of the JThread package, which contains some object-
+oriented thread wrappers for different thread implementations.
+
+Copyright (c) 2000-2006 Jori Liesenborgs (jori.liesenborgs@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef THREADING_MUTEX_AUTO_LOCK_H
+#define THREADING_MUTEX_AUTO_LOCK_H
+
+#if __cplusplus >= 201103L
+ #include <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
+
--- /dev/null
+/*
+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
+}
+
--- /dev/null
+/*
+Minetest
+Copyright (C) 2013 sapier <sapier AT gmx DOT net>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef THREADING_SEMAPHORE_H
+#define THREADING_SEMAPHORE_H
+
+#if defined(_WIN32)
+ #include <windows.h>
+#elif defined(__MACH__) && defined(__APPLE__)
+ #include <mach/semaphore.h>
+#else
+ #include <semaphore.h>
+#endif
+
+
+class Semaphore {
+public:
+ Semaphore(int val=0);
+ ~Semaphore();
+
+ void post(unsigned int num=1);
+ void wait();
+ bool wait(unsigned int time_ms);
+
+private:
+#if defined(WIN32)
+ HANDLE semaphore;
+#elif defined(__MACH__) && defined(__APPLE__)
+ semaphore_t semaphore;
+#else
+ sem_t semaphore;
+#endif
+};
+
+#endif
+
--- /dev/null
+/*
+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
+}
+
--- /dev/null
+/*
+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
+
#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;
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();
${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
--- /dev/null
+/*
+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);
+}
+
#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>
class MutexedMap
{
public:
- MutexedMap()
- {
- }
+ MutexedMap() {}
void set(const Key &name, const Value &value)
{
- JMutexAutoLock lock(m_mutex);
-
+ MutexAutoLock lock(m_mutex);
m_values[name] = value;
}
- bool get(const Key &name, Value *result)
+ bool get(const Key &name, Value *result) const
{
- JMutexAutoLock lock(m_mutex);
-
- typename std::map<Key, Value>::iterator n;
- n = m_values.find(name);
-
- if(n == m_values.end())
+ MutexAutoLock lock(m_mutex);
+ typename std::map<Key, Value>::const_iterator n =
+ m_values.find(name);
+ if (n == m_values.end())
return false;
-
- if(result != NULL)
+ if (result)
*result = n->second;
-
return true;
}
- std::vector<Value> getValues()
+ std::vector<Value> getValues() const
{
+ MutexAutoLock lock(m_mutex);
std::vector<Value> result;
- for(typename std::map<Key, Value>::iterator
- i = m_values.begin();
- i != m_values.end(); ++i){
- result.push_back(i->second);
+ for (typename std::map<Key, Value>::const_iterator
+ it = m_values.begin();
+ it != m_values.end(); ++it){
+ result.push_back(it->second);
}
return result;
}
- void clear ()
- {
- m_values.clear();
- }
+ void clear() { m_values.clear(); }
private:
std::map<Key, Value> m_values;
- JMutex m_mutex;
+ mutable Mutex m_mutex;
};
-/*
-Generates ids for comparable values.
-Id=0 is reserved for "no value".
-Is fast at:
-- Returning value by id (very fast)
-- Returning id by value
-- Generating a new id for a value
-
-Is not able to:
-- Remove an id/value pair (is possible to implement but slow)
-*/
-template<typename T>
-class MutexedIdGenerator
-{
-public:
- MutexedIdGenerator()
- {
- }
-
- // Returns true if found
- bool getValue(u32 id, T &value)
- {
- if(id == 0)
- return false;
- JMutexAutoLock lock(m_mutex);
- if(m_id_to_value.size() < id)
- return false;
- value = m_id_to_value[id-1];
- return true;
- }
-
- // If id exists for value, returns the id.
- // Otherwise generates an id for the value.
- u32 getId(const T &value)
- {
- JMutexAutoLock lock(m_mutex);
- typename std::map<T, u32>::iterator n;
- n = m_value_to_id.find(value);
- if(n != m_value_to_id.end())
- return n->second;
- m_id_to_value.push_back(value);
- u32 new_id = m_id_to_value.size();
- m_value_to_id.insert(value, new_id);
- return new_id;
- }
-
-private:
- JMutex m_mutex;
- // Values are stored here at id-1 position (id 1 = [0])
- std::vector<T> m_id_to_value;
- std::map<T, u32> m_value_to_id;
-};
-
-/*
-Thread-safe FIFO queue (well, actually a FILO also)
-*/
+// Thread-safe Double-ended queue
template<typename T>
class MutexedQueue
template<typename Key, typename U, typename Caller, typename CallerData>
friend class RequestQueue;
- MutexedQueue()
- {
- }
- bool empty()
+ MutexedQueue() {}
+ bool empty() const
{
- JMutexAutoLock lock(m_mutex);
- return (m_queue.size() == 0);
+ MutexAutoLock lock(m_mutex);
+ return m_queue.empty();
}
+
void push_back(T t)
{
- JMutexAutoLock lock(m_mutex);
+ MutexAutoLock lock(m_mutex);
m_queue.push_back(t);
- m_size.Post();
+ m_signal.post();
}
/* this version of pop_front returns a empty element of T on timeout.
*/
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();
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");
}
}
/* 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();
}
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>
#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];
#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>
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
#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"
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;
};
/*
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
MutexedQueue<GetRequest<Key, T, Caller, CallerData> > m_queue;
};
-class UpdateThread : public JThread {
+class UpdateThread : public Thread
+{
public:
- UpdateThread() {}
- virtual ~UpdateThread() {}
+ UpdateThread(const std::string &name) : Thread(name + "Update") {}
+ ~UpdateThread() {}
- void deferUpdate()
- {
- m_update_sem.Post();
- }
+ void deferUpdate() { m_update_sem.post(); }
- void Stop()
+ void stop()
{
- JThread::Stop();
+ Thread::stop();
// give us a nudge
- m_update_sem.Post();
+ m_update_sem.post();
}
- void *Thread()
+ void *run()
{
- ThreadStarted();
-
- const char *thread_name = getName();
- log_register_thread(thread_name);
- porting::setThreadName(thread_name);
-
DSTACK(__FUNCTION_NAME);
BEGIN_DEBUG_EXCEPTION_HANDLER
- while (!StopRequested()) {
- m_update_sem.Wait();
-
- // Empty the queue, just in case doUpdate() is expensive
- while (m_update_sem.GetValue())
- m_update_sem.Wait();
+ while (!stopRequested()) {
+ m_update_sem.wait();
+ // Set semaphore to 0
+ while (m_update_sem.wait(0));
- if (StopRequested())
- break;
+ if (stopRequested()) break;
doUpdate();
}
protected:
virtual void doUpdate() = 0;
- virtual const char *getName() = 0;
private:
- JSemaphore m_update_sem;
+ Semaphore m_update_sem;
};
#endif