From b33f4bb205a5ea3dfd2c213811b3210a895de202 Mon Sep 17 00:00:00 2001 From: Vittorio Romeo Date: Mon, 13 Dec 2021 19:51:02 +0100 Subject: [PATCH] Replace SFML multithreading primitives with standard C++ ones --- examples/island/CMakeLists.txt | 7 +- examples/island/Island.cpp | 24 +- examples/voip/Server.cpp | 7 +- include/SFML/Audio/Music.hpp | 9 +- include/SFML/Audio/SoundRecorder.hpp | 34 ++- include/SFML/Audio/SoundStream.hpp | 46 ++- include/SFML/System.hpp | 5 - include/SFML/System/Lock.hpp | 139 --------- include/SFML/System/Mutex.hpp | 148 --------- include/SFML/System/Thread.hpp | 282 ------------------ include/SFML/System/Thread.inl | 90 ------ include/SFML/System/ThreadLocal.hpp | 103 ------- include/SFML/System/ThreadLocalPtr.hpp | 158 ---------- include/SFML/System/ThreadLocalPtr.inl | 77 ----- src/SFML/Audio/AlResource.cpp | 9 +- src/SFML/Audio/Music.cpp | 8 +- src/SFML/Audio/SoundRecorder.cpp | 34 ++- src/SFML/Audio/SoundStream.cpp | 76 +++-- src/SFML/Graphics/RenderTarget.cpp | 13 +- src/SFML/Graphics/RenderTextureImplFBO.cpp | 19 +- src/SFML/Graphics/Shader.cpp | 9 +- src/SFML/Graphics/Texture.cpp | 11 +- src/SFML/Graphics/VertexBuffer.cpp | 7 +- src/SFML/Main/MainAndroid.cpp | 29 +- src/SFML/System/Android/Activity.hpp | 4 +- src/SFML/System/Android/ResourceStream.cpp | 4 +- src/SFML/System/CMakeLists.txt | 24 +- src/SFML/System/Lock.cpp | 48 --- src/SFML/System/Mutex.cpp | 66 ---- src/SFML/System/Thread.cpp | 86 ------ src/SFML/System/ThreadLocal.cpp | 67 ----- src/SFML/System/Unix/MutexImpl.cpp | 69 ----- src/SFML/System/Unix/MutexImpl.hpp | 83 ------ src/SFML/System/Unix/ThreadImpl.cpp | 94 ------ src/SFML/System/Unix/ThreadImpl.hpp | 93 ------ src/SFML/System/Unix/ThreadLocalImpl.cpp | 65 ---- src/SFML/System/Unix/ThreadLocalImpl.hpp | 87 ------ src/SFML/System/Win32/ClockImpl.cpp | 7 +- src/SFML/System/Win32/MutexImpl.cpp | 64 ---- src/SFML/System/Win32/MutexImpl.hpp | 83 ------ src/SFML/System/Win32/ThreadImpl.cpp | 93 ------ src/SFML/System/Win32/ThreadImpl.hpp | 109 ------- src/SFML/System/Win32/ThreadLocalImpl.cpp | 64 ---- src/SFML/System/Win32/ThreadLocalImpl.hpp | 87 ------ src/SFML/Window/Android/InputImpl.cpp | 20 +- src/SFML/Window/Android/VideoModeImpl.cpp | 4 +- src/SFML/Window/Android/WindowImplAndroid.cpp | 14 +- src/SFML/Window/Context.cpp | 3 +- src/SFML/Window/EglContext.cpp | 7 +- src/SFML/Window/GlContext.cpp | 45 ++- src/SFML/Window/Unix/Display.cpp | 15 +- src/SFML/Window/Unix/GlxContext.cpp | 11 +- src/SFML/Window/Unix/WindowImplX11.cpp | 15 +- src/SFML/Window/Win32/WglContext.cpp | 14 +- 54 files changed, 281 insertions(+), 2508 deletions(-) delete mode 100644 include/SFML/System/Lock.hpp delete mode 100644 include/SFML/System/Mutex.hpp delete mode 100644 include/SFML/System/Thread.hpp delete mode 100644 include/SFML/System/Thread.inl delete mode 100644 include/SFML/System/ThreadLocal.hpp delete mode 100644 include/SFML/System/ThreadLocalPtr.hpp delete mode 100644 include/SFML/System/ThreadLocalPtr.inl delete mode 100644 src/SFML/System/Mutex.cpp delete mode 100644 src/SFML/System/Thread.cpp delete mode 100644 src/SFML/System/ThreadLocal.cpp delete mode 100644 src/SFML/System/Unix/MutexImpl.cpp delete mode 100644 src/SFML/System/Unix/MutexImpl.hpp delete mode 100644 src/SFML/System/Unix/ThreadImpl.cpp delete mode 100644 src/SFML/System/Unix/ThreadImpl.hpp delete mode 100644 src/SFML/System/Unix/ThreadLocalImpl.cpp delete mode 100644 src/SFML/System/Unix/ThreadLocalImpl.hpp delete mode 100644 src/SFML/System/Win32/MutexImpl.cpp delete mode 100644 src/SFML/System/Win32/MutexImpl.hpp delete mode 100644 src/SFML/System/Win32/ThreadImpl.cpp delete mode 100644 src/SFML/System/Win32/ThreadImpl.hpp delete mode 100644 src/SFML/System/Win32/ThreadLocalImpl.cpp delete mode 100644 src/SFML/System/Win32/ThreadLocalImpl.hpp diff --git a/examples/island/CMakeLists.txt b/examples/island/CMakeLists.txt index 71a865d2a..4b2f3875c 100644 --- a/examples/island/CMakeLists.txt +++ b/examples/island/CMakeLists.txt @@ -11,4 +11,9 @@ sfml_add_example(island GUI_APP RESOURCES_DIR resources) # external dependency headers -target_include_directories(island SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/examples/island) \ No newline at end of file +target_include_directories(island SYSTEM PRIVATE ${PROJECT_SOURCE_DIR}/examples/island) + +# link against pthread +if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX) + target_link_libraries(island PRIVATE pthread) +endif() diff --git a/examples/island/Island.cpp b/examples/island/Island.cpp index 01f2510eb..e37b079b6 100644 --- a/examples/island/Island.cpp +++ b/examples/island/Island.cpp @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include @@ -39,11 +41,11 @@ namespace }; std::deque workQueue; - std::vector threads; + std::vector threads; int pendingWorkCount = 0; bool workPending = true; bool bufferUploadPending = false; - sf::Mutex workQueueMutex; + std::recursive_mutex workQueueMutex; struct Setting { @@ -136,8 +138,7 @@ int main() // Start up our thread pool for (unsigned int i = 0; i < threadCount; i++) { - threads.push_back(new sf::Thread(threadFunction)); - threads.back()->launch(); + threads.emplace_back(threadFunction); } // Create our VertexBuffer with enough space to hold all the terrain geometry @@ -216,7 +217,7 @@ int main() if (prerequisitesSupported) { { - sf::Lock lock(workQueueMutex); + std::scoped_lock lock(workQueueMutex); // Don't bother updating/drawing the VertexBuffer while terrain is being regenerated if (!pendingWorkCount) @@ -258,14 +259,13 @@ int main() // Shut down our thread pool { - sf::Lock lock(workQueueMutex); + std::scoped_lock lock(workQueueMutex); workPending = false; } while (!threads.empty()) { - threads.back()->wait(); - delete threads.back(); + threads.back().join(); threads.pop_back(); } @@ -552,7 +552,7 @@ void threadFunction() // Check if there are new work items in the queue { - sf::Lock lock(workQueueMutex); + std::scoped_lock lock(workQueueMutex); if (!workPending) return; @@ -575,7 +575,7 @@ void threadFunction() processWorkItem(vertices, workItem); { - sf::Lock lock(workQueueMutex); + std::scoped_lock lock(workQueueMutex); --pendingWorkCount; } @@ -597,7 +597,7 @@ void generateTerrain(sf::Vertex* buffer) for (;;) { { - sf::Lock lock(workQueueMutex); + std::scoped_lock lock(workQueueMutex); if (workQueue.empty()) break; @@ -608,7 +608,7 @@ void generateTerrain(sf::Vertex* buffer) // Queue all the new work items { - sf::Lock lock(workQueueMutex); + std::scoped_lock lock(workQueueMutex); for (unsigned int i = 0; i < blockCount; i++) { diff --git a/examples/voip/Server.cpp b/examples/voip/Server.cpp index e4c9c95f4..32ca10302 100644 --- a/examples/voip/Server.cpp +++ b/examples/voip/Server.cpp @@ -8,6 +8,7 @@ #include #include #include +#include const sf::Uint8 serverAudioData = 1; @@ -84,7 +85,7 @@ private: // Copy samples into a local buffer to avoid synchronization problems // (don't forget that we run in two separate threads) { - sf::Lock lock(m_mutex); + std::scoped_lock lock(m_mutex); m_tempBuffer.assign(m_samples.begin() + static_cast::difference_type>(m_offset), m_samples.end()); } @@ -132,7 +133,7 @@ private: // Don't forget that the other thread can access the sample array at any time // (so we protect any operation on it with the mutex) { - sf::Lock lock(m_mutex); + std::scoped_lock lock(m_mutex); std::size_t oldSize = m_samples.size(); m_samples.resize(oldSize + sampleCount); std::memcpy(&(m_samples[oldSize]), static_cast(packet.getData()) + 1, sampleCount * sizeof(sf::Int16)); @@ -158,7 +159,7 @@ private: //////////////////////////////////////////////////////////// sf::TcpListener m_listener; sf::TcpSocket m_client; - sf::Mutex m_mutex; + std::recursive_mutex m_mutex; std::vector m_samples; std::vector m_tempBuffer; std::size_t m_offset; diff --git a/include/SFML/Audio/Music.hpp b/include/SFML/Audio/Music.hpp index b1bcbb29e..fb3ab7a32 100644 --- a/include/SFML/Audio/Music.hpp +++ b/include/SFML/Audio/Music.hpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -276,10 +275,10 @@ private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - InputSoundFile m_file; //!< The streamed music file - std::vector m_samples; //!< Temporary buffer of samples - Mutex m_mutex; //!< Mutex protecting the data - Span m_loopSpan; //!< Loop Range Specifier + InputSoundFile m_file; //!< The streamed music file + std::vector m_samples; //!< Temporary buffer of samples + std::recursive_mutex m_mutex; //!< Mutex protecting the data + Span m_loopSpan; //!< Loop Range Specifier }; } // namespace sf diff --git a/include/SFML/Audio/SoundRecorder.hpp b/include/SFML/Audio/SoundRecorder.hpp index 5a15e60e6..1d7e39115 100644 --- a/include/SFML/Audio/SoundRecorder.hpp +++ b/include/SFML/Audio/SoundRecorder.hpp @@ -30,10 +30,10 @@ //////////////////////////////////////////////////////////// #include #include -#include #include #include #include +#include namespace sf @@ -282,16 +282,34 @@ private: //////////////////////////////////////////////////////////// void cleanup(); + //////////////////////////////////////////////////////////// + /// \brief Launch a new capture thread running 'record' + /// + /// This function is called when the capture is started or + /// when the device is changed. + /// + //////////////////////////////////////////////////////////// + void launchCapturingThread(); + + //////////////////////////////////////////////////////////// + /// \brief Stop capturing and wait for 'm_thread' to join + /// + /// This function is called when the capture is stopped or + /// when the device is changed. + /// + //////////////////////////////////////////////////////////// + void awaitCapturingThread(); + //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - Thread m_thread; //!< Thread running the background recording task - std::vector m_samples; //!< Buffer to store captured samples - unsigned int m_sampleRate; //!< Sample rate - Time m_processingInterval; //!< Time period between calls to onProcessSamples - bool m_isCapturing; //!< Capturing state - std::string m_deviceName; //!< Name of the audio capture device - unsigned int m_channelCount; //!< Number of recording channels + std::thread m_thread; //!< Thread running the background recording task + std::vector m_samples; //!< Buffer to store captured samples + unsigned int m_sampleRate; //!< Sample rate + Time m_processingInterval; //!< Time period between calls to onProcessSamples + bool m_isCapturing; //!< Capturing state + std::string m_deviceName; //!< Name of the audio capture device + unsigned int m_channelCount; //!< Number of recording channels }; } // namespace sf diff --git a/include/SFML/Audio/SoundStream.hpp b/include/SFML/Audio/SoundStream.hpp index f39cf3fd3..be4c9fb2a 100644 --- a/include/SFML/Audio/SoundStream.hpp +++ b/include/SFML/Audio/SoundStream.hpp @@ -30,10 +30,10 @@ //////////////////////////////////////////////////////////// #include #include -#include #include -#include #include +#include +#include namespace sf @@ -311,6 +311,24 @@ private: //////////////////////////////////////////////////////////// void clearQueue(); + //////////////////////////////////////////////////////////// + /// \brief Launch a new stream thread running 'streamData' + /// + /// This function is called when the stream is played or + /// when the playing offset is changed. + /// + //////////////////////////////////////////////////////////// + void launchStreamingThread(Status threadStartState); + + //////////////////////////////////////////////////////////// + /// \brief Stop streaming and wait for 'm_thread' to join + /// + /// This function is called when the playback is stopped or + /// when the sound stream is destroyed. + /// + //////////////////////////////////////////////////////////// + void awaitStreamingThread(); + enum { BufferCount = 3, //!< Number of audio buffers used by the streaming loop @@ -320,18 +338,18 @@ private: //////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - Thread m_thread; //!< Thread running the background tasks - mutable Mutex m_threadMutex; //!< Thread mutex - Status m_threadStartState; //!< State the thread starts in (Playing, Paused, Stopped) - bool m_isStreaming; //!< Streaming state (true = playing, false = stopped) - unsigned int m_buffers[BufferCount]; //!< Sound buffers used to store temporary audio data - unsigned int m_channelCount; //!< Number of channels (1 = mono, 2 = stereo, ...) - unsigned int m_sampleRate; //!< Frequency (samples / second) - Int32 m_format; //!< Format of the internal sound buffers - bool m_loop; //!< Loop flag (true to loop, false to play once) - Uint64 m_samplesProcessed; //!< Number of samples processed since beginning of the stream - Int64 m_bufferSeeks[BufferCount]; //!< If buffer is an "end buffer", holds next seek position, else NoLoop. For play offset calculation. - Time m_processingInterval; //!< Interval for checking and filling the internal sound buffers. + std::thread m_thread; //!< Thread running the background tasks + mutable std::recursive_mutex m_threadMutex; //!< Thread mutex + Status m_threadStartState; //!< State the thread starts in (Playing, Paused, Stopped) + bool m_isStreaming; //!< Streaming state (true = playing, false = stopped) + unsigned int m_buffers[BufferCount]; //!< Sound buffers used to store temporary audio data + unsigned int m_channelCount; //!< Number of channels (1 = mono, 2 = stereo, ...) + unsigned int m_sampleRate; //!< Frequency (samples / second) + Int32 m_format; //!< Format of the internal sound buffers + bool m_loop; //!< Loop flag (true to loop, false to play once) + Uint64 m_samplesProcessed; //!< Number of samples processed since beginning of the stream + Int64 m_bufferSeeks[BufferCount]; //!< If buffer is an "end buffer", holds next seek position, else NoLoop. For play offset calculation. + Time m_processingInterval; //!< Interval for checking and filling the internal sound buffers. }; } // namespace sf diff --git a/include/SFML/System.hpp b/include/SFML/System.hpp index f7058c052..8c30726af 100644 --- a/include/SFML/System.hpp +++ b/include/SFML/System.hpp @@ -34,15 +34,10 @@ #include #include #include -#include #include -#include #include #include #include -#include -#include -#include #include #include #include diff --git a/include/SFML/System/Lock.hpp b/include/SFML/System/Lock.hpp deleted file mode 100644 index 453aebd8a..000000000 --- a/include/SFML/System/Lock.hpp +++ /dev/null @@ -1,139 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_LOCK_HPP -#define SFML_LOCK_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -class Mutex; - -//////////////////////////////////////////////////////////// -/// \brief Automatic wrapper for locking and unlocking mutexes -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API Lock : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Construct the lock with a target mutex - /// - /// The mutex passed to sf::Lock is automatically locked. - /// - /// \param mutex Mutex to lock - /// - //////////////////////////////////////////////////////////// - explicit Lock(Mutex& mutex); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// The destructor of sf::Lock automatically unlocks its mutex. - /// - //////////////////////////////////////////////////////////// - ~Lock(); - -private: - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - Mutex& m_mutex; //!< Mutex to lock / unlock -}; - -} // namespace sf - - -#endif // SFML_LOCK_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Lock -/// \ingroup system -/// -/// sf::Lock is a RAII wrapper for sf::Mutex. By unlocking -/// it in its destructor, it ensures that the mutex will -/// always be released when the current scope (most likely -/// a function) ends. -/// This is even more important when an exception or an early -/// return statement can interrupt the execution flow of the -/// function. -/// -/// For maximum robustness, sf::Lock should always be used -/// to lock/unlock a mutex. -/// -/// Usage example: -/// \code -/// sf::Mutex mutex; -/// -/// void function() -/// { -/// sf::Lock lock(mutex); // mutex is now locked -/// -/// functionThatMayThrowAnException(); // mutex is unlocked if this function throws -/// -/// if (someCondition) -/// return; // mutex is unlocked -/// -/// } // mutex is unlocked -/// \endcode -/// -/// Because the mutex is not explicitly unlocked in the code, -/// it may remain locked longer than needed. If the region -/// of the code that needs to be protected by the mutex is -/// not the entire function, a good practice is to create a -/// smaller, inner scope so that the lock is limited to this -/// part of the code. -/// -/// \code -/// sf::Mutex mutex; -/// -/// void function() -/// { -/// { -/// sf::Lock lock(mutex); -/// codeThatRequiresProtection(); -/// -/// } // mutex is unlocked here -/// -/// codeThatDoesntCareAboutTheMutex(); -/// } -/// \endcode -/// -/// Having a mutex locked longer than required is a bad practice -/// which can lead to bad performances. Don't forget that when -/// a mutex is locked, other threads may be waiting doing nothing -/// until it is released. -/// -/// \see sf::Mutex -/// -//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Mutex.hpp b/include/SFML/System/Mutex.hpp deleted file mode 100644 index d07846f65..000000000 --- a/include/SFML/System/Mutex.hpp +++ /dev/null @@ -1,148 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_MUTEX_HPP -#define SFML_MUTEX_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ - class MutexImpl; -} - -//////////////////////////////////////////////////////////// -/// \brief Blocks concurrent access to shared resources -/// from multiple threads -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API Mutex : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - Mutex(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~Mutex(); - - //////////////////////////////////////////////////////////// - /// \brief Lock the mutex - /// - /// If the mutex is already locked in another thread, - /// this call will block the execution until the mutex - /// is released. - /// - /// \see unlock - /// - //////////////////////////////////////////////////////////// - void lock(); - - //////////////////////////////////////////////////////////// - /// \brief Unlock the mutex - /// - /// \see lock - /// - //////////////////////////////////////////////////////////// - void unlock(); - -private: - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::MutexImpl* m_mutexImpl; //!< OS-specific implementation -}; - -} // namespace sf - - -#endif // SFML_MUTEX_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Mutex -/// \ingroup system -/// -/// Mutex stands for "MUTual EXclusion". A mutex is a -/// synchronization object, used when multiple threads are involved. -/// -/// When you want to protect a part of the code from being accessed -/// simultaneously by multiple threads, you typically use a -/// mutex. When a thread is locked by a mutex, any other thread -/// trying to lock it will be blocked until the mutex is released -/// by the thread that locked it. This way, you can allow only -/// one thread at a time to access a critical region of your code. -/// -/// Usage example: -/// \code -/// Database database; // this is a critical resource that needs some protection -/// sf::Mutex mutex; -/// -/// void thread1() -/// { -/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread2 -/// database.write(...); -/// mutex.unlock(); // if thread2 was waiting, it will now be unblocked -/// } -/// -/// void thread2() -/// { -/// mutex.lock(); // this call will block the thread if the mutex is already locked by thread1 -/// database.write(...); -/// mutex.unlock(); // if thread1 was waiting, it will now be unblocked -/// } -/// \endcode -/// -/// Be very careful with mutexes. A bad usage can lead to bad problems, -/// like deadlocks (two threads are waiting for each other and the -/// application is globally stuck). -/// -/// To make the usage of mutexes more robust, particularly in -/// environments where exceptions can be thrown, you should -/// use the helper class sf::Lock to lock/unlock mutexes. -/// -/// SFML mutexes are recursive, which means that you can lock -/// a mutex multiple times in the same thread without creating -/// a deadlock. In this case, the first call to lock() behaves -/// as usual, and the following ones have no effect. -/// However, you must call unlock() exactly as many times as you -/// called lock(). If you don't, the mutex won't be released. -/// -/// \see sf::Lock -/// -//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Thread.hpp b/include/SFML/System/Thread.hpp deleted file mode 100644 index 905d3f7be..000000000 --- a/include/SFML/System/Thread.hpp +++ /dev/null @@ -1,282 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREAD_HPP -#define SFML_THREAD_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - class ThreadImpl; - struct ThreadFunc; -} - -//////////////////////////////////////////////////////////// -/// \brief Utility class to manipulate threads -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API Thread : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Construct the thread from a functor with no argument - /// - /// This constructor works for function objects, as well - /// as free functions. - /// - /// Use this constructor for this kind of function: - /// \code - /// void function(); - /// - /// // --- or ---- - /// - /// struct Functor - /// { - /// void operator()(); - /// }; - /// \endcode - /// Note: this does *not* run the thread, use launch(). - /// - /// \param function Functor or free function to use as the entry point of the thread - /// - //////////////////////////////////////////////////////////// - template - Thread(F function); - - //////////////////////////////////////////////////////////// - /// \brief Construct the thread from a functor with an argument - /// - /// This constructor works for function objects, as well - /// as free functions. - /// It is a template, which means that the argument can - /// have any type (int, std::string, void*, Toto, ...). - /// - /// Use this constructor for this kind of function: - /// \code - /// void function(int arg); - /// - /// // --- or ---- - /// - /// struct Functor - /// { - /// void operator()(std::string arg); - /// }; - /// \endcode - /// Note: this does *not* run the thread, use launch(). - /// - /// \param function Functor or free function to use as the entry point of the thread - /// \param argument argument to forward to the function - /// - //////////////////////////////////////////////////////////// - template - Thread(F function, A argument); - - //////////////////////////////////////////////////////////// - /// \brief Construct the thread from a member function and an object - /// - /// This constructor is a template, which means that you can - /// use it with any class. - /// Use this constructor for this kind of function: - /// \code - /// class MyClass - /// { - /// public: - /// - /// void function(); - /// }; - /// \endcode - /// Note: this does *not* run the thread, use launch(). - /// - /// \param function Entry point of the thread - /// \param object Pointer to the object to use - /// - //////////////////////////////////////////////////////////// - template - Thread(void(C::*function)(), C* object); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - /// This destructor calls wait(), so that the internal thread - /// cannot survive after its sf::Thread instance is destroyed. - /// - //////////////////////////////////////////////////////////// - ~Thread(); - - //////////////////////////////////////////////////////////// - /// \brief Run the thread - /// - /// This function starts the entry point passed to the - /// thread's constructor, and returns immediately. - /// After this function returns, the thread's function is - /// running in parallel to the calling code. - /// - //////////////////////////////////////////////////////////// - void launch(); - - //////////////////////////////////////////////////////////// - /// \brief Wait until the thread finishes - /// - /// This function will block the execution until the - /// thread's function ends. - /// Warning: if the thread function never ends, the calling - /// thread will block forever. - /// If this function is called from its owner thread, it - /// returns without doing anything. - /// - //////////////////////////////////////////////////////////// - void wait(); - - //////////////////////////////////////////////////////////// - /// \brief Terminate the thread - /// - /// This function immediately stops the thread, without waiting - /// for its function to finish. - /// Terminating a thread with this function is not safe, - /// and can lead to local variables not being destroyed - /// on some operating systems. You should rather try to make - /// the thread function terminate by itself. - /// - //////////////////////////////////////////////////////////// - void terminate(); - -private: - - friend class priv::ThreadImpl; - - //////////////////////////////////////////////////////////// - /// \brief Internal entry point of the thread - /// - /// This function is called by the thread implementation. - /// - //////////////////////////////////////////////////////////// - void run(); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::ThreadImpl* m_impl; //!< OS-specific implementation of the thread - priv::ThreadFunc* m_entryPoint; //!< Abstraction of the function to run -}; - -#include - -} // namespace sf - -#endif // SFML_THREAD_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::Thread -/// \ingroup system -/// -/// Threads provide a way to run multiple parts of the code -/// in parallel. When you launch a new thread, the execution -/// is split and both the new thread and the caller run -/// in parallel. -/// -/// To use a sf::Thread, you construct it directly with the -/// function to execute as the entry point of the thread. -/// sf::Thread has multiple template constructors, which means -/// that you can use several types of entry points: -/// \li non-member functions with no argument -/// \li non-member functions with one argument of any type -/// \li functors with no argument (this one is particularly useful for compatibility with boost/std::%bind) -/// \li functors with one argument of any type -/// \li member functions from any class with no argument -/// -/// The function argument, if any, is copied in the sf::Thread -/// instance, as well as the functor (if the corresponding -/// constructor is used). Class instances, however, are passed -/// by pointer so you must make sure that the object won't be -/// destroyed while the thread is still using it. -/// -/// The thread ends when its function is terminated. If the -/// owner sf::Thread instance is destroyed before the -/// thread is finished, the destructor will wait (see wait()) -/// -/// Usage examples: -/// \code -/// // example 1: non member function with one argument -/// -/// void threadFunc(int argument) -/// { -/// ... -/// } -/// -/// sf::Thread thread(&threadFunc, 5); -/// thread.launch(); // start the thread (internally calls threadFunc(5)) -/// \endcode -/// -/// \code -/// // example 2: member function -/// -/// class Task -/// { -/// public: -/// void run() -/// { -/// ... -/// } -/// }; -/// -/// Task task; -/// sf::Thread thread(&Task::run, &task); -/// thread.launch(); // start the thread (internally calls task.run()) -/// \endcode -/// -/// \code -/// // example 3: functor -/// -/// struct Task -/// { -/// void operator()() -/// { -/// ... -/// } -/// }; -/// -/// sf::Thread thread(Task()); -/// thread.launch(); // start the thread (internally calls operator() on the Task instance) -/// \endcode -/// -/// Creating parallel threads of execution can be dangerous: -/// all threads inside the same process share the same memory space, -/// which means that you may end up accessing the same variable -/// from multiple threads at the same time. To prevent this -/// kind of situations, you can use mutexes (see sf::Mutex). -/// -/// \see sf::Mutex -/// -//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/Thread.inl b/include/SFML/System/Thread.inl deleted file mode 100644 index b5a54ad10..000000000 --- a/include/SFML/System/Thread.inl +++ /dev/null @@ -1,90 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -namespace priv -{ -// Base class for abstract thread functions -struct ThreadFunc -{ - virtual ~ThreadFunc() {} - virtual void run() = 0; -}; - -// Specialization using a functor (including free functions) with no argument -template -struct ThreadFunctor : ThreadFunc -{ - ThreadFunctor(T functor) : m_functor(functor) {} - void run() override {m_functor();} - T m_functor; -}; - -// Specialization using a functor (including free functions) with one argument -template -struct ThreadFunctorWithArg : ThreadFunc -{ - ThreadFunctorWithArg(F function, A arg) : m_function(function), m_arg(arg) {} - void run() override {m_function(m_arg);} - F m_function; - A m_arg; -}; - -// Specialization using a member function -template -struct ThreadMemberFunc : ThreadFunc -{ - ThreadMemberFunc(void(C::*function)(), C* object) : m_function(function), m_object(object) {} - void run() override {(m_object->*m_function)();} - void(C::*m_function)(); - C* m_object; -}; - -} // namespace priv - - -//////////////////////////////////////////////////////////// -template -Thread::Thread(F functor) : -m_impl (nullptr), -m_entryPoint(new priv::ThreadFunctor(functor)) -{ -} - - -//////////////////////////////////////////////////////////// -template -Thread::Thread(F function, A argument) : -m_impl (nullptr), -m_entryPoint(new priv::ThreadFunctorWithArg(function, argument)) -{ -} - - -//////////////////////////////////////////////////////////// -template -Thread::Thread(void(C::*function)(), C* object) : -m_impl (nullptr), -m_entryPoint(new priv::ThreadMemberFunc(function, object)) -{ -} diff --git a/include/SFML/System/ThreadLocal.hpp b/include/SFML/System/ThreadLocal.hpp deleted file mode 100644 index 6bed2c7ff..000000000 --- a/include/SFML/System/ThreadLocal.hpp +++ /dev/null @@ -1,103 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADLOCAL_HPP -#define SFML_THREADLOCAL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -namespace priv -{ - class ThreadLocalImpl; -} - -//////////////////////////////////////////////////////////// -/// \brief Defines variables with thread-local storage -/// -//////////////////////////////////////////////////////////// -class SFML_SYSTEM_API ThreadLocal : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// \param value Optional value to initialize the variable - /// - //////////////////////////////////////////////////////////// - ThreadLocal(void* value = nullptr); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~ThreadLocal(); - - //////////////////////////////////////////////////////////// - /// \brief Set the thread-specific value of the variable - /// - /// \param value Value of the variable for the current thread - /// - //////////////////////////////////////////////////////////// - void setValue(void* value); - - //////////////////////////////////////////////////////////// - /// \brief Retrieve the thread-specific value of the variable - /// - /// \return Value of the variable for the current thread - /// - //////////////////////////////////////////////////////////// - void* getValue() const; - -private: - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - priv::ThreadLocalImpl* m_impl; //!< Pointer to the OS specific implementation -}; - -} // namespace sf - - -#endif // SFML_THREADLOCAL_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::ThreadLocal -/// \ingroup system -/// -/// This class manipulates void* parameters and thus is not -/// appropriate for strongly-typed variables. You should rather -/// use the sf::ThreadLocalPtr template class. -/// -//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/ThreadLocalPtr.hpp b/include/SFML/System/ThreadLocalPtr.hpp deleted file mode 100644 index af864ffea..000000000 --- a/include/SFML/System/ThreadLocalPtr.hpp +++ /dev/null @@ -1,158 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADLOCALPTR_HPP -#define SFML_THREADLOCALPTR_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -/// \brief Pointer to a thread-local variable -/// -//////////////////////////////////////////////////////////// -template -class ThreadLocalPtr : private ThreadLocal -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - /// \param value Optional value to initialize the variable - /// - //////////////////////////////////////////////////////////// - ThreadLocalPtr(T* value = nullptr); - - //////////////////////////////////////////////////////////// - /// \brief Overload of unary operator * - /// - /// Like raw pointers, applying the * operator returns a - /// reference to the pointed-to object. - /// - /// \return Reference to the thread-local variable - /// - //////////////////////////////////////////////////////////// - T& operator *() const; - - //////////////////////////////////////////////////////////// - /// \brief Overload of operator -> - /// - /// Similarly to raw pointers, applying the -> operator - /// returns the pointed-to object. - /// - /// \return Pointer to the thread-local variable - /// - //////////////////////////////////////////////////////////// - T* operator ->() const; - - //////////////////////////////////////////////////////////// - /// \brief Conversion operator to implicitly convert the - /// pointer to its raw pointer type (T*) - /// - /// \return Pointer to the actual object - /// - //////////////////////////////////////////////////////////// - operator T*() const; - - //////////////////////////////////////////////////////////// - /// \brief Assignment operator for a raw pointer parameter - /// - /// \param value Pointer to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - ThreadLocalPtr& operator =(T* value); - - //////////////////////////////////////////////////////////// - /// \brief Assignment operator for a ThreadLocalPtr parameter - /// - /// \param right ThreadLocalPtr to assign - /// - /// \return Reference to self - /// - //////////////////////////////////////////////////////////// - ThreadLocalPtr& operator =(const ThreadLocalPtr& right); -}; - -} // namespace sf - -#include - - -#endif // SFML_THREADLOCALPTR_HPP - - -//////////////////////////////////////////////////////////// -/// \class sf::ThreadLocalPtr -/// \ingroup system -/// -/// sf::ThreadLocalPtr is a type-safe wrapper for storing -/// pointers to thread-local variables. A thread-local -/// variable holds a different value for each different -/// thread, unlike normal variables that are shared. -/// -/// Its usage is completely transparent, so that it is similar -/// to manipulating the raw pointer directly (like any smart pointer). -/// -/// Usage example: -/// \code -/// MyClass object1; -/// MyClass object2; -/// sf::ThreadLocalPtr objectPtr; -/// -/// void thread1() -/// { -/// objectPtr = &object1; // doesn't impact thread2 -/// ... -/// } -/// -/// void thread2() -/// { -/// objectPtr = &object2; // doesn't impact thread1 -/// ... -/// } -/// -/// int main() -/// { -/// // Create and launch the two threads -/// sf::Thread t1(&thread1); -/// sf::Thread t2(&thread2); -/// t1.launch(); -/// t2.launch(); -/// -/// return 0; -/// } -/// \endcode -/// -/// ThreadLocalPtr is designed for internal use; however you -/// can use it if you feel like it fits well your implementation. -/// -//////////////////////////////////////////////////////////// diff --git a/include/SFML/System/ThreadLocalPtr.inl b/include/SFML/System/ThreadLocalPtr.inl deleted file mode 100644 index 61b6813eb..000000000 --- a/include/SFML/System/ThreadLocalPtr.inl +++ /dev/null @@ -1,77 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - - -namespace sf -{ -//////////////////////////////////////////////////////////// -template -ThreadLocalPtr::ThreadLocalPtr(T* value) : -ThreadLocal(value) -{ -} - - -//////////////////////////////////////////////////////////// -template -T& ThreadLocalPtr::operator *() const -{ - return *static_cast(getValue()); -} - - -//////////////////////////////////////////////////////////// -template -T* ThreadLocalPtr::operator ->() const -{ - return static_cast(getValue()); -} - - -//////////////////////////////////////////////////////////// -template -ThreadLocalPtr::operator T*() const -{ - return static_cast(getValue()); -} - - -//////////////////////////////////////////////////////////// -template -ThreadLocalPtr& ThreadLocalPtr::operator =(T* value) -{ - setValue(value); - return *this; -} - - -//////////////////////////////////////////////////////////// -template -ThreadLocalPtr& ThreadLocalPtr::operator =(const ThreadLocalPtr& right) -{ - setValue(right.getValue()); - return *this; -} - -} // namespace sf diff --git a/src/SFML/Audio/AlResource.cpp b/src/SFML/Audio/AlResource.cpp index e888a7a9c..973b1f0b2 100644 --- a/src/SFML/Audio/AlResource.cpp +++ b/src/SFML/Audio/AlResource.cpp @@ -27,15 +27,14 @@ //////////////////////////////////////////////////////////// #include #include -#include -#include +#include namespace { // OpenAL resources counter and its mutex unsigned int count = 0; - sf::Mutex mutex; + std::recursive_mutex mutex; // The audio device is instantiated on demand rather than at global startup, // which solves a lot of weird crashes and errors. @@ -50,7 +49,7 @@ namespace sf AlResource::AlResource() { // Protect from concurrent access - Lock lock(mutex); + std::scoped_lock lock(mutex); // If this is the very first resource, trigger the global device initialization if (count == 0) @@ -65,7 +64,7 @@ AlResource::AlResource() AlResource::~AlResource() { // Protect from concurrent access - Lock lock(mutex); + std::scoped_lock lock(mutex); // Decrement the resources counter count--; diff --git a/src/SFML/Audio/Music.cpp b/src/SFML/Audio/Music.cpp index c0b375909..03be3b5ae 100644 --- a/src/SFML/Audio/Music.cpp +++ b/src/SFML/Audio/Music.cpp @@ -27,10 +27,10 @@ //////////////////////////////////////////////////////////// #include #include -#include #include #include #include +#include namespace sf @@ -179,7 +179,7 @@ void Music::setLoopPoints(TimeSpan timePoints) //////////////////////////////////////////////////////////// bool Music::onGetData(SoundStream::Chunk& data) { - Lock lock(m_mutex); + std::scoped_lock lock(m_mutex); std::size_t toFill = m_samples.size(); Uint64 currentOffset = m_file.getSampleOffset(); @@ -204,7 +204,7 @@ bool Music::onGetData(SoundStream::Chunk& data) //////////////////////////////////////////////////////////// void Music::onSeek(Time timeOffset) { - Lock lock(m_mutex); + std::scoped_lock lock(m_mutex); m_file.seek(timeOffset); } @@ -213,7 +213,7 @@ void Music::onSeek(Time timeOffset) Int64 Music::onLoop() { // Called by underlying SoundStream so we can determine where to loop. - Lock lock(m_mutex); + std::scoped_lock lock(m_mutex); Uint64 currentOffset = m_file.getSampleOffset(); if (getLoop() && (m_loopSpan.length != 0) && (currentOffset == m_loopSpan.offset + m_loopSpan.length)) { diff --git a/src/SFML/Audio/SoundRecorder.cpp b/src/SFML/Audio/SoundRecorder.cpp index 2ca37c407..8126d5685 100644 --- a/src/SFML/Audio/SoundRecorder.cpp +++ b/src/SFML/Audio/SoundRecorder.cpp @@ -47,7 +47,7 @@ namespace sf { //////////////////////////////////////////////////////////// SoundRecorder::SoundRecorder() : -m_thread (&SoundRecorder::record, this), +m_thread (), m_sampleRate (0), m_processingInterval(milliseconds(100)), m_isCapturing (false), @@ -111,8 +111,7 @@ bool SoundRecorder::start(unsigned int sampleRate) alcCaptureStart(captureDevice); // Start the capture in a new thread, to avoid blocking the main thread - m_isCapturing = true; - m_thread.launch(); + launchCapturingThread(); return true; } @@ -127,8 +126,7 @@ void SoundRecorder::stop() // Stop the capturing thread if there is one if (m_isCapturing) { - m_isCapturing = false; - m_thread.wait(); + awaitCapturingThread(); // Notify derived class onStop(); @@ -181,8 +179,7 @@ bool SoundRecorder::setDevice(const std::string& name) if (m_isCapturing) { // Stop the capturing thread - m_isCapturing = false; - m_thread.wait(); + awaitCapturingThread(); // Determine the recording format ALCenum format = (m_channelCount == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16; @@ -202,8 +199,7 @@ bool SoundRecorder::setDevice(const std::string& name) alcCaptureStart(captureDevice); // Start the capture in a new thread, to avoid blocking the main thread - m_isCapturing = true; - m_thread.launch(); + launchCapturingThread(); } return true; @@ -327,4 +323,24 @@ void SoundRecorder::cleanup() captureDevice = nullptr; } + +//////////////////////////////////////////////////////////// +void SoundRecorder::launchCapturingThread() +{ + m_isCapturing = true; + + assert(!m_thread.joinable()); + m_thread = std::thread(&SoundRecorder::record, this); +} + + +//////////////////////////////////////////////////////////// +void SoundRecorder::awaitCapturingThread() +{ + m_isCapturing = false; + + if (m_thread.joinable()) + m_thread.join(); +} + } // namespace sf diff --git a/src/SFML/Audio/SoundStream.cpp b/src/SFML/Audio/SoundStream.cpp index be882a51f..bc5482284 100644 --- a/src/SFML/Audio/SoundStream.cpp +++ b/src/SFML/Audio/SoundStream.cpp @@ -30,7 +30,8 @@ #include #include #include -#include +#include +#include #ifdef _MSC_VER #pragma warning(disable: 4355) // 'this' used in base member initializer list @@ -41,7 +42,7 @@ namespace sf { //////////////////////////////////////////////////////////// SoundStream::SoundStream() : -m_thread (&SoundStream::streamData, this), +m_thread (), m_threadMutex (), m_threadStartState(Stopped), m_isStreaming (false), @@ -63,14 +64,8 @@ SoundStream::~SoundStream() { // Stop the sound if it was playing - // Request the thread to terminate - { - Lock lock(m_threadMutex); - m_isStreaming = false; - } - - // Wait for the thread to terminate - m_thread.wait(); + // Wait for the thread to join + awaitStreamingThread(); } @@ -109,7 +104,7 @@ void SoundStream::play() Status threadStartState = Stopped; { - Lock lock(m_threadMutex); + std::scoped_lock lock(m_threadMutex); isStreaming = m_isStreaming; threadStartState = m_threadStartState; @@ -119,7 +114,7 @@ void SoundStream::play() if (isStreaming && (threadStartState == Paused)) { // If the sound is paused, resume it - Lock lock(m_threadMutex); + std::scoped_lock lock(m_threadMutex); m_threadStartState = Playing; alCheck(alSourcePlay(m_source)); return; @@ -131,9 +126,7 @@ void SoundStream::play() } // Start updating the stream in a separate thread to avoid blocking the application - m_isStreaming = true; - m_threadStartState = Playing; - m_thread.launch(); + launchStreamingThread(Playing); } @@ -142,7 +135,7 @@ void SoundStream::pause() { // Handle pause() being called before the thread has started { - Lock lock(m_threadMutex); + std::scoped_lock lock(m_threadMutex); if (!m_isStreaming) return; @@ -157,14 +150,8 @@ void SoundStream::pause() //////////////////////////////////////////////////////////// void SoundStream::stop() { - // Request the thread to terminate - { - Lock lock(m_threadMutex); - m_isStreaming = false; - } - - // Wait for the thread to terminate - m_thread.wait(); + // Wait for the thread to join + awaitStreamingThread(); // Move to the beginning onSeek(Time::Zero); @@ -193,7 +180,7 @@ SoundStream::Status SoundStream::getStatus() const // To compensate for the lag between play() and alSourceplay() if (status == Stopped) { - Lock lock(m_threadMutex); + std::scoped_lock lock(m_threadMutex); if (m_isStreaming) status = m_threadStartState; @@ -221,9 +208,7 @@ void SoundStream::setPlayingOffset(Time timeOffset) if (oldStatus == Stopped) return; - m_isStreaming = true; - m_threadStartState = oldStatus; - m_thread.launch(); + launchStreamingThread(oldStatus); } @@ -277,7 +262,7 @@ void SoundStream::streamData() bool requestStop = false; { - Lock lock(m_threadMutex); + std::scoped_lock lock(m_threadMutex); // Check if the thread was launched Stopped if (m_threadStartState == Stopped) @@ -299,7 +284,7 @@ void SoundStream::streamData() alCheck(alSourcePlay(m_source)); { - Lock lock(m_threadMutex); + std::scoped_lock lock(m_threadMutex); // Check if the thread was launched Paused if (m_threadStartState == Paused) @@ -309,7 +294,7 @@ void SoundStream::streamData() for (;;) { { - Lock lock(m_threadMutex); + std::scoped_lock lock(m_threadMutex); if (!m_isStreaming) break; } @@ -325,7 +310,7 @@ void SoundStream::streamData() else { // End streaming - Lock lock(m_threadMutex); + std::scoped_lock lock(m_threadMutex); m_isStreaming = false; } } @@ -369,7 +354,7 @@ void SoundStream::streamData() << "and initialize() has been called correctly" << std::endl; // Abort streaming (exit main loop) - Lock lock(m_threadMutex); + std::scoped_lock lock(m_threadMutex); m_isStreaming = false; requestStop = true; break; @@ -498,4 +483,29 @@ void SoundStream::clearQueue() alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer)); } + +//////////////////////////////////////////////////////////// +void SoundStream::launchStreamingThread(Status threadStartState) +{ + m_isStreaming = true; + m_threadStartState = threadStartState; + + assert(!m_thread.joinable()); + m_thread = std::thread(&SoundStream::streamData, this); +} + + +//////////////////////////////////////////////////////////// +void SoundStream::awaitStreamingThread() +{ + // Request the thread to join + { + std::scoped_lock lock(m_threadMutex); + m_isStreaming = false; + } + + if (m_thread.joinable()) + m_thread.join(); +} + } // namespace sf diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp index 66062e980..29af0bdd5 100644 --- a/src/SFML/Graphics/RenderTarget.cpp +++ b/src/SFML/Graphics/RenderTarget.cpp @@ -33,13 +33,12 @@ #include #include #include -#include -#include #include -#include -#include #include +#include +#include #include +#include namespace @@ -48,13 +47,13 @@ namespace namespace RenderTargetImpl { // Mutex to protect ID generation and our context-RenderTarget-map - sf::Mutex mutex; + std::recursive_mutex mutex; // Unique identifier, used for identifying RenderTargets when // tracking the currently active RenderTarget within a given context sf::Uint64 getUniqueId() { - sf::Lock lock(mutex); + std::scoped_lock lock(mutex); static sf::Uint64 id = 1; // start at 1, zero is "no RenderTarget" @@ -402,7 +401,7 @@ bool RenderTarget::setActive(bool active) { // Mark this RenderTarget as active or no longer active in the tracking map { - sf::Lock lock(RenderTargetImpl::mutex); + std::scoped_lock lock(RenderTargetImpl::mutex); Uint64 contextId = Context::getActiveContextId(); diff --git a/src/SFML/Graphics/RenderTextureImplFBO.cpp b/src/SFML/Graphics/RenderTextureImplFBO.cpp index 281c7b4b4..3705519da 100644 --- a/src/SFML/Graphics/RenderTextureImplFBO.cpp +++ b/src/SFML/Graphics/RenderTextureImplFBO.cpp @@ -28,13 +28,12 @@ #include #include #include -#include -#include #include #include #include #include #include +#include namespace @@ -53,7 +52,7 @@ namespace std::set > staleFrameBuffers; // Mutex to protect both active and stale frame buffer sets - sf::Mutex mutex; + std::recursive_mutex mutex; // This function is called either when a RenderTextureImplFBO is // destroyed or via contextDestroyCallback when context destruction @@ -81,7 +80,7 @@ namespace // Callback that is called every time a context is destroyed void contextDestroyCallback(void* /*arg*/) { - sf::Lock lock(mutex); + std::scoped_lock lock(mutex); sf::Uint64 contextId = sf::Context::getActiveContextId(); @@ -125,7 +124,7 @@ m_multisample (false), m_stencil (false), m_sRgb (false) { - Lock lock(mutex); + std::scoped_lock lock(mutex); // Register the context destruction callback registerContextDestroyCallback(contextDestroyCallback, nullptr); @@ -141,7 +140,7 @@ RenderTextureImplFBO::~RenderTextureImplFBO() { TransientContextLock contextLock; - Lock lock(mutex); + std::scoped_lock lock(mutex); // Remove the frame buffer mapping from the set of all active mappings frameBuffers.erase(&m_frameBuffers); @@ -445,7 +444,7 @@ bool RenderTextureImplFBO::createFrameBuffer() } { - Lock lock(mutex); + std::scoped_lock lock(mutex); // Insert the FBO into our map m_frameBuffers.emplace(Context::getActiveContextId(), frameBuffer); @@ -492,7 +491,7 @@ bool RenderTextureImplFBO::createFrameBuffer() } { - Lock lock(mutex); + std::scoped_lock lock(mutex); // Insert the FBO into our map m_multisampleFrameBuffers.emplace(Context::getActiveContextId(), multisampleFrameBuffer); @@ -543,7 +542,7 @@ bool RenderTextureImplFBO::activate(bool active) // If none is found, there is no FBO corresponding to the // currently active context so we will have to create a new FBO { - Lock lock(mutex); + std::scoped_lock lock(mutex); std::unordered_map::iterator it; @@ -597,7 +596,7 @@ void RenderTextureImplFBO::updateTexture(unsigned int) { Uint64 contextId = Context::getActiveContextId(); - Lock lock(mutex); + std::scoped_lock lock(mutex); auto frameBufferIt = m_frameBuffers.find(contextId); auto multisampleIt = m_multisampleFrameBuffers.find(contextId); diff --git a/src/SFML/Graphics/Shader.cpp b/src/SFML/Graphics/Shader.cpp index e54b72d6e..ddb06cb09 100644 --- a/src/SFML/Graphics/Shader.cpp +++ b/src/SFML/Graphics/Shader.cpp @@ -33,11 +33,10 @@ #include #include #include -#include -#include #include #include #include +#include #ifndef SFML_OPENGL_ES @@ -56,7 +55,7 @@ namespace { - sf::Mutex isAvailableMutex; + std::recursive_mutex isAvailableMutex; GLint checkMaxTextureUnits() { @@ -697,7 +696,7 @@ void Shader::bind(const Shader* shader) //////////////////////////////////////////////////////////// bool Shader::isAvailable() { - Lock lock(isAvailableMutex); + std::scoped_lock lock(isAvailableMutex); static bool checked = false; static bool available = false; @@ -725,7 +724,7 @@ bool Shader::isAvailable() //////////////////////////////////////////////////////////// bool Shader::isGeometryAvailable() { - Lock lock(isAvailableMutex); + std::scoped_lock lock(isAvailableMutex); static bool checked = false; static bool available = false; diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp index 7f9905370..e77e21ffd 100644 --- a/src/SFML/Graphics/Texture.cpp +++ b/src/SFML/Graphics/Texture.cpp @@ -31,12 +31,11 @@ #include #include #include -#include -#include #include #include #include #include +#include namespace @@ -44,14 +43,14 @@ namespace // A nested named namespace is used here to allow unity builds of SFML. namespace TextureImpl { - sf::Mutex idMutex; - sf::Mutex maximumSizeMutex; + std::recursive_mutex idMutex; + std::recursive_mutex maximumSizeMutex; // Thread-safe unique identifier generator, // is used for states cache (see RenderTarget) sf::Uint64 getUniqueId() { - sf::Lock lock(idMutex); + std::scoped_lock lock(idMutex); static sf::Uint64 id = 1; // start at 1, zero is "no texture" @@ -795,7 +794,7 @@ void Texture::bind(const Texture* texture, CoordinateType coordinateType) //////////////////////////////////////////////////////////// unsigned int Texture::getMaximumSize() { - Lock lock(TextureImpl::maximumSizeMutex); + std::scoped_lock lock(TextureImpl::maximumSizeMutex); static bool checked = false; static GLint size = 0; diff --git a/src/SFML/Graphics/VertexBuffer.cpp b/src/SFML/Graphics/VertexBuffer.cpp index 7b88ebf79..366177d6a 100644 --- a/src/SFML/Graphics/VertexBuffer.cpp +++ b/src/SFML/Graphics/VertexBuffer.cpp @@ -29,17 +29,16 @@ #include #include #include -#include -#include #include #include +#include namespace { // A nested named namespace is used here to allow unity builds of SFML. namespace VertexBufferImpl { - sf::Mutex isAvailableMutex; + std::recursive_mutex isAvailableMutex; GLenum usageToGlEnum(sf::VertexBuffer::Usage usage) { @@ -336,7 +335,7 @@ VertexBuffer::Usage VertexBuffer::getUsage() const //////////////////////////////////////////////////////////// bool VertexBuffer::isAvailable() { - Lock lock(VertexBufferImpl::isAvailableMutex); + std::scoped_lock lock(VertexBufferImpl::isAvailableMutex); static bool checked = false; static bool available = false; diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp index d5edb60eb..010fca855 100644 --- a/src/SFML/Main/MainAndroid.cpp +++ b/src/SFML/Main/MainAndroid.cpp @@ -40,13 +40,13 @@ #include #include -#include -#include #include #include #include #include #include +#include +#include #define SF_GLAD_EGL_IMPLEMENTATION #include @@ -93,7 +93,7 @@ ActivityStates* retrieveStates(ANativeActivity* activity) static void initializeMain(ActivityStates* states) { // Protect from concurrent access - Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); // Prepare and share the looper to be read later ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); @@ -117,7 +117,7 @@ static void initializeMain(ActivityStates* states) static void terminateMain(ActivityStates* states) { // Protect from concurrent access - Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); // The main thread has finished, we must explicitly ask the activity to finish states->mainOver = true; @@ -138,7 +138,7 @@ void* main(ActivityStates* states) terminateMain(states); { - Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); states->terminated = true; } @@ -255,7 +255,7 @@ static void onResume(ANativeActivity* activity) { // Retrieve our activity states from the activity instance sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); if (states->fullscreen) goToFullscreenMode(activity); @@ -273,7 +273,7 @@ static void onPause(ANativeActivity* activity) { // Retrieve our activity states from the activity instance sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); // Send an event to warn people the activity has been paused sf::Event event; @@ -298,7 +298,7 @@ static void onDestroy(ANativeActivity* activity) // Send an event to warn people the activity is being destroyed { - sf::Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); // If the main thread hasn't yet finished, send the event and wait for // it to finish. @@ -342,7 +342,7 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind (void) window; sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); // Update the activity states states->window = window; @@ -369,7 +369,7 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi (void) window; sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); // Update the activity states states->window = nullptr; @@ -414,7 +414,7 @@ static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) // Attach the input queue { - sf::Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); AInputQueue_attachLooper(queue, states->looper, 1, states->processEvent, nullptr); states->inputQueue = queue; @@ -430,7 +430,7 @@ static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) // Detach the input queue { - sf::Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); AInputQueue_detachLooper(queue); states->inputQueue = nullptr; @@ -455,7 +455,7 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) // Retrieve our activity states from the activity instance sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity); - sf::Lock lock(states->mutex); + std::scoped_lock lock(states->mutex); // Make sure the window still exists before we access the dimensions on it if (states->window != nullptr) { @@ -568,8 +568,7 @@ JNIEXPORT void ANativeActivity_onCreate(ANativeActivity* activity, void* savedSt sf::err().rdbuf(&states->logcat); // Launch the main thread - sf::Thread* thread = new sf::Thread(sf::priv::main, states); - thread->launch(); + std::thread(sf::priv::main, states).detach(); // Wait for the main thread to be initialized states->mutex.lock(); diff --git a/src/SFML/System/Android/Activity.hpp b/src/SFML/System/Android/Activity.hpp index 257f5c275..943b106f4 100644 --- a/src/SFML/System/Android/Activity.hpp +++ b/src/SFML/System/Android/Activity.hpp @@ -30,13 +30,13 @@ //////////////////////////////////////////////////////////// #include #include -#include #include #include #include #include #include #include +#include class SFML_SYSTEM_API LogcatStream : public std::streambuf { @@ -68,7 +68,7 @@ struct ActivityStates void* savedState; size_t savedStateSize; - Mutex mutex; + std::recursive_mutex mutex; void (*forwardEvent)(const Event& event); int (*processEvent)(int fd, int events, void* data); diff --git a/src/SFML/System/Android/ResourceStream.cpp b/src/SFML/System/Android/ResourceStream.cpp index 32f254a2a..9cf81e825 100644 --- a/src/SFML/System/Android/ResourceStream.cpp +++ b/src/SFML/System/Android/ResourceStream.cpp @@ -28,7 +28,7 @@ //////////////////////////////////////////////////////////// #include #include -#include +#include namespace sf @@ -41,7 +41,7 @@ ResourceStream::ResourceStream(const std::string& filename) : m_file (nullptr) { ActivityStates& states = getActivity(); - Lock lock(states.mutex); + std::scoped_lock lock(states.mutex); m_file = AAssetManager_open(states.activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN); } diff --git a/src/SFML/System/CMakeLists.txt b/src/SFML/System/CMakeLists.txt index 1206968be..de3aa0b2c 100644 --- a/src/SFML/System/CMakeLists.txt +++ b/src/SFML/System/CMakeLists.txt @@ -10,10 +10,6 @@ set(SRC ${INCROOT}/Err.hpp ${INCROOT}/Export.hpp ${INCROOT}/InputStream.hpp - ${SRCROOT}/Lock.cpp - ${INCROOT}/Lock.hpp - ${SRCROOT}/Mutex.cpp - ${INCROOT}/Mutex.hpp ${INCROOT}/NativeActivity.hpp ${INCROOT}/NonCopyable.hpp ${SRCROOT}/Sleep.cpp @@ -21,13 +17,6 @@ set(SRC ${SRCROOT}/String.cpp ${INCROOT}/String.hpp ${INCROOT}/String.inl - ${SRCROOT}/Thread.cpp - ${INCROOT}/Thread.hpp - ${INCROOT}/Thread.inl - ${SRCROOT}/ThreadLocal.cpp - ${INCROOT}/ThreadLocal.hpp - ${INCROOT}/ThreadLocalPtr.hpp - ${INCROOT}/ThreadLocalPtr.inl ${SRCROOT}/Time.cpp ${INCROOT}/Time.hpp ${INCROOT}/Utf.hpp @@ -48,28 +37,16 @@ if(SFML_OS_WINDOWS) set(PLATFORM_SRC ${SRCROOT}/Win32/ClockImpl.cpp ${SRCROOT}/Win32/ClockImpl.hpp - ${SRCROOT}/Win32/MutexImpl.cpp - ${SRCROOT}/Win32/MutexImpl.hpp ${SRCROOT}/Win32/SleepImpl.cpp ${SRCROOT}/Win32/SleepImpl.hpp - ${SRCROOT}/Win32/ThreadImpl.cpp - ${SRCROOT}/Win32/ThreadImpl.hpp - ${SRCROOT}/Win32/ThreadLocalImpl.cpp - ${SRCROOT}/Win32/ThreadLocalImpl.hpp ) source_group("windows" FILES ${PLATFORM_SRC}) else() set(PLATFORM_SRC ${SRCROOT}/Unix/ClockImpl.cpp ${SRCROOT}/Unix/ClockImpl.hpp - ${SRCROOT}/Unix/MutexImpl.cpp - ${SRCROOT}/Unix/MutexImpl.hpp ${SRCROOT}/Unix/SleepImpl.cpp ${SRCROOT}/Unix/SleepImpl.hpp - ${SRCROOT}/Unix/ThreadImpl.cpp - ${SRCROOT}/Unix/ThreadImpl.hpp - ${SRCROOT}/Unix/ThreadLocalImpl.cpp - ${SRCROOT}/Unix/ThreadLocalImpl.hpp ) if(SFML_OS_ANDROID) @@ -98,6 +75,7 @@ endif() if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX) target_link_libraries(sfml-system PRIVATE pthread) endif() + if(SFML_OS_LINUX) target_link_libraries(sfml-system PRIVATE rt) elseif(SFML_OS_WINDOWS) diff --git a/src/SFML/System/Lock.cpp b/src/SFML/System/Lock.cpp index b3f905c1e..e69de29bb 100644 --- a/src/SFML/System/Lock.cpp +++ b/src/SFML/System/Lock.cpp @@ -1,48 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Lock::Lock(Mutex& mutex) : -m_mutex(mutex) -{ - m_mutex.lock(); -} - - -//////////////////////////////////////////////////////////// -Lock::~Lock() -{ - m_mutex.unlock(); -} - -} // namespace sf diff --git a/src/SFML/System/Mutex.cpp b/src/SFML/System/Mutex.cpp deleted file mode 100644 index fb392f162..000000000 --- a/src/SFML/System/Mutex.cpp +++ /dev/null @@ -1,66 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#if defined(SFML_SYSTEM_WINDOWS) - #include -#else - #include -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Mutex::Mutex() -{ - m_mutexImpl = new priv::MutexImpl; -} - - -//////////////////////////////////////////////////////////// -Mutex::~Mutex() -{ - delete m_mutexImpl; -} - - -//////////////////////////////////////////////////////////// -void Mutex::lock() -{ - m_mutexImpl->lock(); -} - - -//////////////////////////////////////////////////////////// -void Mutex::unlock() -{ - m_mutexImpl->unlock(); -} - -} // namespace sf diff --git a/src/SFML/System/Thread.cpp b/src/SFML/System/Thread.cpp deleted file mode 100644 index cc966e68a..000000000 --- a/src/SFML/System/Thread.cpp +++ /dev/null @@ -1,86 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -#if defined(SFML_SYSTEM_WINDOWS) - #include -#else - #include -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -Thread::~Thread() -{ - wait(); - delete m_entryPoint; -} - - -//////////////////////////////////////////////////////////// -void Thread::launch() -{ - wait(); - m_impl = new priv::ThreadImpl(this); -} - - -//////////////////////////////////////////////////////////// -void Thread::wait() -{ - if (m_impl) - { - m_impl->wait(); - delete m_impl; - m_impl = nullptr; - } -} - - -//////////////////////////////////////////////////////////// -void Thread::terminate() -{ - if (m_impl) - { - m_impl->terminate(); - delete m_impl; - m_impl = nullptr; - } -} - - -//////////////////////////////////////////////////////////// -void Thread::run() -{ - m_entryPoint->run(); -} - -} // namespace sf diff --git a/src/SFML/System/ThreadLocal.cpp b/src/SFML/System/ThreadLocal.cpp deleted file mode 100644 index ec1ac6596..000000000 --- a/src/SFML/System/ThreadLocal.cpp +++ /dev/null @@ -1,67 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - -#if defined(SFML_SYSTEM_WINDOWS) - #include -#else - #include -#endif - - -namespace sf -{ -//////////////////////////////////////////////////////////// -ThreadLocal::ThreadLocal(void* value) -{ - m_impl = new priv::ThreadLocalImpl; - setValue(value); -} - - -//////////////////////////////////////////////////////////// -ThreadLocal::~ThreadLocal() -{ - delete m_impl; -} - - -//////////////////////////////////////////////////////////// -void ThreadLocal::setValue(void* value) -{ - m_impl->setValue(value); -} - - -//////////////////////////////////////////////////////////// -void* ThreadLocal::getValue() const -{ - return m_impl->getValue(); -} - -} // namespace sf diff --git a/src/SFML/System/Unix/MutexImpl.cpp b/src/SFML/System/Unix/MutexImpl.cpp deleted file mode 100644 index 448be0e39..000000000 --- a/src/SFML/System/Unix/MutexImpl.cpp +++ /dev/null @@ -1,69 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -MutexImpl::MutexImpl() -{ - // Make it recursive to follow the expected behavior - pthread_mutexattr_t attributes; - pthread_mutexattr_init(&attributes); - pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE); - - pthread_mutex_init(&m_mutex, &attributes); -} - - -//////////////////////////////////////////////////////////// -MutexImpl::~MutexImpl() -{ - pthread_mutex_destroy(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -void MutexImpl::lock() -{ - pthread_mutex_lock(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -void MutexImpl::unlock() -{ - pthread_mutex_unlock(&m_mutex); -} - -} // namespace priv - -} // namespace sf diff --git a/src/SFML/System/Unix/MutexImpl.hpp b/src/SFML/System/Unix/MutexImpl.hpp deleted file mode 100644 index 259ee0dbb..000000000 --- a/src/SFML/System/Unix/MutexImpl.hpp +++ /dev/null @@ -1,83 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_MUTEXIMPL_HPP -#define SFML_MUTEXIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Unix implementation of mutexes -//////////////////////////////////////////////////////////// -class MutexImpl : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - MutexImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~MutexImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Lock the mutex - /// - //////////////////////////////////////////////////////////// - void lock(); - - //////////////////////////////////////////////////////////// - /// \brief Unlock the mutex - /// - //////////////////////////////////////////////////////////// - void unlock(); - -private: - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - pthread_mutex_t m_mutex; ///< pthread handle of the mutex -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_MUTEXIMPL_HPP diff --git a/src/SFML/System/Unix/ThreadImpl.cpp b/src/SFML/System/Unix/ThreadImpl.cpp deleted file mode 100644 index 343d0d18a..000000000 --- a/src/SFML/System/Unix/ThreadImpl.cpp +++ /dev/null @@ -1,94 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ThreadImpl::ThreadImpl(Thread* owner) : -m_isActive(true) -{ - m_isActive = pthread_create(&m_thread, nullptr, &ThreadImpl::entryPoint, owner) == 0; - - if (!m_isActive) - std::cerr << "Failed to create thread" << std::endl; -} - - -//////////////////////////////////////////////////////////// -void ThreadImpl::wait() -{ - if (m_isActive) - { - assert(pthread_equal(pthread_self(), m_thread) == 0); // A thread cannot wait for itself! - pthread_join(m_thread, nullptr); - } -} - - -//////////////////////////////////////////////////////////// -void ThreadImpl::terminate() -{ - if (m_isActive) - { - #ifndef SFML_SYSTEM_ANDROID - pthread_cancel(m_thread); - #else - // See https://stackoverflow.com/questions/4610086/pthread-cancel-al - pthread_kill(m_thread, SIGUSR1); - #endif - } -} - - -//////////////////////////////////////////////////////////// -void* ThreadImpl::entryPoint(void* userData) -{ - // The Thread instance is stored in the user data - auto* owner = static_cast(userData); - - #ifndef SFML_SYSTEM_ANDROID - // Tell the thread to handle cancel requests immediately - pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, nullptr); - #endif - - // Forward to the owner - owner->run(); - - return nullptr; -} - -} // namespace priv - -} // namespace sf diff --git a/src/SFML/System/Unix/ThreadImpl.hpp b/src/SFML/System/Unix/ThreadImpl.hpp deleted file mode 100644 index 4f89ee874..000000000 --- a/src/SFML/System/Unix/ThreadImpl.hpp +++ /dev/null @@ -1,93 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADIMPL_HPP -#define SFML_THREADIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include - - -namespace sf -{ -class Thread; - -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Unix implementation of threads -//////////////////////////////////////////////////////////// -class ThreadImpl : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor, launch the thread - /// - /// \param owner The Thread instance to run - /// - //////////////////////////////////////////////////////////// - ThreadImpl(Thread* owner); - - //////////////////////////////////////////////////////////// - /// \brief Wait until the thread finishes - /// - //////////////////////////////////////////////////////////// - void wait(); - - //////////////////////////////////////////////////////////// - /// \brief Terminate the thread - /// - //////////////////////////////////////////////////////////// - void terminate(); - -private: - - //////////////////////////////////////////////////////////// - /// \brief Global entry point for all threads - /// - /// \param userData User-defined data (contains the Thread instance) - /// - /// \return Os specific error code - /// - //////////////////////////////////////////////////////////// - static void* entryPoint(void* userData); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - pthread_t m_thread; ///< pthread thread instance - bool m_isActive; ///< Thread state (active or inactive) -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_THREADIMPL_HPP diff --git a/src/SFML/System/Unix/ThreadLocalImpl.cpp b/src/SFML/System/Unix/ThreadLocalImpl.cpp deleted file mode 100644 index 53a228ec7..000000000 --- a/src/SFML/System/Unix/ThreadLocalImpl.cpp +++ /dev/null @@ -1,65 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ThreadLocalImpl::ThreadLocalImpl() : -m_key(0) -{ - pthread_key_create(&m_key, nullptr); -} - - -//////////////////////////////////////////////////////////// -ThreadLocalImpl::~ThreadLocalImpl() -{ - pthread_key_delete(m_key); -} - - -//////////////////////////////////////////////////////////// -void ThreadLocalImpl::setValue(void* value) -{ - pthread_setspecific(m_key, value); -} - - -//////////////////////////////////////////////////////////// -void* ThreadLocalImpl::getValue() const -{ - return pthread_getspecific(m_key); -} - -} // namespace priv - -} // namespace sf diff --git a/src/SFML/System/Unix/ThreadLocalImpl.hpp b/src/SFML/System/Unix/ThreadLocalImpl.hpp deleted file mode 100644 index c8bcc480e..000000000 --- a/src/SFML/System/Unix/ThreadLocalImpl.hpp +++ /dev/null @@ -1,87 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADLOCALIMPL_HPP -#define SFML_THREADLOCALIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Unix implementation of thread-local storage -//////////////////////////////////////////////////////////// -class ThreadLocalImpl : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor -- allocate the storage - /// - //////////////////////////////////////////////////////////// - ThreadLocalImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor -- free the storage - /// - //////////////////////////////////////////////////////////// - ~ThreadLocalImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Set the thread-specific value of the variable - /// - /// \param value Value of the variable for this thread - /// - //////////////////////////////////////////////////////////// - void setValue(void* value); - - //////////////////////////////////////////////////////////// - /// \brief Retrieve the thread-specific value of the variable - /// - /// \return Value of the variable for this thread - /// - //////////////////////////////////////////////////////////// - void* getValue() const; - -private: - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - pthread_key_t m_key; ///< Index of our thread-local storage slot -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_THREADLOCALIMPL_HPP diff --git a/src/SFML/System/Win32/ClockImpl.cpp b/src/SFML/System/Win32/ClockImpl.cpp index 3d28d7ea3..af136badf 100644 --- a/src/SFML/System/Win32/ClockImpl.cpp +++ b/src/SFML/System/Win32/ClockImpl.cpp @@ -26,8 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include -#include -#include +#include #include @@ -65,10 +64,10 @@ Time ClockImpl::getCurrentTime() if (oldWindows) { - static sf::Mutex oldWindowsMutex; + static std::recursive_mutex oldWindowsMutex; // Acquire a lock (CRITICAL_SECTION) to prevent travelling back in time - Lock lock(oldWindowsMutex); + std::scoped_lock lock(oldWindowsMutex); // Get the current time QueryPerformanceCounter(&time); diff --git a/src/SFML/System/Win32/MutexImpl.cpp b/src/SFML/System/Win32/MutexImpl.cpp deleted file mode 100644 index f345cb154..000000000 --- a/src/SFML/System/Win32/MutexImpl.cpp +++ /dev/null @@ -1,64 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -MutexImpl::MutexImpl() -{ - InitializeCriticalSection(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -MutexImpl::~MutexImpl() -{ - DeleteCriticalSection(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -void MutexImpl::lock() -{ - EnterCriticalSection(&m_mutex); -} - - -//////////////////////////////////////////////////////////// -void MutexImpl::unlock() -{ - LeaveCriticalSection(&m_mutex); -} - -} // namespace priv - -} // namespace sf diff --git a/src/SFML/System/Win32/MutexImpl.hpp b/src/SFML/System/Win32/MutexImpl.hpp deleted file mode 100644 index cf6cbd8bc..000000000 --- a/src/SFML/System/Win32/MutexImpl.hpp +++ /dev/null @@ -1,83 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_MUTEXIMPL_HPP -#define SFML_MUTEXIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Windows implementation of mutexes -//////////////////////////////////////////////////////////// -class MutexImpl : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor - /// - //////////////////////////////////////////////////////////// - MutexImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~MutexImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Lock the mutex - /// - //////////////////////////////////////////////////////////// - void lock(); - - //////////////////////////////////////////////////////////// - /// \brief Unlock the mutex - /// - //////////////////////////////////////////////////////////// - void unlock(); - -private: - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - CRITICAL_SECTION m_mutex; //!< Win32 handle of the mutex -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_MUTEXIMPL_HPP diff --git a/src/SFML/System/Win32/ThreadImpl.cpp b/src/SFML/System/Win32/ThreadImpl.cpp deleted file mode 100644 index aec029b83..000000000 --- a/src/SFML/System/Win32/ThreadImpl.cpp +++ /dev/null @@ -1,93 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include -#include -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ThreadImpl::ThreadImpl(Thread* owner) -{ - m_thread = reinterpret_cast(_beginthreadex(nullptr, 0, &ThreadImpl::entryPoint, owner, 0, &m_threadId)); - - if (!m_thread) - err() << "Failed to create thread" << std::endl; -} - - -//////////////////////////////////////////////////////////// -ThreadImpl::~ThreadImpl() -{ - if (m_thread) - CloseHandle(m_thread); -} - - -//////////////////////////////////////////////////////////// -void ThreadImpl::wait() -{ - if (m_thread) - { - assert(m_threadId != GetCurrentThreadId()); // A thread cannot wait for itself! - WaitForSingleObject(m_thread, INFINITE); - } -} - - -//////////////////////////////////////////////////////////// -void ThreadImpl::terminate() -{ - if (m_thread) - TerminateThread(m_thread, 0); -} - - -//////////////////////////////////////////////////////////// -unsigned int __stdcall ThreadImpl::entryPoint(void* userData) -{ - // The Thread instance is stored in the user data - auto* owner = static_cast(userData); - - // Forward to the owner - owner->run(); - - // Optional, but it is cleaner - _endthreadex(0); - - return 0; -} - -} // namespace priv - -} // namespace sf diff --git a/src/SFML/System/Win32/ThreadImpl.hpp b/src/SFML/System/Win32/ThreadImpl.hpp deleted file mode 100644 index cfabaab3d..000000000 --- a/src/SFML/System/Win32/ThreadImpl.hpp +++ /dev/null @@ -1,109 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADIMPL_HPP -#define SFML_THREADIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - -// Fix for unaligned stack with clang and GCC on Windows XP 32-bit -#if defined(SFML_SYSTEM_WINDOWS) && (defined(__clang__) || defined(__GNUC__)) - - #define ALIGN_STACK __attribute__((__force_align_arg_pointer__)) - -#else - - #define ALIGN_STACK - -#endif - - -namespace sf -{ -class Thread; - -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Windows implementation of threads -//////////////////////////////////////////////////////////// -class ThreadImpl : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor, launch the thread - /// - /// \param owner The Thread instance to run - /// - //////////////////////////////////////////////////////////// - ThreadImpl(Thread* owner); - - //////////////////////////////////////////////////////////// - /// \brief Destructor - /// - //////////////////////////////////////////////////////////// - ~ThreadImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Wait until the thread finishes - /// - //////////////////////////////////////////////////////////// - void wait(); - - //////////////////////////////////////////////////////////// - /// \brief Terminate the thread - /// - //////////////////////////////////////////////////////////// - void terminate(); - -private: - - //////////////////////////////////////////////////////////// - /// \brief Global entry point for all threads - /// - /// \param userData User-defined data (contains the Thread instance) - /// - /// \return OS specific error code - /// - //////////////////////////////////////////////////////////// - ALIGN_STACK static unsigned int __stdcall entryPoint(void* userData); - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - HANDLE m_thread; //!< Win32 thread handle - unsigned int m_threadId; //!< Win32 thread identifier -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_THREADIMPL_HPP diff --git a/src/SFML/System/Win32/ThreadLocalImpl.cpp b/src/SFML/System/Win32/ThreadLocalImpl.cpp deleted file mode 100644 index 4e47f6c47..000000000 --- a/src/SFML/System/Win32/ThreadLocalImpl.cpp +++ /dev/null @@ -1,64 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -ThreadLocalImpl::ThreadLocalImpl() -{ - m_index = TlsAlloc(); -} - - -//////////////////////////////////////////////////////////// -ThreadLocalImpl::~ThreadLocalImpl() -{ - TlsFree(m_index); -} - - -//////////////////////////////////////////////////////////// -void ThreadLocalImpl::setValue(void* value) -{ - TlsSetValue(m_index, value); -} - - -//////////////////////////////////////////////////////////// -void* ThreadLocalImpl::getValue() const -{ - return TlsGetValue(m_index); -} - -} // namespace priv - -} // namespace sf diff --git a/src/SFML/System/Win32/ThreadLocalImpl.hpp b/src/SFML/System/Win32/ThreadLocalImpl.hpp deleted file mode 100644 index a28e2d432..000000000 --- a/src/SFML/System/Win32/ThreadLocalImpl.hpp +++ /dev/null @@ -1,87 +0,0 @@ -//////////////////////////////////////////////////////////// -// -// SFML - Simple and Fast Multimedia Library -// Copyright (C) 2007-2021 Laurent Gomila (laurent@sfml-dev.org) -// -// This software is provided 'as-is', without any express or implied warranty. -// In no event will the authors be held liable for any damages arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it freely, -// subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; -// you must not claim that you wrote the original software. -// If you use this software in a product, an acknowledgment -// in the product documentation would be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, -// and must not be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source distribution. -// -//////////////////////////////////////////////////////////// - -#ifndef SFML_THREADLOCALIMPL_HPP -#define SFML_THREADLOCALIMPL_HPP - -//////////////////////////////////////////////////////////// -// Headers -//////////////////////////////////////////////////////////// -#include -#include - - -namespace sf -{ -namespace priv -{ -//////////////////////////////////////////////////////////// -/// \brief Windows implementation of thread-local storage -//////////////////////////////////////////////////////////// -class ThreadLocalImpl : NonCopyable -{ -public: - - //////////////////////////////////////////////////////////// - /// \brief Default constructor -- allocate the storage - /// - //////////////////////////////////////////////////////////// - ThreadLocalImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Destructor -- free the storage - /// - //////////////////////////////////////////////////////////// - ~ThreadLocalImpl(); - - //////////////////////////////////////////////////////////// - /// \brief Set the thread-specific value of the variable - /// - /// \param value Value of the variable for this thread - /// - //////////////////////////////////////////////////////////// - void setValue(void* value); - - //////////////////////////////////////////////////////////// - /// \brief Retrieve the thread-specific value of the variable - /// - /// \return Value of the variable for this thread - /// - //////////////////////////////////////////////////////////// - void* getValue() const; - -private: - - //////////////////////////////////////////////////////////// - // Member data - //////////////////////////////////////////////////////////// - DWORD m_index; //!< Index of our thread-local storage slot -}; - -} // namespace priv - -} // namespace sf - - -#endif // SFML_THREADLOCALIMPL_HPP diff --git a/src/SFML/Window/Android/InputImpl.cpp b/src/SFML/Window/Android/InputImpl.cpp index 90ed8023b..0c290668e 100644 --- a/src/SFML/Window/Android/InputImpl.cpp +++ b/src/SFML/Window/Android/InputImpl.cpp @@ -27,8 +27,8 @@ //////////////////////////////////////////////////////////// #include #include -#include #include +#include #include @@ -49,7 +49,7 @@ void InputImpl::setVirtualKeyboardVisible(bool visible) // todo: Check if the window is active ActivityStates& states = getActivity(); - Lock lock(states.mutex); + std::scoped_lock lock(states.mutex); // Initializes JNI jint lResult; @@ -138,8 +138,8 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button) { ALooper_pollAll(0, nullptr, nullptr, nullptr); - priv::ActivityStates& states = priv::getActivity(); - Lock lock(states.mutex); + ActivityStates& states = getActivity(); + std::scoped_lock lock(states.mutex); return states.isButtonPressed[button]; } @@ -150,8 +150,8 @@ Vector2i InputImpl::getMousePosition() { ALooper_pollAll(0, nullptr, nullptr, nullptr); - priv::ActivityStates& states = priv::getActivity(); - Lock lock(states.mutex); + ActivityStates& states = getActivity(); + std::scoped_lock lock(states.mutex); return states.mousePosition; } @@ -183,8 +183,8 @@ bool InputImpl::isTouchDown(unsigned int finger) { ALooper_pollAll(0, nullptr, nullptr, nullptr); - priv::ActivityStates& states = priv::getActivity(); - Lock lock(states.mutex); + ActivityStates& states = getActivity(); + std::scoped_lock lock(states.mutex); return states.touchEvents.find(finger) != states.touchEvents.end(); } @@ -195,8 +195,8 @@ Vector2i InputImpl::getTouchPosition(unsigned int finger) { ALooper_pollAll(0, nullptr, nullptr, nullptr); - priv::ActivityStates& states = priv::getActivity(); - Lock lock(states.mutex); + ActivityStates& states = getActivity(); + std::scoped_lock lock(states.mutex); return states.touchEvents.find(finger)->second; } diff --git a/src/SFML/Window/Android/VideoModeImpl.cpp b/src/SFML/Window/Android/VideoModeImpl.cpp index d525541ad..4522f090f 100644 --- a/src/SFML/Window/Android/VideoModeImpl.cpp +++ b/src/SFML/Window/Android/VideoModeImpl.cpp @@ -29,7 +29,7 @@ #include #include #include -#include +#include namespace sf { @@ -53,7 +53,7 @@ VideoMode VideoModeImpl::getDesktopMode() { // Get the activity states priv::ActivityStates& states = priv::getActivity(); - Lock lock(states.mutex); + std::scoped_lock lock(states.mutex); return VideoMode(states.screenSize.x, states.screenSize.y); } diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index e9e940a00..8a80135df 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -29,8 +29,8 @@ #include // important to be included first (conflict with None) #include #include -#include #include +#include #include // Define missing constants for older API levels @@ -65,8 +65,8 @@ WindowImplAndroid::WindowImplAndroid(VideoMode mode, const String& title, unsign , m_windowBeingDestroyed(false) , m_hasFocus(false) { - priv::ActivityStates& states = priv::getActivity(); - Lock lock(states.mutex); + ActivityStates& states = getActivity(); + std::scoped_lock lock(states.mutex); if (style& Style::Fullscreen) states.fullscreen = true; @@ -92,7 +92,7 @@ WindowImplAndroid::~WindowImplAndroid() WindowHandle WindowImplAndroid::getSystemHandle() const { ActivityStates& states = getActivity(); - Lock lock(states.mutex); + std::scoped_lock lock(states.mutex); return states.window; } @@ -105,7 +105,7 @@ void WindowImplAndroid::processEvents() ALooper_pollAll(0, nullptr, nullptr, nullptr); ActivityStates& states = getActivity(); - Lock lock(states.mutex); + std::scoped_lock lock(states.mutex); if (m_windowBeingCreated) { @@ -243,7 +243,7 @@ void WindowImplAndroid::forwardEvent(const Event& event) int WindowImplAndroid::processEvent(int fd, int events, void* data) { ActivityStates& states = getActivity(); - Lock lock(states.mutex); + std::scoped_lock lock(states.mutex); AInputEvent* _event = nullptr; @@ -680,7 +680,7 @@ int WindowImplAndroid::getUnicode(AInputEvent* event) { // Retrieve activity states ActivityStates& states = getActivity(); - Lock lock(states.mutex); + std::scoped_lock lock(states.mutex); // Initializes JNI jint lResult; diff --git a/src/SFML/Window/Context.cpp b/src/SFML/Window/Context.cpp index 6db7bfc14..e7a891393 100644 --- a/src/SFML/Window/Context.cpp +++ b/src/SFML/Window/Context.cpp @@ -27,7 +27,6 @@ //////////////////////////////////////////////////////////// #include #include -#include #include @@ -37,7 +36,7 @@ namespace namespace ContextImpl { // This per-thread variable holds the current context for each thread - sf::ThreadLocalPtr currentContext(nullptr); + thread_local sf::Context* currentContext(nullptr); } } diff --git a/src/SFML/Window/EglContext.cpp b/src/SFML/Window/EglContext.cpp index d5845c5d9..8e028e3a4 100644 --- a/src/SFML/Window/EglContext.cpp +++ b/src/SFML/Window/EglContext.cpp @@ -30,8 +30,7 @@ #include #include #include -#include -#include +#include #ifdef SFML_SYSTEM_ANDROID #include #endif @@ -58,7 +57,7 @@ namespace // On Android, its native activity handles this for us sf::priv::ActivityStates& states = sf::priv::getActivity(); - sf::Lock lock(states.mutex); + std::scoped_lock lock(states.mutex); return states.display; @@ -144,7 +143,7 @@ m_config (nullptr) // On Android, we must save the created context ActivityStates& states = getActivity(); - Lock lock(states.mutex); + std::scoped_lock lock(states.mutex); states.context = this; diff --git a/src/SFML/Window/GlContext.cpp b/src/SFML/Window/GlContext.cpp index b3848646c..4e18d6df8 100644 --- a/src/SFML/Window/GlContext.cpp +++ b/src/SFML/Window/GlContext.cpp @@ -28,9 +28,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -42,6 +39,8 @@ #include #include #include +#include +#include #if defined(SFML_SYSTEM_WINDOWS) @@ -158,13 +157,13 @@ namespace // This mutex is also used to protect the shared context // from being locked on multiple threads and for managing // the resource count - sf::Mutex mutex; + std::recursive_mutex mutex; // OpenGL resources counter unsigned int resourceCount = 0; // This per-thread variable holds the current context for each thread - sf::ThreadLocalPtr currentContext(nullptr); + thread_local sf::priv::GlContext* currentContext(nullptr); // The hidden, inactive context that will be shared with all other contexts ContextType* sharedContext = nullptr; @@ -190,7 +189,7 @@ namespace TransientContext() : referenceCount (0), context (nullptr), - sharedContextLock(nullptr), + sharedContextLock(), useSharedContext (false) { if (resourceCount == 0) @@ -199,7 +198,7 @@ namespace } else if (!currentContext) { - sharedContextLock = new sf::Lock(mutex); + sharedContextLock.emplace(mutex); useSharedContext = true; sharedContext->setActive(true); } @@ -214,22 +213,22 @@ namespace if (useSharedContext) sharedContext->setActive(false); - delete sharedContextLock; + sharedContextLock.reset(); delete context; } /////////////////////////////////////////////////////////// // Member data //////////////////////////////////////////////////////////// - unsigned int referenceCount; - sf::Context* context; - sf::Lock* sharedContextLock; - bool useSharedContext; + unsigned int referenceCount; + sf::Context* context; + std::optional> sharedContextLock; + bool useSharedContext; }; // This per-thread variable tracks if and how a transient // context is currently being used on the current thread - sf::ThreadLocalPtr transientContext(nullptr); + thread_local TransientContext* transientContext(nullptr); // Supported OpenGL extensions std::vector extensions; @@ -322,7 +321,7 @@ void GlContext::initResource() using GlContextImpl::loadExtensions; // Protect from concurrent access - Lock lock(mutex); + std::scoped_lock lock(mutex); // If this is the very first resource, trigger the global context initialization if (resourceCount == 0) @@ -359,7 +358,7 @@ void GlContext::cleanupResource() using GlContextImpl::sharedContext; // Protect from concurrent access - Lock lock(mutex); + std::scoped_lock lock(mutex); // Decrement the resources counter resourceCount--; @@ -392,7 +391,7 @@ void GlContext::acquireTransientContext() using GlContextImpl::transientContext; // Protect from concurrent access - Lock lock(mutex); + std::scoped_lock lock(mutex); // If this is the first TransientContextLock on this thread // construct the state object @@ -411,7 +410,7 @@ void GlContext::releaseTransientContext() using GlContextImpl::transientContext; // Protect from concurrent access - Lock lock(mutex); + std::scoped_lock lock(mutex); // Make sure a matching acquireTransientContext() was called assert(transientContext); @@ -438,7 +437,7 @@ GlContext* GlContext::create() // Make sure that there's an active context (context creation may need extensions, and thus a valid context) assert(sharedContext != nullptr); - Lock lock(mutex); + std::scoped_lock lock(mutex); GlContext* context = nullptr; @@ -471,7 +470,7 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* // Make sure that there's an active context (context creation may need extensions, and thus a valid context) assert(sharedContext != nullptr); - Lock lock(mutex); + std::scoped_lock lock(mutex); // If resourceCount is 1 we know that we are inside sf::Context or sf::Window // Only in this situation we allow the user to indirectly re-create the shared context as a core context @@ -524,7 +523,7 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width // Make sure that there's an active context (context creation may need extensions, and thus a valid context) assert(sharedContext != nullptr); - Lock lock(mutex); + std::scoped_lock lock(mutex); // If resourceCount is 1 we know that we are inside sf::Context or sf::Window // Only in this situation we allow the user to indirectly re-create the shared context as a core context @@ -577,7 +576,7 @@ bool GlContext::isExtensionAvailable(const char* name) //////////////////////////////////////////////////////////// GlFunctionPointer GlContext::getFunction(const char* name) { - Lock lock(GlContextImpl::mutex); + std::scoped_lock lock(GlContextImpl::mutex); return ContextType::getFunction(name); } @@ -632,7 +631,7 @@ bool GlContext::setActive(bool active) { if (this != currentContext) { - Lock lock(mutex); + std::scoped_lock lock(mutex); // Activate the context if (makeCurrent(true)) @@ -656,7 +655,7 @@ bool GlContext::setActive(bool active) { if (this == currentContext) { - Lock lock(mutex); + std::scoped_lock lock(mutex); // Deactivate the context if (makeCurrent(false)) diff --git a/src/SFML/Window/Unix/Display.cpp b/src/SFML/Window/Unix/Display.cpp index 1bb6ef65c..1dd954215 100644 --- a/src/SFML/Window/Unix/Display.cpp +++ b/src/SFML/Window/Unix/Display.cpp @@ -26,13 +26,12 @@ // Headers //////////////////////////////////////////////////////////// #include -#include -#include #include #include +#include +#include #include #include -#include namespace @@ -42,7 +41,7 @@ namespace unsigned int referenceCount = 0; XIM sharedXIM = NULL; unsigned int referenceCountXIM = 0; - sf::Mutex mutex; + std::recursive_mutex mutex; using AtomMap = std::unordered_map; AtomMap atoms; @@ -55,7 +54,7 @@ namespace priv //////////////////////////////////////////////////////////// Display* OpenDisplay() { - Lock lock(mutex); + std::scoped_lock lock(mutex); if (referenceCount == 0) { @@ -78,7 +77,7 @@ Display* OpenDisplay() //////////////////////////////////////////////////////////// void CloseDisplay(Display* display) { - Lock lock(mutex); + std::scoped_lock lock(mutex); assert(display == sharedDisplay); @@ -90,7 +89,7 @@ void CloseDisplay(Display* display) //////////////////////////////////////////////////////////// XIM OpenXIM() { - Lock lock(mutex); + std::scoped_lock lock(mutex); assert(sharedDisplay != nullptr); @@ -128,7 +127,7 @@ XIM OpenXIM() //////////////////////////////////////////////////////////// void CloseXIM(XIM xim) { - Lock lock(mutex); + std::scoped_lock lock(mutex); assert(xim == sharedXIM); diff --git a/src/SFML/Window/Unix/GlxContext.cpp b/src/SFML/Window/Unix/GlxContext.cpp index 2a27649d2..aa548c947 100644 --- a/src/SFML/Window/Unix/GlxContext.cpp +++ b/src/SFML/Window/Unix/GlxContext.cpp @@ -28,9 +28,8 @@ #include // important to be included first (conflict with None) #include #include -#include -#include #include +#include #include // We check for this definition in order to avoid multiple definitions of GLAD @@ -48,7 +47,7 @@ namespace { - sf::Mutex glxErrorMutex; + std::recursive_mutex glxErrorMutex; bool glxErrorOccurred = false; @@ -95,9 +94,9 @@ namespace } private: - sf::Lock m_lock; - ::Display* m_display; - int (*m_previousHandler)(::Display*, XErrorEvent*); + std::scoped_lock m_lock; + ::Display* m_display; + int (*m_previousHandler)(::Display*, XErrorEvent*); }; } diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 5bbfa6c38..7da831c48 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -31,10 +31,12 @@ #include #include #include -#include -#include #include + #include +#undef min // Defined by `Xlibint.h`, conflicts with standard headers +#undef max // Defined by `Xlibint.h`, conflicts with standard headers + #include #include #include @@ -49,6 +51,7 @@ #include #include #include +#include #ifdef SFML_OPENGL_ES #include @@ -68,7 +71,7 @@ namespace { sf::priv::WindowImplX11* fullscreenWindow = nullptr; std::vector allWindows; - sf::Mutex allWindowsMutex; + std::recursive_mutex allWindowsMutex; sf::String windowManagerName; sf::String wmAbsPosGood[] = { "Enlightenment", "FVWM", "i3" }; @@ -811,7 +814,7 @@ WindowImplX11::~WindowImplX11() CloseDisplay(m_display); // Remove this window from the global list of windows (required for focus request) - Lock lock(allWindowsMutex); + std::scoped_lock lock(allWindowsMutex); allWindows.erase(std::find(allWindows.begin(), allWindows.end(), this)); } @@ -1201,7 +1204,7 @@ void WindowImplX11::requestFocus() bool sfmlWindowFocused = false; { - Lock lock(allWindowsMutex); + std::scoped_lock lock(allWindowsMutex); for (sf::priv::WindowImplX11* windowPtr : allWindows) { if (windowPtr->hasFocus()) @@ -1658,7 +1661,7 @@ void WindowImplX11::initialize() XFlush(m_display); // Add this window to the global list of windows (required for focus request) - Lock lock(allWindowsMutex); + std::scoped_lock lock(allWindowsMutex); allWindows.push_back(this); } diff --git a/src/SFML/Window/Win32/WglContext.cpp b/src/SFML/Window/Win32/WglContext.cpp index c65795670..8f673fcbb 100644 --- a/src/SFML/Window/Win32/WglContext.cpp +++ b/src/SFML/Window/Win32/WglContext.cpp @@ -27,10 +27,8 @@ //////////////////////////////////////////////////////////// #include // included first to avoid a warning about macro redefinition #include -#include -#include -#include #include +#include #include #include @@ -48,7 +46,7 @@ namespace { // Some drivers are bugged and don't track the current HDC/HGLRC properly // In order to deactivate successfully, we need to track it ourselves as well - sf::ThreadLocalPtr currentContext(nullptr); + thread_local sf::priv::WglContext* currentContext(nullptr); //////////////////////////////////////////////////////////// @@ -648,8 +646,8 @@ void WglContext::createContext(WglContext* shared) if (sharedContext) { - static Mutex mutex; - Lock lock(mutex); + static std::recursive_mutex mutex; + std::scoped_lock lock(mutex); if (WglContextImpl::currentContext == shared) { @@ -718,8 +716,8 @@ void WglContext::createContext(WglContext* shared) if (sharedContext) { // wglShareLists doesn't seem to be thread-safe - static Mutex mutex; - Lock lock(mutex); + static std::recursive_mutex mutex; + std::scoped_lock lock(mutex); if (WglContextImpl::currentContext == shared) {