mirror of
https://github.com/SFML/SFML.git
synced 2024-11-24 20:31:05 +08:00
Replace SFML multithreading primitives with standard C++ ones
This commit is contained in:
parent
db38696c48
commit
b33f4bb205
@ -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()
|
||||
|
@ -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++)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
@ -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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
@ -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
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
@ -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))
|
||||
{
|
||||
}
|
@ -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.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
@ -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.
|
||||
///
|
||||
////////////////////////////////////////////////////////////
|
@ -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
|
@ -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--;
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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);
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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*);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user