diff --git a/Android/native/jni/Android.mk b/Android/native/jni/Android.mk index 08b4b9faf..e1b63838d 100644 --- a/Android/native/jni/Android.mk +++ b/Android/native/jni/Android.mk @@ -167,7 +167,9 @@ LOCAL_SRC_FILES := \ ../../src/script/lua_api/l_util.cpp \ ../../src/script/lua_api/l_vmanip.cpp \ $(wildcard ../../src/server/*.cpp) \ - $(wildcard ../../src/threading/*.cpp) \ + ../../src/threading/event.cpp \ + ../../src/threading/sdl_semaphore.cpp \ + ../../src/threading/sdl_thread.cpp \ $(wildcard ../../src/util/*.c) \ $(wildcard ../../src/util/*.cpp) \ ../../src/ban.cpp \ diff --git a/Apple/MultiCraft/MultiCraft.xcodeproj/project.pbxproj b/Apple/MultiCraft/MultiCraft.xcodeproj/project.pbxproj index da3d9d60e..07d58179f 100644 --- a/Apple/MultiCraft/MultiCraft.xcodeproj/project.pbxproj +++ b/Apple/MultiCraft/MultiCraft.xcodeproj/project.pbxproj @@ -130,6 +130,8 @@ 846F883B27A59704007B6210 /* libluajit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 846F883A27A596F9007B6210 /* libluajit.a */; }; 847C6D4B25D6F483008F5FC8 /* lutf8lib.c in Sources */ = {isa = PBXBuildFile; fileRef = 847C6D4A25D6F483008F5FC8 /* lutf8lib.c */; }; 8488539F28DA4857004AD90F /* libjpeg.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8488539E28DA4851004AD90F /* libjpeg.a */; }; + 848920FD29984994001CB194 /* sdl_semaphore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 848920FA29984994001CB194 /* sdl_semaphore.cpp */; }; + 848920FE29984994001CB194 /* sdl_thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 848920FB29984994001CB194 /* sdl_thread.cpp */; }; 848ADEF427BD68AE001C60F3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 848ADEF627BD68AE001C60F3 /* Localizable.strings */; }; 848CE6E527778E38001D3E0F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 848CE6E427778E30001D3E0F /* libz.tbd */; }; 8495BD1628B80B14009FCF4D /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8495BD1528B80B00009FCF4D /* libSDL2.a */; }; @@ -138,8 +140,6 @@ 8495BD2A28B81170009FCF4D /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8495BD2928B81170009FCF4D /* Carbon.framework */; }; 849D0847278AC1B200471354 /* lchacha.c in Sources */ = {isa = PBXBuildFile; fileRef = 849D0845278AC1B200471354 /* lchacha.c */; }; 849D0848278AC1B200471354 /* chacha.c in Sources */ = {isa = PBXBuildFile; fileRef = 849D0846278AC1B200471354 /* chacha.c */; }; - 84A1F9B2252E616B00000717 /* semaphore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A1F9AC252E616B00000717 /* semaphore.cpp */; }; - 84A1F9B3252E616B00000717 /* thread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A1F9AF252E616B00000717 /* thread.cpp */; }; 84A1F9BB252E617D00000717 /* scripting_mainmenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A1F9B5252E617D00000717 /* scripting_mainmenu.cpp */; }; 84A1F9BC252E617D00000717 /* scripting_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A1F9B8252E617D00000717 /* scripting_client.cpp */; }; 84A1F9BD252E617D00000717 /* scripting_server.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84A1F9B9252E617D00000717 /* scripting_server.cpp */; }; @@ -547,6 +547,10 @@ 847C6D4925D6F483008F5FC8 /* unidata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unidata.h; path = ../../../lib/luautf8/unidata.h; sourceTree = ""; }; 847C6D4A25D6F483008F5FC8 /* lutf8lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lutf8lib.c; path = ../../../lib/luautf8/lutf8lib.c; sourceTree = ""; }; 8488539E28DA4851004AD90F /* libjpeg.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libjpeg.a; path = ../deps/libjpeg/libjpeg.a; sourceTree = ""; }; + 848920F929984994001CB194 /* sdl_semaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sdl_semaphore.h; path = ../../../src/threading/sdl_semaphore.h; sourceTree = ""; }; + 848920FA29984994001CB194 /* sdl_semaphore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sdl_semaphore.cpp; path = ../../../src/threading/sdl_semaphore.cpp; sourceTree = ""; }; + 848920FB29984994001CB194 /* sdl_thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sdl_thread.cpp; path = ../../../src/threading/sdl_thread.cpp; sourceTree = ""; }; + 848920FC29984994001CB194 /* sdl_thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sdl_thread.h; path = ../../../src/threading/sdl_thread.h; sourceTree = ""; }; 848ADEF527BD68AE001C60F3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 848ADEF827BD6904001C60F3 /* bg */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = bg; path = bg.lproj/Localizable.strings; sourceTree = ""; }; 848ADEF927BD695E001C60F3 /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; @@ -578,13 +582,9 @@ 849D0844278AC1B200471354 /* ecrypt-machine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ecrypt-machine.h"; path = "../../../lib/luachacha/ecrypt-machine.h"; sourceTree = ""; }; 849D0845278AC1B200471354 /* lchacha.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = lchacha.c; path = ../../../lib/luachacha/lchacha.c; sourceTree = ""; }; 849D0846278AC1B200471354 /* chacha.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = chacha.c; path = ../../../lib/luachacha/chacha.c; sourceTree = ""; }; - 84A1F9A6252E616A00000717 /* thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = thread.h; path = ../../../src/threading/thread.h; sourceTree = ""; }; 84A1F9A7252E616A00000717 /* mutex_auto_lock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mutex_auto_lock.h; path = ../../../src/threading/mutex_auto_lock.h; sourceTree = ""; }; 84A1F9A8252E616A00000717 /* event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = event.cpp; path = ../../../src/threading/event.cpp; sourceTree = ""; }; - 84A1F9AC252E616B00000717 /* semaphore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = semaphore.cpp; path = ../../../src/threading/semaphore.cpp; sourceTree = ""; }; - 84A1F9AD252E616B00000717 /* semaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = semaphore.h; path = ../../../src/threading/semaphore.h; sourceTree = ""; }; 84A1F9AE252E616B00000717 /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = event.h; path = ../../../src/threading/event.h; sourceTree = ""; }; - 84A1F9AF252E616B00000717 /* thread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = thread.cpp; path = ../../../src/threading/thread.cpp; sourceTree = ""; }; 84A1F9B5252E617D00000717 /* scripting_mainmenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = scripting_mainmenu.cpp; path = ../../../src/script/scripting_mainmenu.cpp; sourceTree = ""; }; 84A1F9B6252E617D00000717 /* scripting_client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scripting_client.h; path = ../../../src/script/scripting_client.h; sourceTree = ""; }; 84A1F9B7252E617D00000717 /* scripting_mainmenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scripting_mainmenu.h; path = ../../../src/script/scripting_mainmenu.h; sourceTree = ""; }; @@ -1544,10 +1544,10 @@ 84A1F9A8252E616A00000717 /* event.cpp */, 84A1F9AE252E616B00000717 /* event.h */, 84A1F9A7252E616A00000717 /* mutex_auto_lock.h */, - 84A1F9AC252E616B00000717 /* semaphore.cpp */, - 84A1F9AD252E616B00000717 /* semaphore.h */, - 84A1F9AF252E616B00000717 /* thread.cpp */, - 84A1F9A6252E616A00000717 /* thread.h */, + 848920FA29984994001CB194 /* sdl_semaphore.cpp */, + 848920F929984994001CB194 /* sdl_semaphore.h */, + 848920FB29984994001CB194 /* sdl_thread.cpp */, + 848920FC29984994001CB194 /* sdl_thread.h */, ); name = threading; sourceTree = ""; @@ -1819,7 +1819,6 @@ 84135C2125D526D700CA4DCF /* sound.cpp in Sources */, 84135B8B25D5264C00CA4DCF /* noise.cpp in Sources */, 84F20E2A25D5282A009562A9 /* l_minimap.cpp in Sources */, - 84A1F9B2252E616B00000717 /* semaphore.cpp in Sources */, 84F20F1825D52958009562A9 /* guiScrollContainer.cpp in Sources */, 84135B6425D5264B00CA4DCF /* map_settings_manager.cpp in Sources */, 84F20F4425D52975009562A9 /* dungeongen.cpp in Sources */, @@ -1871,6 +1870,7 @@ 84F20F4D25D52975009562A9 /* mapgen_v7.cpp in Sources */, 84F20E8F25D52868009562A9 /* directiontables.cpp in Sources */, 84F20E5625D5283F009562A9 /* player_sao.cpp in Sources */, + 848920FD29984994001CB194 /* sdl_semaphore.cpp in Sources */, 84135B8C25D5264C00CA4DCF /* serverenvironment.cpp in Sources */, 84F20E5325D5283F009562A9 /* luaentity_sao.cpp in Sources */, 84F20F1425D52958009562A9 /* guiKeyChangeMenu.cpp in Sources */, @@ -1887,6 +1887,7 @@ 84135C1425D526D700CA4DCF /* inputhandler.cpp in Sources */, 84F20E3E25D5282A009562A9 /* l_vmanip.cpp in Sources */, 84F20E3325D5282A009562A9 /* l_areastore.cpp in Sources */, + 848920FE29984994001CB194 /* sdl_thread.cpp in Sources */, 84F20DB725D527D8009562A9 /* c_converter.cpp in Sources */, 84135B7125D5264B00CA4DCF /* tool.cpp in Sources */, 84135BA125D5264C00CA4DCF /* serialization.cpp in Sources */, @@ -1979,7 +1980,6 @@ 84135B7F25D5264C00CA4DCF /* version.cpp in Sources */, 84F20F0C25D52958009562A9 /* guiAnimatedImage.cpp in Sources */, 84135C1A25D526D700CA4DCF /* clientmap.cpp in Sources */, - 84A1F9B3252E616B00000717 /* thread.cpp in Sources */, 84F20F0125D52958009562A9 /* guiInventoryList.cpp in Sources */, 84F20EA525D528C5009562A9 /* factory.cpp in Sources */, 84F20E2425D5282A009562A9 /* l_env.cpp in Sources */, diff --git a/src/ban.h b/src/ban.h index 0a425e296..975efd2c0 100644 --- a/src/ban.h +++ b/src/ban.h @@ -19,8 +19,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include "IrrCompileConfig.h" + #include "util/string.h" +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ +#include "threading/sdl_thread.h" +#else #include "threading/thread.h" +#endif #include "exceptions.h" #include #include diff --git a/src/network/connectionthreads.h b/src/network/connectionthreads.h index efd3ddda0..58ce666c9 100644 --- a/src/network/connectionthreads.h +++ b/src/network/connectionthreads.h @@ -20,8 +20,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include "IrrCompileConfig.h" + #include +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ +#include "threading/sdl_thread.h" +#else #include "threading/thread.h" +#endif #include "connection.h" namespace con diff --git a/src/porting_android.cpp b/src/porting_android.cpp index 1ca848be5..5629a4f7d 100644 --- a/src/porting_android.cpp +++ b/src/porting_android.cpp @@ -23,10 +23,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #error This file may only be compiled for android! #endif +#include "IrrCompileConfig.h" + #include "util/numeric.h" #include "porting.h" #include "porting_android.h" +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ +#include "threading/sdl_thread.h" +#else #include "threading/thread.h" +#endif #include "config.h" #include "filesys.h" #include "log.h" @@ -54,8 +60,6 @@ extern "C" int SDL_main(int argc, char *argv[]) return 0; } - Thread::setName("Main"); - try { char *argv[] = {strdup(PROJECT_NAME), nullptr}; real_main(ARRLEN(argv) - 1, argv); diff --git a/src/script/cpp_api/s_async.h b/src/script/cpp_api/s_async.h index 8413dd420..6c129f745 100644 --- a/src/script/cpp_api/s_async.h +++ b/src/script/cpp_api/s_async.h @@ -19,12 +19,19 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include "IrrCompileConfig.h" + #include #include #include +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ +#include "threading/sdl_semaphore.h" +#include "threading/sdl_thread.h" +#else #include "threading/semaphore.h" #include "threading/thread.h" +#endif #include "lua.h" #include "cpp_api/s_base.h" diff --git a/src/terminal_chat_console.h b/src/terminal_chat_console.h index 067d560af..5b971f975 100644 --- a/src/terminal_chat_console.h +++ b/src/terminal_chat_console.h @@ -19,8 +19,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include "IrrCompileConfig.h" + #include "chat.h" +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ +#include "threading/sdl_thread.h" +#else #include "threading/thread.h" +#endif #include "util/container.h" #include "log.h" #include diff --git a/src/threading/CMakeLists.txt b/src/threading/CMakeLists.txt index 8f86158be..5b7ded611 100644 --- a/src/threading/CMakeLists.txt +++ b/src/threading/CMakeLists.txt @@ -2,5 +2,7 @@ set(JTHREAD_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/event.cpp ${CMAKE_CURRENT_SOURCE_DIR}/thread.cpp ${CMAKE_CURRENT_SOURCE_DIR}/semaphore.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sdl_semaphore.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sdl_thread.cpp PARENT_SCOPE) diff --git a/src/threading/sdl_semaphore.cpp b/src/threading/sdl_semaphore.cpp new file mode 100644 index 000000000..2c8379f36 --- /dev/null +++ b/src/threading/sdl_semaphore.cpp @@ -0,0 +1,71 @@ +/* +MultiCraft +Copyright (C) 2013 sapier +Copyright (C) 2023 Dawid Gan + +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 3.0 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/sdl_semaphore.h" + +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ + +#include + +#define UNUSED(expr) \ + do { \ + (void)(expr); \ + } while (0) + +Semaphore::Semaphore(int val) +{ + semaphore = SDL_CreateSemaphore(val); +} + +Semaphore::~Semaphore() +{ + SDL_DestroySemaphore(semaphore); +} + +void Semaphore::post(unsigned int num) +{ + assert(num > 0); + for (unsigned i = 0; i < num; i++) { + int ret = SDL_SemPost(semaphore); + assert(!ret); + UNUSED(ret); + } +} + +void Semaphore::wait() +{ + int ret = SDL_SemWait(semaphore); + assert(!ret); + UNUSED(ret); +} + +bool Semaphore::wait(unsigned int time_ms) +{ + int ret; + if (time_ms > 0) { + ret = SDL_SemWaitTimeout(semaphore, time_ms); + } else { + ret = SDL_SemTryWait(semaphore); + } + assert(!ret || ret == SDL_MUTEX_TIMEDOUT); + return !ret; +} + +#endif diff --git a/src/threading/sdl_semaphore.h b/src/threading/sdl_semaphore.h new file mode 100644 index 000000000..534943910 --- /dev/null +++ b/src/threading/sdl_semaphore.h @@ -0,0 +1,48 @@ +/* +MultiCraft +Copyright (C) 2013 sapier +Copyright (C) 2023 Dawid Gan + +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 3.0 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. +*/ + +#pragma once + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ + +#include "porting.h" +#include "util/basic_macros.h" + +#include + +class Semaphore +{ +public: + Semaphore(int val = 0); + ~Semaphore(); + + DISABLE_CLASS_COPY(Semaphore); + + void post(unsigned int num = 1); + void wait(); + bool wait(unsigned int time_ms); + +private: + SDL_sem *semaphore; +}; + +#endif diff --git a/src/threading/sdl_thread.cpp b/src/threading/sdl_thread.cpp new file mode 100644 index 000000000..d80f7ae85 --- /dev/null +++ b/src/threading/sdl_thread.cpp @@ -0,0 +1,153 @@ +/* +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) +Copyright (c) 2023 Dawid Gan + +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/sdl_thread.h" +#include "threading/mutex_auto_lock.h" +#include "log.h" +#include "porting.h" + +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ + +Thread::Thread(const std::string &name) : + m_name(name), m_request_stop(false), m_running(false) +{ +} + +Thread::~Thread() +{ + m_running = false; + wait(); + + // Make sure start finished mutex is unlocked before it's destroyed + if (m_start_finished_mutex.try_lock()) + m_start_finished_mutex.unlock(); +} + +bool Thread::start() +{ + MutexAutoLock lock(m_mutex); + + if (m_running) + return false; + + m_request_stop = false; + + // The mutex may already be locked if the thread is being restarted + m_start_finished_mutex.try_lock(); + + m_thread_obj = SDL_CreateThread(&threadProc, m_name.c_str(), this); + + if (!m_thread_obj) + return false; + + // Allow spawned thread to continue + m_start_finished_mutex.unlock(); + + while (!m_running) + sleep_ms(1); + + m_joinable = true; + + return true; +} + +bool Thread::stop() +{ + m_request_stop = true; + return true; +} + +bool Thread::wait() +{ + MutexAutoLock lock(m_mutex); + + if (!m_joinable) + return false; + + SDL_WaitThread(m_thread_obj, NULL); + + m_thread_obj = nullptr; + + assert(m_running == false); + m_joinable = false; + return true; +} + +bool Thread::getReturnValue(void **ret) +{ + if (m_running) + return false; + + *ret = m_retval; + return true; +} + +int Thread::threadProc(void *data) +{ + Thread *thr = (Thread *)data; + + g_logger.registerThread(thr->m_name); + thr->m_running = true; + + // Wait for the thread that started this one to finish initializing the + // thread handle so that getThreadId/getThreadHandle will work. + thr->m_start_finished_mutex.lock(); + + thr->m_retval = thr->run(); + + thr->m_running = false; + // Unlock m_start_finished_mutex to prevent data race condition on Windows. + // On Windows with VS2017 build TerminateThread is called and this mutex is not + // released. We try to unlock it from caller thread and it's refused by system. + thr->m_start_finished_mutex.unlock(); + g_logger.deregisterThread(); + + return 0; +} + +void Thread::setName(const std::string &name) +{ + // Name can be set only during thread creation. +} + +unsigned int Thread::getNumberOfProcessors() +{ + return SDL_GetCPUCount(); +} + +bool Thread::bindToProcessor(unsigned int proc_number) +{ + // Not available in SDL + return false; +} + +bool Thread::setPriority(SDL_ThreadPriority prio) +{ + int result = SDL_SetThreadPriority(prio); + return result == 0; +} + +#endif diff --git a/src/threading/sdl_thread.h b/src/threading/sdl_thread.h new file mode 100644 index 000000000..c38be503a --- /dev/null +++ b/src/threading/sdl_thread.h @@ -0,0 +1,130 @@ +/* +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) +Copyright (c) 2023 Dawid Gan + +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. +*/ + +#pragma once + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ + +#include "util/basic_macros.h" + +#include +#include +#include + +#include + +class Thread +{ +public: + Thread(const std::string &name = ""); + virtual ~Thread(); + DISABLE_CLASS_COPY(Thread) + + /* + * Begins execution of a new thread at the pure virtual method Thread::run(). + * Execution of the thread is guaranteed to have started after this function + * returns. + */ + bool start(); + + /* + * Requests that the thread exit gracefully. + * Returns immediately; thread execution is guaranteed to be complete after + * a subsequent call to Thread::wait. + */ + bool stop(); + + /* + * Waits for thread to finish. + * Note: This does not stop a thread, you have to do this on your own. + * Returns false immediately if the thread is not started or has been waited + * on before. + */ + bool wait(); + + /* + * Returns true if the calling thread is this Thread object. + */ + bool isCurrentThread() { return SDL_ThreadID() == getThreadId(); } + + bool isRunning() { return m_running; } + bool stopRequested() { return m_request_stop; } + + SDL_threadID getThreadId() { return SDL_GetThreadID(m_thread_obj); } + + /* + * Gets the thread return value. + * Returns true if the thread has exited and the return value was available, + * or false if the thread has yet to finish. + */ + bool getReturnValue(void **ret); + + /* + * Binds (if possible, otherwise sets the affinity of) the thread to the + * specific processor specified by proc_number. + */ + bool bindToProcessor(unsigned int proc_number); + + /* + * Sets the thread priority to the specified priority. + * + * prio can be one of: SDL_THREAD_PRIORITY_LOW, SDL_THREAD_PRIORITY_NORMAL, + * SDL_THREAD_PRIORITY_HIGH. + */ + bool setPriority(SDL_ThreadPriority prio); + + /* + * Sets the currently executing thread's name to where supported; useful + * for debugging. + */ + static void setName(const std::string &name); + + /* + * Returns the number of processors/cores configured and active on this machine. + */ + static unsigned int getNumberOfProcessors(); + +protected: + std::string m_name; + + virtual void *run() = 0; + +private: + static int threadProc(void *data); + + void *m_retval = nullptr; + bool m_joinable = false; + std::atomic m_request_stop; + std::atomic m_running; + std::mutex m_mutex; + std::mutex m_start_finished_mutex; + + SDL_Thread *m_thread_obj = nullptr; +}; + +#endif diff --git a/src/threading/semaphore.cpp b/src/threading/semaphore.cpp index 87b7af5b1..0dcb93e51 100644 --- a/src/threading/semaphore.cpp +++ b/src/threading/semaphore.cpp @@ -19,6 +19,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "threading/semaphore.h" +#ifndef _IRR_COMPILE_WITH_SDL_DEVICE_ + #include #include #include @@ -165,3 +167,4 @@ bool Semaphore::wait(unsigned int time_ms) #endif } +#endif diff --git a/src/threading/semaphore.h b/src/threading/semaphore.h index b3725c672..79bb4f939 100644 --- a/src/threading/semaphore.h +++ b/src/threading/semaphore.h @@ -19,6 +19,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include "IrrCompileConfig.h" + +#ifndef _IRR_COMPILE_WITH_SDL_DEVICE_ + #if defined(_WIN32) #include #elif defined(__MACH__) && defined(__APPLE__) @@ -50,3 +54,5 @@ private: sem_t semaphore; #endif }; + +#endif diff --git a/src/threading/thread.cpp b/src/threading/thread.cpp index 318624234..b40eeecdb 100644 --- a/src/threading/thread.cpp +++ b/src/threading/thread.cpp @@ -28,6 +28,8 @@ DEALINGS IN THE SOFTWARE. #include "log.h" #include "porting.h" +#ifndef _IRR_COMPILE_WITH_SDL_DEVICE_ + // for setName #if defined(__linux__) #include @@ -344,3 +346,5 @@ bool Thread::setPriority(int prio) #endif } + +#endif diff --git a/src/threading/thread.h b/src/threading/thread.h index 45fb171da..c18a42a23 100644 --- a/src/threading/thread.h +++ b/src/threading/thread.h @@ -25,6 +25,10 @@ DEALINGS IN THE SOFTWARE. #pragma once +#include "IrrCompileConfig.h" + +#ifndef _IRR_COMPILE_WITH_SDL_DEVICE_ + #include "util/basic_macros.h" #include @@ -158,3 +162,4 @@ private: #endif }; +#endif diff --git a/src/unittest/test_threading.cpp b/src/unittest/test_threading.cpp index f3d7fb060..5f2d69789 100644 --- a/src/unittest/test_threading.cpp +++ b/src/unittest/test_threading.cpp @@ -19,9 +19,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "test.h" +#include "IrrCompileConfig.h" + #include +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ +#include "threading/sdl_semaphore.h" +#include "threading/sdl_thread.h" +#else #include "threading/semaphore.h" #include "threading/thread.h" +#endif class TestThreading : public TestBase { diff --git a/src/util/container.h b/src/util/container.h index fe013314d..b30acb4ea 100644 --- a/src/util/container.h +++ b/src/util/container.h @@ -19,10 +19,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include "IrrCompileConfig.h" + #include "irrlichttypes.h" #include "exceptions.h" #include "threading/mutex_auto_lock.h" +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ +#include "threading/sdl_semaphore.h" +#else #include "threading/semaphore.h" +#endif #include #include #include diff --git a/src/util/thread.h b/src/util/thread.h index 66dc7d1fe..93571aa0e 100644 --- a/src/util/thread.h +++ b/src/util/thread.h @@ -19,8 +19,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once +#include "IrrCompileConfig.h" + #include "irrlichttypes.h" +#ifdef _IRR_COMPILE_WITH_SDL_DEVICE_ +#include "threading/sdl_thread.h" +#else #include "threading/thread.h" +#endif #include "threading/mutex_auto_lock.h" #include "porting.h" #include "log.h"