Replace SFML multithreading primitives with standard C++ ones

This commit is contained in:
Vittorio Romeo 2021-12-13 19:51:02 +01:00
parent db38696c48
commit b33f4bb205
54 changed files with 281 additions and 2508 deletions

View File

@ -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)
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()

View File

@ -10,7 +10,9 @@
#include <algorithm>
#include <deque>
#include <iostream>
#include <mutex>
#include <sstream>
#include <thread>
#include <vector>
#include <cmath>
@ -39,11 +41,11 @@ namespace
};
std::deque<WorkItem> workQueue;
std::vector<sf::Thread*> threads;
std::vector<std::thread> 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++)
{

View File

@ -8,6 +8,7 @@
#include <iomanip>
#include <iostream>
#include <iterator>
#include <mutex>
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<std::vector<sf::Int64>::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<const char*>(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<sf::Int16> m_samples;
std::vector<sf::Int16> m_tempBuffer;
std::size_t m_offset;

View File

@ -31,7 +31,6 @@
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundStream.hpp>
#include <SFML/Audio/InputSoundFile.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Time.hpp>
#include <string>
#include <vector>
@ -276,10 +275,10 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
InputSoundFile m_file; //!< The streamed music file
std::vector<Int16> m_samples; //!< Temporary buffer of samples
Mutex m_mutex; //!< Mutex protecting the data
Span<Uint64> m_loopSpan; //!< Loop Range Specifier
InputSoundFile m_file; //!< The streamed music file
std::vector<Int16> m_samples; //!< Temporary buffer of samples
std::recursive_mutex m_mutex; //!< Mutex protecting the data
Span<Uint64> m_loopSpan; //!< Loop Range Specifier
};
} // namespace sf

View File

@ -30,10 +30,10 @@
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/Time.hpp>
#include <vector>
#include <string>
#include <thread>
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<Int16> 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<Int16> 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

View File

@ -30,10 +30,10 @@
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/SoundSource.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/Time.hpp>
#include <SFML/System/Mutex.hpp>
#include <cstdlib>
#include <mutex>
#include <thread>
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

View File

@ -34,15 +34,10 @@
#include <SFML/System/Err.hpp>
#include <SFML/System/FileInputStream.hpp>
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/MemoryInputStream.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/String.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/ThreadLocal.hpp>
#include <SFML/System/ThreadLocalPtr.hpp>
#include <SFML/System/Time.hpp>
#include <SFML/System/Utf.hpp>
#include <SFML/System/Vector2.hpp>

View File

@ -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 <SFML/System/Export.hpp>
#include <SFML/System/NonCopyable.hpp>
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
///
////////////////////////////////////////////////////////////

View File

@ -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 <SFML/System/Export.hpp>
#include <SFML/System/NonCopyable.hpp>
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
///
////////////////////////////////////////////////////////////

View File

@ -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 <SFML/System/Export.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <cstdlib>
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 <typename F>
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 <typename F, typename A>
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 <typename C>
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 <SFML/System/Thread.inl>
} // 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
///
////////////////////////////////////////////////////////////

View File

@ -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 <typename T>
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 <typename F, typename A>
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 <typename C>
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 <typename F>
Thread::Thread(F functor) :
m_impl (nullptr),
m_entryPoint(new priv::ThreadFunctor<F>(functor))
{
}
////////////////////////////////////////////////////////////
template <typename F, typename A>
Thread::Thread(F function, A argument) :
m_impl (nullptr),
m_entryPoint(new priv::ThreadFunctorWithArg<F, A>(function, argument))
{
}
////////////////////////////////////////////////////////////
template <typename C>
Thread::Thread(void(C::*function)(), C* object) :
m_impl (nullptr),
m_entryPoint(new priv::ThreadMemberFunc<C>(function, object))
{
}

View File

@ -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 <SFML/System/Export.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <cstdlib>
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.
///
////////////////////////////////////////////////////////////

View File

@ -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 <SFML/System/ThreadLocal.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Pointer to a thread-local variable
///
////////////////////////////////////////////////////////////
template <typename T>
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<T>& operator =(T* value);
////////////////////////////////////////////////////////////
/// \brief Assignment operator for a ThreadLocalPtr parameter
///
/// \param right ThreadLocalPtr to assign
///
/// \return Reference to self
///
////////////////////////////////////////////////////////////
ThreadLocalPtr<T>& operator =(const ThreadLocalPtr<T>& right);
};
} // namespace sf
#include <SFML/System/ThreadLocalPtr.inl>
#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<MyClass> 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.
///
////////////////////////////////////////////////////////////

View File

@ -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 <typename T>
ThreadLocalPtr<T>::ThreadLocalPtr(T* value) :
ThreadLocal(value)
{
}
////////////////////////////////////////////////////////////
template <typename T>
T& ThreadLocalPtr<T>::operator *() const
{
return *static_cast<T*>(getValue());
}
////////////////////////////////////////////////////////////
template <typename T>
T* ThreadLocalPtr<T>::operator ->() const
{
return static_cast<T*>(getValue());
}
////////////////////////////////////////////////////////////
template <typename T>
ThreadLocalPtr<T>::operator T*() const
{
return static_cast<T*>(getValue());
}
////////////////////////////////////////////////////////////
template <typename T>
ThreadLocalPtr<T>& ThreadLocalPtr<T>::operator =(T* value)
{
setValue(value);
return *this;
}
////////////////////////////////////////////////////////////
template <typename T>
ThreadLocalPtr<T>& ThreadLocalPtr<T>::operator =(const ThreadLocalPtr<T>& right)
{
setValue(right.getValue());
return *this;
}
} // namespace sf

View File

@ -27,15 +27,14 @@
////////////////////////////////////////////////////////////
#include <SFML/Audio/AlResource.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <mutex>
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--;

View File

@ -27,10 +27,10 @@
////////////////////////////////////////////////////////////
#include <SFML/Audio/Music.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <fstream>
#include <algorithm>
#include <mutex>
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))
{

View File

@ -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

View File

@ -30,7 +30,8 @@
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Lock.hpp>
#include <cassert>
#include <mutex>
#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

View File

@ -33,13 +33,12 @@
#include <SFML/Graphics/VertexBuffer.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
#include <iostream>
#include <algorithm>
#include <iostream>
#include <mutex>
#include <unordered_map>
#include <cassert>
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();

View File

@ -28,13 +28,12 @@
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <utility>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <mutex>
namespace
@ -53,7 +52,7 @@ namespace
std::set<std::pair<sf::Uint64, unsigned int> > 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<Uint64, unsigned int>::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);

View File

@ -33,11 +33,10 @@
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <fstream>
#include <vector>
#include <mutex>
#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;

View File

@ -31,12 +31,11 @@
#include <SFML/Graphics/TextureSaver.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/Window.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
#include <cstring>
#include <climits>
#include <mutex>
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;

View File

@ -29,17 +29,16 @@
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Vertex.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <cstring>
#include <mutex>
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;

View File

@ -40,13 +40,13 @@
#include <SFML/System/Android/Activity.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <android/window.h>
#include <android/native_activity.h>
#include <cstring>
#include <cassert>
#include <mutex>
#include <thread>
#define SF_GLAD_EGL_IMPLEMENTATION
#include <glad/egl.h>
@ -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();

View File

@ -30,13 +30,13 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Event.hpp>
#include <SFML/Window/EglContext.hpp>
#include <SFML/System/Mutex.hpp>
#include <android/native_activity.h>
#include <android/configuration.h>
#include <vector>
#include <unordered_map>
#include <string>
#include <fstream>
#include <mutex>
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);

View File

@ -28,7 +28,7 @@
////////////////////////////////////////////////////////////
#include <SFML/System/Android/ResourceStream.hpp>
#include <SFML/System/Android/Activity.hpp>
#include <SFML/System/Lock.hpp>
#include <mutex>
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);
}

View File

@ -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)

View File

@ -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 <SFML/System/Lock.hpp>
#include <SFML/System/Mutex.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Lock::Lock(Mutex& mutex) :
m_mutex(mutex)
{
m_mutex.lock();
}
////////////////////////////////////////////////////////////
Lock::~Lock()
{
m_mutex.unlock();
}
} // namespace sf

View File

@ -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 <SFML/System/Mutex.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/MutexImpl.hpp>
#else
#include <SFML/System/Unix/MutexImpl.hpp>
#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

View File

@ -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 <SFML/System/Thread.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/ThreadImpl.hpp>
#else
#include <SFML/System/Unix/ThreadImpl.hpp>
#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

View File

@ -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 <SFML/System/ThreadLocal.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/ThreadLocalImpl.hpp>
#else
#include <SFML/System/Unix/ThreadLocalImpl.hpp>
#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

View File

@ -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 <SFML/System/Unix/MutexImpl.hpp>
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

View File

@ -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 <SFML/System/NonCopyable.hpp>
#include <pthread.h>
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

View File

@ -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 <SFML/System/Unix/ThreadImpl.hpp>
#include <SFML/System/Thread.hpp>
#include <iostream>
#include <cassert>
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<Thread*>(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

View File

@ -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 <SFML/Config.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <pthread.h>
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

View File

@ -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 <SFML/System/Unix/ThreadLocalImpl.hpp>
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

View File

@ -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 <SFML/System/NonCopyable.hpp>
#include <pthread.h>
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

View File

@ -26,8 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Win32/ClockImpl.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <mutex>
#include <windows.h>
@ -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);

View File

@ -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 <SFML/System/Win32/MutexImpl.hpp>
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

View File

@ -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 <SFML/System/NonCopyable.hpp>
#include <windows.h>
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

View File

@ -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 <SFML/System/Win32/ThreadImpl.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
#include <process.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ThreadImpl::ThreadImpl(Thread* owner)
{
m_thread = reinterpret_cast<HANDLE>(_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<Thread*>(userData);
// Forward to the owner
owner->run();
// Optional, but it is cleaner
_endthreadex(0);
return 0;
}
} // namespace priv
} // namespace sf

View File

@ -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 <SFML/System/NonCopyable.hpp>
#include <windows.h>
// 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

View File

@ -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 <SFML/System/Win32/ThreadLocalImpl.hpp>
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

View File

@ -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 <SFML/System/NonCopyable.hpp>
#include <windows.h>
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

View File

@ -27,8 +27,8 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Android/InputImpl.hpp>
#include <SFML/System/Android/Activity.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <mutex>
#include <jni.h>
@ -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;
}

View File

@ -29,7 +29,7 @@
#include <SFML/System/Android/Activity.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Lock.hpp>
#include <mutex>
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);
}

View File

@ -29,8 +29,8 @@
#include <SFML/Window/WindowStyle.hpp> // important to be included first (conflict with None)
#include <SFML/Window/Android/WindowImplAndroid.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <mutex>
#include <android/looper.h>
// 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;

View File

@ -27,7 +27,6 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Context.hpp>
#include <SFML/Window/GlContext.hpp>
#include <SFML/System/ThreadLocalPtr.hpp>
#include <SFML/System/Err.hpp>
@ -37,7 +36,7 @@ namespace
namespace ContextImpl
{
// This per-thread variable holds the current context for each thread
sf::ThreadLocalPtr<sf::Context> currentContext(nullptr);
thread_local sf::Context* currentContext(nullptr);
}
}

View File

@ -30,8 +30,7 @@
#include <SFML/Window/WindowImpl.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <mutex>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/Activity.hpp>
#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;

View File

@ -28,9 +28,6 @@
#include <SFML/Window/GlContext.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/EglContext.hpp>
#include <SFML/System/ThreadLocalPtr.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <glad/gl.h>
#include <algorithm>
@ -42,6 +39,8 @@
#include <cstring>
#include <cctype>
#include <cassert>
#include <mutex>
#include <optional>
#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<sf::priv::GlContext> 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<std::scoped_lock<std::recursive_mutex>> 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> transientContext(nullptr);
thread_local TransientContext* transientContext(nullptr);
// Supported OpenGL extensions
std::vector<std::string> 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))

View File

@ -26,13 +26,12 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Err.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <X11/keysym.h>
#include <mutex>
#include <unordered_map>
#include <cassert>
#include <cstdlib>
#include <unordered_map>
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<std::string, Atom>;
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);

View File

@ -28,9 +28,8 @@
#include <SFML/Window/Unix/WindowImplX11.hpp> // important to be included first (conflict with None)
#include <SFML/Window/Unix/GlxContext.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <mutex>
#include <vector>
// 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<std::recursive_mutex> m_lock;
::Display* m_display;
int (*m_previousHandler)(::Display*, XErrorEvent*);
};
}

View File

@ -31,10 +31,12 @@
#include <SFML/Window/Unix/InputImpl.hpp>
#include <SFML/System/Utf.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Sleep.hpp>
#include <X11/Xlibint.h>
#undef min // Defined by `Xlibint.h`, conflicts with standard headers
#undef max // Defined by `Xlibint.h`, conflicts with standard headers
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
@ -49,6 +51,7 @@
#include <string>
#include <cstring>
#include <cassert>
#include <mutex>
#ifdef SFML_OPENGL_ES
#include <SFML/Window/EglContext.hpp>
@ -68,7 +71,7 @@ namespace
{
sf::priv::WindowImplX11* fullscreenWindow = nullptr;
std::vector<sf::priv::WindowImplX11*> 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);
}

View File

@ -27,10 +27,8 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/WindowImpl.hpp> // included first to avoid a warning about macro redefinition
#include <SFML/Window/Win32/WglContext.hpp>
#include <SFML/System/ThreadLocalPtr.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Err.hpp>
#include <mutex>
#include <sstream>
#include <vector>
@ -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<sf::priv::WglContext> 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)
{