mirror of
https://github.com/SFML/SFML.git
synced 2024-11-28 22:31:09 +08:00
Replace SFML multithreading primitives with standard C++ ones
This commit is contained in:
parent
db38696c48
commit
b33f4bb205
@ -12,3 +12,8 @@ sfml_add_example(island GUI_APP
|
|||||||
|
|
||||||
# external dependency headers
|
# 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 <algorithm>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -39,11 +41,11 @@ namespace
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::deque<WorkItem> workQueue;
|
std::deque<WorkItem> workQueue;
|
||||||
std::vector<sf::Thread*> threads;
|
std::vector<std::thread> threads;
|
||||||
int pendingWorkCount = 0;
|
int pendingWorkCount = 0;
|
||||||
bool workPending = true;
|
bool workPending = true;
|
||||||
bool bufferUploadPending = false;
|
bool bufferUploadPending = false;
|
||||||
sf::Mutex workQueueMutex;
|
std::recursive_mutex workQueueMutex;
|
||||||
|
|
||||||
struct Setting
|
struct Setting
|
||||||
{
|
{
|
||||||
@ -136,8 +138,7 @@ int main()
|
|||||||
// Start up our thread pool
|
// Start up our thread pool
|
||||||
for (unsigned int i = 0; i < threadCount; i++)
|
for (unsigned int i = 0; i < threadCount; i++)
|
||||||
{
|
{
|
||||||
threads.push_back(new sf::Thread(threadFunction));
|
threads.emplace_back(threadFunction);
|
||||||
threads.back()->launch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create our VertexBuffer with enough space to hold all the terrain geometry
|
// Create our VertexBuffer with enough space to hold all the terrain geometry
|
||||||
@ -216,7 +217,7 @@ int main()
|
|||||||
if (prerequisitesSupported)
|
if (prerequisitesSupported)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
sf::Lock lock(workQueueMutex);
|
std::scoped_lock lock(workQueueMutex);
|
||||||
|
|
||||||
// Don't bother updating/drawing the VertexBuffer while terrain is being regenerated
|
// Don't bother updating/drawing the VertexBuffer while terrain is being regenerated
|
||||||
if (!pendingWorkCount)
|
if (!pendingWorkCount)
|
||||||
@ -258,14 +259,13 @@ int main()
|
|||||||
|
|
||||||
// Shut down our thread pool
|
// Shut down our thread pool
|
||||||
{
|
{
|
||||||
sf::Lock lock(workQueueMutex);
|
std::scoped_lock lock(workQueueMutex);
|
||||||
workPending = false;
|
workPending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!threads.empty())
|
while (!threads.empty())
|
||||||
{
|
{
|
||||||
threads.back()->wait();
|
threads.back().join();
|
||||||
delete threads.back();
|
|
||||||
threads.pop_back();
|
threads.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,7 +552,7 @@ void threadFunction()
|
|||||||
|
|
||||||
// Check if there are new work items in the queue
|
// Check if there are new work items in the queue
|
||||||
{
|
{
|
||||||
sf::Lock lock(workQueueMutex);
|
std::scoped_lock lock(workQueueMutex);
|
||||||
|
|
||||||
if (!workPending)
|
if (!workPending)
|
||||||
return;
|
return;
|
||||||
@ -575,7 +575,7 @@ void threadFunction()
|
|||||||
processWorkItem(vertices, workItem);
|
processWorkItem(vertices, workItem);
|
||||||
|
|
||||||
{
|
{
|
||||||
sf::Lock lock(workQueueMutex);
|
std::scoped_lock lock(workQueueMutex);
|
||||||
|
|
||||||
--pendingWorkCount;
|
--pendingWorkCount;
|
||||||
}
|
}
|
||||||
@ -597,7 +597,7 @@ void generateTerrain(sf::Vertex* buffer)
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
sf::Lock lock(workQueueMutex);
|
std::scoped_lock lock(workQueueMutex);
|
||||||
|
|
||||||
if (workQueue.empty())
|
if (workQueue.empty())
|
||||||
break;
|
break;
|
||||||
@ -608,7 +608,7 @@ void generateTerrain(sf::Vertex* buffer)
|
|||||||
|
|
||||||
// Queue all the new work items
|
// Queue all the new work items
|
||||||
{
|
{
|
||||||
sf::Lock lock(workQueueMutex);
|
std::scoped_lock lock(workQueueMutex);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < blockCount; i++)
|
for (unsigned int i = 0; i < blockCount; i++)
|
||||||
{
|
{
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
const sf::Uint8 serverAudioData = 1;
|
const sf::Uint8 serverAudioData = 1;
|
||||||
@ -84,7 +85,7 @@ private:
|
|||||||
// Copy samples into a local buffer to avoid synchronization problems
|
// Copy samples into a local buffer to avoid synchronization problems
|
||||||
// (don't forget that we run in two separate threads)
|
// (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());
|
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
|
// 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)
|
// (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();
|
std::size_t oldSize = m_samples.size();
|
||||||
m_samples.resize(oldSize + sampleCount);
|
m_samples.resize(oldSize + sampleCount);
|
||||||
std::memcpy(&(m_samples[oldSize]), static_cast<const char*>(packet.getData()) + 1, sampleCount * sizeof(sf::Int16));
|
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::TcpListener m_listener;
|
||||||
sf::TcpSocket m_client;
|
sf::TcpSocket m_client;
|
||||||
sf::Mutex m_mutex;
|
std::recursive_mutex m_mutex;
|
||||||
std::vector<sf::Int16> m_samples;
|
std::vector<sf::Int16> m_samples;
|
||||||
std::vector<sf::Int16> m_tempBuffer;
|
std::vector<sf::Int16> m_tempBuffer;
|
||||||
std::size_t m_offset;
|
std::size_t m_offset;
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
#include <SFML/Audio/SoundStream.hpp>
|
#include <SFML/Audio/SoundStream.hpp>
|
||||||
#include <SFML/Audio/InputSoundFile.hpp>
|
#include <SFML/Audio/InputSoundFile.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -278,7 +277,7 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
InputSoundFile m_file; //!< The streamed music file
|
InputSoundFile m_file; //!< The streamed music file
|
||||||
std::vector<Int16> m_samples; //!< Temporary buffer of samples
|
std::vector<Int16> m_samples; //!< Temporary buffer of samples
|
||||||
Mutex m_mutex; //!< Mutex protecting the data
|
std::recursive_mutex m_mutex; //!< Mutex protecting the data
|
||||||
Span<Uint64> m_loopSpan; //!< Loop Range Specifier
|
Span<Uint64> m_loopSpan; //!< Loop Range Specifier
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,10 +30,10 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
#include <SFML/Audio/AlResource.hpp>
|
#include <SFML/Audio/AlResource.hpp>
|
||||||
#include <SFML/System/Thread.hpp>
|
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -282,10 +282,28 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void cleanup();
|
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
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Thread m_thread; //!< Thread running the background recording task
|
std::thread m_thread; //!< Thread running the background recording task
|
||||||
std::vector<Int16> m_samples; //!< Buffer to store captured samples
|
std::vector<Int16> m_samples; //!< Buffer to store captured samples
|
||||||
unsigned int m_sampleRate; //!< Sample rate
|
unsigned int m_sampleRate; //!< Sample rate
|
||||||
Time m_processingInterval; //!< Time period between calls to onProcessSamples
|
Time m_processingInterval; //!< Time period between calls to onProcessSamples
|
||||||
|
@ -30,10 +30,10 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Export.hpp>
|
#include <SFML/Audio/Export.hpp>
|
||||||
#include <SFML/Audio/SoundSource.hpp>
|
#include <SFML/Audio/SoundSource.hpp>
|
||||||
#include <SFML/System/Thread.hpp>
|
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -311,6 +311,24 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void clearQueue();
|
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
|
enum
|
||||||
{
|
{
|
||||||
BufferCount = 3, //!< Number of audio buffers used by the streaming loop
|
BufferCount = 3, //!< Number of audio buffers used by the streaming loop
|
||||||
@ -320,8 +338,8 @@ private:
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Thread m_thread; //!< Thread running the background tasks
|
std::thread m_thread; //!< Thread running the background tasks
|
||||||
mutable Mutex m_threadMutex; //!< Thread mutex
|
mutable std::recursive_mutex m_threadMutex; //!< Thread mutex
|
||||||
Status m_threadStartState; //!< State the thread starts in (Playing, Paused, Stopped)
|
Status m_threadStartState; //!< State the thread starts in (Playing, Paused, Stopped)
|
||||||
bool m_isStreaming; //!< Streaming state (true = playing, false = 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_buffers[BufferCount]; //!< Sound buffers used to store temporary audio data
|
||||||
|
@ -34,15 +34,10 @@
|
|||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/FileInputStream.hpp>
|
#include <SFML/System/FileInputStream.hpp>
|
||||||
#include <SFML/System/InputStream.hpp>
|
#include <SFML/System/InputStream.hpp>
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/MemoryInputStream.hpp>
|
#include <SFML/System/MemoryInputStream.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/NonCopyable.hpp>
|
#include <SFML/System/NonCopyable.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
#include <SFML/System/String.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/Time.hpp>
|
||||||
#include <SFML/System/Utf.hpp>
|
#include <SFML/System/Utf.hpp>
|
||||||
#include <SFML/System/Vector2.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/AlResource.hpp>
|
||||||
#include <SFML/Audio/AudioDevice.hpp>
|
#include <SFML/Audio/AudioDevice.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
#include <mutex>
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// OpenAL resources counter and its mutex
|
// OpenAL resources counter and its mutex
|
||||||
unsigned int count = 0;
|
unsigned int count = 0;
|
||||||
sf::Mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
|
|
||||||
// The audio device is instantiated on demand rather than at global startup,
|
// The audio device is instantiated on demand rather than at global startup,
|
||||||
// which solves a lot of weird crashes and errors.
|
// which solves a lot of weird crashes and errors.
|
||||||
@ -50,7 +49,7 @@ namespace sf
|
|||||||
AlResource::AlResource()
|
AlResource::AlResource()
|
||||||
{
|
{
|
||||||
// Protect from concurrent access
|
// 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 this is the very first resource, trigger the global device initialization
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
@ -65,7 +64,7 @@ AlResource::AlResource()
|
|||||||
AlResource::~AlResource()
|
AlResource::~AlResource()
|
||||||
{
|
{
|
||||||
// Protect from concurrent access
|
// Protect from concurrent access
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
// Decrement the resources counter
|
// Decrement the resources counter
|
||||||
count--;
|
count--;
|
||||||
|
@ -27,10 +27,10 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Audio/Music.hpp>
|
#include <SFML/Audio/Music.hpp>
|
||||||
#include <SFML/Audio/ALCheck.hpp>
|
#include <SFML/Audio/ALCheck.hpp>
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -179,7 +179,7 @@ void Music::setLoopPoints(TimeSpan timePoints)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Music::onGetData(SoundStream::Chunk& data)
|
bool Music::onGetData(SoundStream::Chunk& data)
|
||||||
{
|
{
|
||||||
Lock lock(m_mutex);
|
std::scoped_lock lock(m_mutex);
|
||||||
|
|
||||||
std::size_t toFill = m_samples.size();
|
std::size_t toFill = m_samples.size();
|
||||||
Uint64 currentOffset = m_file.getSampleOffset();
|
Uint64 currentOffset = m_file.getSampleOffset();
|
||||||
@ -204,7 +204,7 @@ bool Music::onGetData(SoundStream::Chunk& data)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void Music::onSeek(Time timeOffset)
|
void Music::onSeek(Time timeOffset)
|
||||||
{
|
{
|
||||||
Lock lock(m_mutex);
|
std::scoped_lock lock(m_mutex);
|
||||||
m_file.seek(timeOffset);
|
m_file.seek(timeOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,7 +213,7 @@ void Music::onSeek(Time timeOffset)
|
|||||||
Int64 Music::onLoop()
|
Int64 Music::onLoop()
|
||||||
{
|
{
|
||||||
// Called by underlying SoundStream so we can determine where to loop.
|
// 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();
|
Uint64 currentOffset = m_file.getSampleOffset();
|
||||||
if (getLoop() && (m_loopSpan.length != 0) && (currentOffset == m_loopSpan.offset + m_loopSpan.length))
|
if (getLoop() && (m_loopSpan.length != 0) && (currentOffset == m_loopSpan.offset + m_loopSpan.length))
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,7 @@ namespace sf
|
|||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundRecorder::SoundRecorder() :
|
SoundRecorder::SoundRecorder() :
|
||||||
m_thread (&SoundRecorder::record, this),
|
m_thread (),
|
||||||
m_sampleRate (0),
|
m_sampleRate (0),
|
||||||
m_processingInterval(milliseconds(100)),
|
m_processingInterval(milliseconds(100)),
|
||||||
m_isCapturing (false),
|
m_isCapturing (false),
|
||||||
@ -111,8 +111,7 @@ bool SoundRecorder::start(unsigned int sampleRate)
|
|||||||
alcCaptureStart(captureDevice);
|
alcCaptureStart(captureDevice);
|
||||||
|
|
||||||
// Start the capture in a new thread, to avoid blocking the main thread
|
// Start the capture in a new thread, to avoid blocking the main thread
|
||||||
m_isCapturing = true;
|
launchCapturingThread();
|
||||||
m_thread.launch();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -127,8 +126,7 @@ void SoundRecorder::stop()
|
|||||||
// Stop the capturing thread if there is one
|
// Stop the capturing thread if there is one
|
||||||
if (m_isCapturing)
|
if (m_isCapturing)
|
||||||
{
|
{
|
||||||
m_isCapturing = false;
|
awaitCapturingThread();
|
||||||
m_thread.wait();
|
|
||||||
|
|
||||||
// Notify derived class
|
// Notify derived class
|
||||||
onStop();
|
onStop();
|
||||||
@ -181,8 +179,7 @@ bool SoundRecorder::setDevice(const std::string& name)
|
|||||||
if (m_isCapturing)
|
if (m_isCapturing)
|
||||||
{
|
{
|
||||||
// Stop the capturing thread
|
// Stop the capturing thread
|
||||||
m_isCapturing = false;
|
awaitCapturingThread();
|
||||||
m_thread.wait();
|
|
||||||
|
|
||||||
// Determine the recording format
|
// Determine the recording format
|
||||||
ALCenum format = (m_channelCount == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
ALCenum format = (m_channelCount == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
||||||
@ -202,8 +199,7 @@ bool SoundRecorder::setDevice(const std::string& name)
|
|||||||
alcCaptureStart(captureDevice);
|
alcCaptureStart(captureDevice);
|
||||||
|
|
||||||
// Start the capture in a new thread, to avoid blocking the main thread
|
// Start the capture in a new thread, to avoid blocking the main thread
|
||||||
m_isCapturing = true;
|
launchCapturingThread();
|
||||||
m_thread.launch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -327,4 +323,24 @@ void SoundRecorder::cleanup()
|
|||||||
captureDevice = nullptr;
|
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
|
} // namespace sf
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
#include <SFML/Audio/ALCheck.hpp>
|
#include <SFML/Audio/ALCheck.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Lock.hpp>
|
#include <cassert>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(disable: 4355) // 'this' used in base member initializer list
|
#pragma warning(disable: 4355) // 'this' used in base member initializer list
|
||||||
@ -41,7 +42,7 @@ namespace sf
|
|||||||
{
|
{
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundStream::SoundStream() :
|
SoundStream::SoundStream() :
|
||||||
m_thread (&SoundStream::streamData, this),
|
m_thread (),
|
||||||
m_threadMutex (),
|
m_threadMutex (),
|
||||||
m_threadStartState(Stopped),
|
m_threadStartState(Stopped),
|
||||||
m_isStreaming (false),
|
m_isStreaming (false),
|
||||||
@ -63,14 +64,8 @@ SoundStream::~SoundStream()
|
|||||||
{
|
{
|
||||||
// Stop the sound if it was playing
|
// Stop the sound if it was playing
|
||||||
|
|
||||||
// Request the thread to terminate
|
// Wait for the thread to join
|
||||||
{
|
awaitStreamingThread();
|
||||||
Lock lock(m_threadMutex);
|
|
||||||
m_isStreaming = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the thread to terminate
|
|
||||||
m_thread.wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -109,7 +104,7 @@ void SoundStream::play()
|
|||||||
Status threadStartState = Stopped;
|
Status threadStartState = Stopped;
|
||||||
|
|
||||||
{
|
{
|
||||||
Lock lock(m_threadMutex);
|
std::scoped_lock lock(m_threadMutex);
|
||||||
|
|
||||||
isStreaming = m_isStreaming;
|
isStreaming = m_isStreaming;
|
||||||
threadStartState = m_threadStartState;
|
threadStartState = m_threadStartState;
|
||||||
@ -119,7 +114,7 @@ void SoundStream::play()
|
|||||||
if (isStreaming && (threadStartState == Paused))
|
if (isStreaming && (threadStartState == Paused))
|
||||||
{
|
{
|
||||||
// If the sound is paused, resume it
|
// If the sound is paused, resume it
|
||||||
Lock lock(m_threadMutex);
|
std::scoped_lock lock(m_threadMutex);
|
||||||
m_threadStartState = Playing;
|
m_threadStartState = Playing;
|
||||||
alCheck(alSourcePlay(m_source));
|
alCheck(alSourcePlay(m_source));
|
||||||
return;
|
return;
|
||||||
@ -131,9 +126,7 @@ void SoundStream::play()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start updating the stream in a separate thread to avoid blocking the application
|
// Start updating the stream in a separate thread to avoid blocking the application
|
||||||
m_isStreaming = true;
|
launchStreamingThread(Playing);
|
||||||
m_threadStartState = Playing;
|
|
||||||
m_thread.launch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -142,7 +135,7 @@ void SoundStream::pause()
|
|||||||
{
|
{
|
||||||
// Handle pause() being called before the thread has started
|
// Handle pause() being called before the thread has started
|
||||||
{
|
{
|
||||||
Lock lock(m_threadMutex);
|
std::scoped_lock lock(m_threadMutex);
|
||||||
|
|
||||||
if (!m_isStreaming)
|
if (!m_isStreaming)
|
||||||
return;
|
return;
|
||||||
@ -157,14 +150,8 @@ void SoundStream::pause()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::stop()
|
void SoundStream::stop()
|
||||||
{
|
{
|
||||||
// Request the thread to terminate
|
// Wait for the thread to join
|
||||||
{
|
awaitStreamingThread();
|
||||||
Lock lock(m_threadMutex);
|
|
||||||
m_isStreaming = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for the thread to terminate
|
|
||||||
m_thread.wait();
|
|
||||||
|
|
||||||
// Move to the beginning
|
// Move to the beginning
|
||||||
onSeek(Time::Zero);
|
onSeek(Time::Zero);
|
||||||
@ -193,7 +180,7 @@ SoundStream::Status SoundStream::getStatus() const
|
|||||||
// To compensate for the lag between play() and alSourceplay()
|
// To compensate for the lag between play() and alSourceplay()
|
||||||
if (status == Stopped)
|
if (status == Stopped)
|
||||||
{
|
{
|
||||||
Lock lock(m_threadMutex);
|
std::scoped_lock lock(m_threadMutex);
|
||||||
|
|
||||||
if (m_isStreaming)
|
if (m_isStreaming)
|
||||||
status = m_threadStartState;
|
status = m_threadStartState;
|
||||||
@ -221,9 +208,7 @@ void SoundStream::setPlayingOffset(Time timeOffset)
|
|||||||
if (oldStatus == Stopped)
|
if (oldStatus == Stopped)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_isStreaming = true;
|
launchStreamingThread(oldStatus);
|
||||||
m_threadStartState = oldStatus;
|
|
||||||
m_thread.launch();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -277,7 +262,7 @@ void SoundStream::streamData()
|
|||||||
bool requestStop = false;
|
bool requestStop = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
Lock lock(m_threadMutex);
|
std::scoped_lock lock(m_threadMutex);
|
||||||
|
|
||||||
// Check if the thread was launched Stopped
|
// Check if the thread was launched Stopped
|
||||||
if (m_threadStartState == Stopped)
|
if (m_threadStartState == Stopped)
|
||||||
@ -299,7 +284,7 @@ void SoundStream::streamData()
|
|||||||
alCheck(alSourcePlay(m_source));
|
alCheck(alSourcePlay(m_source));
|
||||||
|
|
||||||
{
|
{
|
||||||
Lock lock(m_threadMutex);
|
std::scoped_lock lock(m_threadMutex);
|
||||||
|
|
||||||
// Check if the thread was launched Paused
|
// Check if the thread was launched Paused
|
||||||
if (m_threadStartState == Paused)
|
if (m_threadStartState == Paused)
|
||||||
@ -309,7 +294,7 @@ void SoundStream::streamData()
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
Lock lock(m_threadMutex);
|
std::scoped_lock lock(m_threadMutex);
|
||||||
if (!m_isStreaming)
|
if (!m_isStreaming)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -325,7 +310,7 @@ void SoundStream::streamData()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// End streaming
|
// End streaming
|
||||||
Lock lock(m_threadMutex);
|
std::scoped_lock lock(m_threadMutex);
|
||||||
m_isStreaming = false;
|
m_isStreaming = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -369,7 +354,7 @@ void SoundStream::streamData()
|
|||||||
<< "and initialize() has been called correctly" << std::endl;
|
<< "and initialize() has been called correctly" << std::endl;
|
||||||
|
|
||||||
// Abort streaming (exit main loop)
|
// Abort streaming (exit main loop)
|
||||||
Lock lock(m_threadMutex);
|
std::scoped_lock lock(m_threadMutex);
|
||||||
m_isStreaming = false;
|
m_isStreaming = false;
|
||||||
requestStop = true;
|
requestStop = true;
|
||||||
break;
|
break;
|
||||||
@ -498,4 +483,29 @@ void SoundStream::clearQueue()
|
|||||||
alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
|
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
|
} // namespace sf
|
||||||
|
@ -33,13 +33,12 @@
|
|||||||
#include <SFML/Graphics/VertexBuffer.hpp>
|
#include <SFML/Graphics/VertexBuffer.hpp>
|
||||||
#include <SFML/Graphics/GLCheck.hpp>
|
#include <SFML/Graphics/GLCheck.hpp>
|
||||||
#include <SFML/Window/Context.hpp>
|
#include <SFML/Window/Context.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -48,13 +47,13 @@ namespace
|
|||||||
namespace RenderTargetImpl
|
namespace RenderTargetImpl
|
||||||
{
|
{
|
||||||
// Mutex to protect ID generation and our context-RenderTarget-map
|
// Mutex to protect ID generation and our context-RenderTarget-map
|
||||||
sf::Mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
|
|
||||||
// Unique identifier, used for identifying RenderTargets when
|
// Unique identifier, used for identifying RenderTargets when
|
||||||
// tracking the currently active RenderTarget within a given context
|
// tracking the currently active RenderTarget within a given context
|
||||||
sf::Uint64 getUniqueId()
|
sf::Uint64 getUniqueId()
|
||||||
{
|
{
|
||||||
sf::Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
static sf::Uint64 id = 1; // start at 1, zero is "no RenderTarget"
|
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
|
// 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();
|
Uint64 contextId = Context::getActiveContextId();
|
||||||
|
|
||||||
|
@ -28,13 +28,12 @@
|
|||||||
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
|
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
|
||||||
#include <SFML/Graphics/Texture.hpp>
|
#include <SFML/Graphics/Texture.hpp>
|
||||||
#include <SFML/Graphics/GLCheck.hpp>
|
#include <SFML/Graphics/GLCheck.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -53,7 +52,7 @@ namespace
|
|||||||
std::set<std::pair<sf::Uint64, unsigned int> > staleFrameBuffers;
|
std::set<std::pair<sf::Uint64, unsigned int> > staleFrameBuffers;
|
||||||
|
|
||||||
// Mutex to protect both active and stale frame buffer sets
|
// 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
|
// This function is called either when a RenderTextureImplFBO is
|
||||||
// destroyed or via contextDestroyCallback when context destruction
|
// destroyed or via contextDestroyCallback when context destruction
|
||||||
@ -81,7 +80,7 @@ namespace
|
|||||||
// Callback that is called every time a context is destroyed
|
// Callback that is called every time a context is destroyed
|
||||||
void contextDestroyCallback(void* /*arg*/)
|
void contextDestroyCallback(void* /*arg*/)
|
||||||
{
|
{
|
||||||
sf::Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
sf::Uint64 contextId = sf::Context::getActiveContextId();
|
sf::Uint64 contextId = sf::Context::getActiveContextId();
|
||||||
|
|
||||||
@ -125,7 +124,7 @@ m_multisample (false),
|
|||||||
m_stencil (false),
|
m_stencil (false),
|
||||||
m_sRgb (false)
|
m_sRgb (false)
|
||||||
{
|
{
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
// Register the context destruction callback
|
// Register the context destruction callback
|
||||||
registerContextDestroyCallback(contextDestroyCallback, nullptr);
|
registerContextDestroyCallback(contextDestroyCallback, nullptr);
|
||||||
@ -141,7 +140,7 @@ RenderTextureImplFBO::~RenderTextureImplFBO()
|
|||||||
{
|
{
|
||||||
TransientContextLock contextLock;
|
TransientContextLock contextLock;
|
||||||
|
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
// Remove the frame buffer mapping from the set of all active mappings
|
// Remove the frame buffer mapping from the set of all active mappings
|
||||||
frameBuffers.erase(&m_frameBuffers);
|
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
|
// Insert the FBO into our map
|
||||||
m_frameBuffers.emplace(Context::getActiveContextId(), frameBuffer);
|
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
|
// Insert the FBO into our map
|
||||||
m_multisampleFrameBuffers.emplace(Context::getActiveContextId(), multisampleFrameBuffer);
|
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
|
// If none is found, there is no FBO corresponding to the
|
||||||
// currently active context so we will have to create a new FBO
|
// 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;
|
std::unordered_map<Uint64, unsigned int>::iterator it;
|
||||||
|
|
||||||
@ -597,7 +596,7 @@ void RenderTextureImplFBO::updateTexture(unsigned int)
|
|||||||
{
|
{
|
||||||
Uint64 contextId = Context::getActiveContextId();
|
Uint64 contextId = Context::getActiveContextId();
|
||||||
|
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
auto frameBufferIt = m_frameBuffers.find(contextId);
|
auto frameBufferIt = m_frameBuffers.find(contextId);
|
||||||
auto multisampleIt = m_multisampleFrameBuffers.find(contextId);
|
auto multisampleIt = m_multisampleFrameBuffers.find(contextId);
|
||||||
|
@ -33,11 +33,10 @@
|
|||||||
#include <SFML/Graphics/GLCheck.hpp>
|
#include <SFML/Graphics/GLCheck.hpp>
|
||||||
#include <SFML/Window/Context.hpp>
|
#include <SFML/Window/Context.hpp>
|
||||||
#include <SFML/System/InputStream.hpp>
|
#include <SFML/System/InputStream.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
#ifndef SFML_OPENGL_ES
|
#ifndef SFML_OPENGL_ES
|
||||||
@ -56,7 +55,7 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
sf::Mutex isAvailableMutex;
|
std::recursive_mutex isAvailableMutex;
|
||||||
|
|
||||||
GLint checkMaxTextureUnits()
|
GLint checkMaxTextureUnits()
|
||||||
{
|
{
|
||||||
@ -697,7 +696,7 @@ void Shader::bind(const Shader* shader)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Shader::isAvailable()
|
bool Shader::isAvailable()
|
||||||
{
|
{
|
||||||
Lock lock(isAvailableMutex);
|
std::scoped_lock lock(isAvailableMutex);
|
||||||
|
|
||||||
static bool checked = false;
|
static bool checked = false;
|
||||||
static bool available = false;
|
static bool available = false;
|
||||||
@ -725,7 +724,7 @@ bool Shader::isAvailable()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool Shader::isGeometryAvailable()
|
bool Shader::isGeometryAvailable()
|
||||||
{
|
{
|
||||||
Lock lock(isAvailableMutex);
|
std::scoped_lock lock(isAvailableMutex);
|
||||||
|
|
||||||
static bool checked = false;
|
static bool checked = false;
|
||||||
static bool available = false;
|
static bool available = false;
|
||||||
|
@ -31,12 +31,11 @@
|
|||||||
#include <SFML/Graphics/TextureSaver.hpp>
|
#include <SFML/Graphics/TextureSaver.hpp>
|
||||||
#include <SFML/Window/Context.hpp>
|
#include <SFML/Window/Context.hpp>
|
||||||
#include <SFML/Window/Window.hpp>
|
#include <SFML/Window/Window.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -44,14 +43,14 @@ namespace
|
|||||||
// A nested named namespace is used here to allow unity builds of SFML.
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
namespace TextureImpl
|
namespace TextureImpl
|
||||||
{
|
{
|
||||||
sf::Mutex idMutex;
|
std::recursive_mutex idMutex;
|
||||||
sf::Mutex maximumSizeMutex;
|
std::recursive_mutex maximumSizeMutex;
|
||||||
|
|
||||||
// Thread-safe unique identifier generator,
|
// Thread-safe unique identifier generator,
|
||||||
// is used for states cache (see RenderTarget)
|
// is used for states cache (see RenderTarget)
|
||||||
sf::Uint64 getUniqueId()
|
sf::Uint64 getUniqueId()
|
||||||
{
|
{
|
||||||
sf::Lock lock(idMutex);
|
std::scoped_lock lock(idMutex);
|
||||||
|
|
||||||
static sf::Uint64 id = 1; // start at 1, zero is "no texture"
|
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()
|
unsigned int Texture::getMaximumSize()
|
||||||
{
|
{
|
||||||
Lock lock(TextureImpl::maximumSizeMutex);
|
std::scoped_lock lock(TextureImpl::maximumSizeMutex);
|
||||||
|
|
||||||
static bool checked = false;
|
static bool checked = false;
|
||||||
static GLint size = 0;
|
static GLint size = 0;
|
||||||
|
@ -29,17 +29,16 @@
|
|||||||
#include <SFML/Graphics/RenderTarget.hpp>
|
#include <SFML/Graphics/RenderTarget.hpp>
|
||||||
#include <SFML/Graphics/Vertex.hpp>
|
#include <SFML/Graphics/Vertex.hpp>
|
||||||
#include <SFML/Graphics/GLCheck.hpp>
|
#include <SFML/Graphics/GLCheck.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// A nested named namespace is used here to allow unity builds of SFML.
|
// A nested named namespace is used here to allow unity builds of SFML.
|
||||||
namespace VertexBufferImpl
|
namespace VertexBufferImpl
|
||||||
{
|
{
|
||||||
sf::Mutex isAvailableMutex;
|
std::recursive_mutex isAvailableMutex;
|
||||||
|
|
||||||
GLenum usageToGlEnum(sf::VertexBuffer::Usage usage)
|
GLenum usageToGlEnum(sf::VertexBuffer::Usage usage)
|
||||||
{
|
{
|
||||||
@ -336,7 +335,7 @@ VertexBuffer::Usage VertexBuffer::getUsage() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
bool VertexBuffer::isAvailable()
|
bool VertexBuffer::isAvailable()
|
||||||
{
|
{
|
||||||
Lock lock(VertexBufferImpl::isAvailableMutex);
|
std::scoped_lock lock(VertexBufferImpl::isAvailableMutex);
|
||||||
|
|
||||||
static bool checked = false;
|
static bool checked = false;
|
||||||
static bool available = false;
|
static bool available = false;
|
||||||
|
@ -40,13 +40,13 @@
|
|||||||
|
|
||||||
#include <SFML/System/Android/Activity.hpp>
|
#include <SFML/System/Android/Activity.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
#include <SFML/System/Thread.hpp>
|
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <android/window.h>
|
#include <android/window.h>
|
||||||
#include <android/native_activity.h>
|
#include <android/native_activity.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
#define SF_GLAD_EGL_IMPLEMENTATION
|
#define SF_GLAD_EGL_IMPLEMENTATION
|
||||||
#include <glad/egl.h>
|
#include <glad/egl.h>
|
||||||
@ -93,7 +93,7 @@ ActivityStates* retrieveStates(ANativeActivity* activity)
|
|||||||
static void initializeMain(ActivityStates* states)
|
static void initializeMain(ActivityStates* states)
|
||||||
{
|
{
|
||||||
// Protect from concurrent access
|
// Protect from concurrent access
|
||||||
Lock lock(states->mutex);
|
std::scoped_lock lock(states->mutex);
|
||||||
|
|
||||||
// Prepare and share the looper to be read later
|
// Prepare and share the looper to be read later
|
||||||
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
|
||||||
@ -117,7 +117,7 @@ static void initializeMain(ActivityStates* states)
|
|||||||
static void terminateMain(ActivityStates* states)
|
static void terminateMain(ActivityStates* states)
|
||||||
{
|
{
|
||||||
// Protect from concurrent access
|
// 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
|
// The main thread has finished, we must explicitly ask the activity to finish
|
||||||
states->mainOver = true;
|
states->mainOver = true;
|
||||||
@ -138,7 +138,7 @@ void* main(ActivityStates* states)
|
|||||||
terminateMain(states);
|
terminateMain(states);
|
||||||
|
|
||||||
{
|
{
|
||||||
Lock lock(states->mutex);
|
std::scoped_lock lock(states->mutex);
|
||||||
|
|
||||||
states->terminated = true;
|
states->terminated = true;
|
||||||
}
|
}
|
||||||
@ -255,7 +255,7 @@ static void onResume(ANativeActivity* activity)
|
|||||||
{
|
{
|
||||||
// Retrieve our activity states from the activity instance
|
// Retrieve our activity states from the activity instance
|
||||||
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
||||||
sf::Lock lock(states->mutex);
|
std::scoped_lock lock(states->mutex);
|
||||||
|
|
||||||
if (states->fullscreen)
|
if (states->fullscreen)
|
||||||
goToFullscreenMode(activity);
|
goToFullscreenMode(activity);
|
||||||
@ -273,7 +273,7 @@ static void onPause(ANativeActivity* activity)
|
|||||||
{
|
{
|
||||||
// Retrieve our activity states from the activity instance
|
// Retrieve our activity states from the activity instance
|
||||||
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
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
|
// Send an event to warn people the activity has been paused
|
||||||
sf::Event event;
|
sf::Event event;
|
||||||
@ -298,7 +298,7 @@ static void onDestroy(ANativeActivity* activity)
|
|||||||
|
|
||||||
// Send an event to warn people the activity is being destroyed
|
// 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
|
// If the main thread hasn't yet finished, send the event and wait for
|
||||||
// it to finish.
|
// it to finish.
|
||||||
@ -342,7 +342,7 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind
|
|||||||
(void) window;
|
(void) window;
|
||||||
|
|
||||||
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
||||||
sf::Lock lock(states->mutex);
|
std::scoped_lock lock(states->mutex);
|
||||||
|
|
||||||
// Update the activity states
|
// Update the activity states
|
||||||
states->window = window;
|
states->window = window;
|
||||||
@ -369,7 +369,7 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi
|
|||||||
(void) window;
|
(void) window;
|
||||||
|
|
||||||
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
||||||
sf::Lock lock(states->mutex);
|
std::scoped_lock lock(states->mutex);
|
||||||
|
|
||||||
// Update the activity states
|
// Update the activity states
|
||||||
states->window = nullptr;
|
states->window = nullptr;
|
||||||
@ -414,7 +414,7 @@ static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue)
|
|||||||
|
|
||||||
// Attach the input 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);
|
AInputQueue_attachLooper(queue, states->looper, 1, states->processEvent, nullptr);
|
||||||
states->inputQueue = queue;
|
states->inputQueue = queue;
|
||||||
@ -430,7 +430,7 @@ static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
|
|||||||
|
|
||||||
// Detach the input queue
|
// Detach the input queue
|
||||||
{
|
{
|
||||||
sf::Lock lock(states->mutex);
|
std::scoped_lock lock(states->mutex);
|
||||||
|
|
||||||
AInputQueue_detachLooper(queue);
|
AInputQueue_detachLooper(queue);
|
||||||
states->inputQueue = nullptr;
|
states->inputQueue = nullptr;
|
||||||
@ -455,7 +455,7 @@ static void onContentRectChanged(ANativeActivity* activity, const ARect* rect)
|
|||||||
|
|
||||||
// Retrieve our activity states from the activity instance
|
// Retrieve our activity states from the activity instance
|
||||||
sf::priv::ActivityStates* states = sf::priv::retrieveStates(activity);
|
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
|
// Make sure the window still exists before we access the dimensions on it
|
||||||
if (states->window != nullptr) {
|
if (states->window != nullptr) {
|
||||||
@ -568,8 +568,7 @@ JNIEXPORT void ANativeActivity_onCreate(ANativeActivity* activity, void* savedSt
|
|||||||
sf::err().rdbuf(&states->logcat);
|
sf::err().rdbuf(&states->logcat);
|
||||||
|
|
||||||
// Launch the main thread
|
// Launch the main thread
|
||||||
sf::Thread* thread = new sf::Thread(sf::priv::main, states);
|
std::thread(sf::priv::main, states).detach();
|
||||||
thread->launch();
|
|
||||||
|
|
||||||
// Wait for the main thread to be initialized
|
// Wait for the main thread to be initialized
|
||||||
states->mutex.lock();
|
states->mutex.lock();
|
||||||
|
@ -30,13 +30,13 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window/Event.hpp>
|
#include <SFML/Window/Event.hpp>
|
||||||
#include <SFML/Window/EglContext.hpp>
|
#include <SFML/Window/EglContext.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <android/native_activity.h>
|
#include <android/native_activity.h>
|
||||||
#include <android/configuration.h>
|
#include <android/configuration.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class SFML_SYSTEM_API LogcatStream : public std::streambuf
|
class SFML_SYSTEM_API LogcatStream : public std::streambuf
|
||||||
{
|
{
|
||||||
@ -68,7 +68,7 @@ struct ActivityStates
|
|||||||
void* savedState;
|
void* savedState;
|
||||||
size_t savedStateSize;
|
size_t savedStateSize;
|
||||||
|
|
||||||
Mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
|
|
||||||
void (*forwardEvent)(const Event& event);
|
void (*forwardEvent)(const Event& event);
|
||||||
int (*processEvent)(int fd, int events, void* data);
|
int (*processEvent)(int fd, int events, void* data);
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/System/Android/ResourceStream.hpp>
|
#include <SFML/System/Android/ResourceStream.hpp>
|
||||||
#include <SFML/System/Android/Activity.hpp>
|
#include <SFML/System/Android/Activity.hpp>
|
||||||
#include <SFML/System/Lock.hpp>
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
@ -41,7 +41,7 @@ ResourceStream::ResourceStream(const std::string& filename) :
|
|||||||
m_file (nullptr)
|
m_file (nullptr)
|
||||||
{
|
{
|
||||||
ActivityStates& states = getActivity();
|
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);
|
m_file = AAssetManager_open(states.activity->assetManager, filename.c_str(), AASSET_MODE_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,10 +10,6 @@ set(SRC
|
|||||||
${INCROOT}/Err.hpp
|
${INCROOT}/Err.hpp
|
||||||
${INCROOT}/Export.hpp
|
${INCROOT}/Export.hpp
|
||||||
${INCROOT}/InputStream.hpp
|
${INCROOT}/InputStream.hpp
|
||||||
${SRCROOT}/Lock.cpp
|
|
||||||
${INCROOT}/Lock.hpp
|
|
||||||
${SRCROOT}/Mutex.cpp
|
|
||||||
${INCROOT}/Mutex.hpp
|
|
||||||
${INCROOT}/NativeActivity.hpp
|
${INCROOT}/NativeActivity.hpp
|
||||||
${INCROOT}/NonCopyable.hpp
|
${INCROOT}/NonCopyable.hpp
|
||||||
${SRCROOT}/Sleep.cpp
|
${SRCROOT}/Sleep.cpp
|
||||||
@ -21,13 +17,6 @@ set(SRC
|
|||||||
${SRCROOT}/String.cpp
|
${SRCROOT}/String.cpp
|
||||||
${INCROOT}/String.hpp
|
${INCROOT}/String.hpp
|
||||||
${INCROOT}/String.inl
|
${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
|
${SRCROOT}/Time.cpp
|
||||||
${INCROOT}/Time.hpp
|
${INCROOT}/Time.hpp
|
||||||
${INCROOT}/Utf.hpp
|
${INCROOT}/Utf.hpp
|
||||||
@ -48,28 +37,16 @@ if(SFML_OS_WINDOWS)
|
|||||||
set(PLATFORM_SRC
|
set(PLATFORM_SRC
|
||||||
${SRCROOT}/Win32/ClockImpl.cpp
|
${SRCROOT}/Win32/ClockImpl.cpp
|
||||||
${SRCROOT}/Win32/ClockImpl.hpp
|
${SRCROOT}/Win32/ClockImpl.hpp
|
||||||
${SRCROOT}/Win32/MutexImpl.cpp
|
|
||||||
${SRCROOT}/Win32/MutexImpl.hpp
|
|
||||||
${SRCROOT}/Win32/SleepImpl.cpp
|
${SRCROOT}/Win32/SleepImpl.cpp
|
||||||
${SRCROOT}/Win32/SleepImpl.hpp
|
${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})
|
source_group("windows" FILES ${PLATFORM_SRC})
|
||||||
else()
|
else()
|
||||||
set(PLATFORM_SRC
|
set(PLATFORM_SRC
|
||||||
${SRCROOT}/Unix/ClockImpl.cpp
|
${SRCROOT}/Unix/ClockImpl.cpp
|
||||||
${SRCROOT}/Unix/ClockImpl.hpp
|
${SRCROOT}/Unix/ClockImpl.hpp
|
||||||
${SRCROOT}/Unix/MutexImpl.cpp
|
|
||||||
${SRCROOT}/Unix/MutexImpl.hpp
|
|
||||||
${SRCROOT}/Unix/SleepImpl.cpp
|
${SRCROOT}/Unix/SleepImpl.cpp
|
||||||
${SRCROOT}/Unix/SleepImpl.hpp
|
${SRCROOT}/Unix/SleepImpl.hpp
|
||||||
${SRCROOT}/Unix/ThreadImpl.cpp
|
|
||||||
${SRCROOT}/Unix/ThreadImpl.hpp
|
|
||||||
${SRCROOT}/Unix/ThreadLocalImpl.cpp
|
|
||||||
${SRCROOT}/Unix/ThreadLocalImpl.hpp
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if(SFML_OS_ANDROID)
|
if(SFML_OS_ANDROID)
|
||||||
@ -98,6 +75,7 @@ endif()
|
|||||||
if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX)
|
if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX)
|
||||||
target_link_libraries(sfml-system PRIVATE pthread)
|
target_link_libraries(sfml-system PRIVATE pthread)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(SFML_OS_LINUX)
|
if(SFML_OS_LINUX)
|
||||||
target_link_libraries(sfml-system PRIVATE rt)
|
target_link_libraries(sfml-system PRIVATE rt)
|
||||||
elseif(SFML_OS_WINDOWS)
|
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
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/System/Win32/ClockImpl.hpp>
|
#include <SFML/System/Win32/ClockImpl.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
#include <mutex>
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
|
||||||
@ -65,10 +64,10 @@ Time ClockImpl::getCurrentTime()
|
|||||||
|
|
||||||
if (oldWindows)
|
if (oldWindows)
|
||||||
{
|
{
|
||||||
static sf::Mutex oldWindowsMutex;
|
static std::recursive_mutex oldWindowsMutex;
|
||||||
|
|
||||||
// Acquire a lock (CRITICAL_SECTION) to prevent travelling back in time
|
// Acquire a lock (CRITICAL_SECTION) to prevent travelling back in time
|
||||||
Lock lock(oldWindowsMutex);
|
std::scoped_lock lock(oldWindowsMutex);
|
||||||
|
|
||||||
// Get the current time
|
// Get the current time
|
||||||
QueryPerformanceCounter(&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/Window/Android/InputImpl.hpp>
|
||||||
#include <SFML/System/Android/Activity.hpp>
|
#include <SFML/System/Android/Activity.hpp>
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <mutex>
|
||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
|
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ void InputImpl::setVirtualKeyboardVisible(bool visible)
|
|||||||
// todo: Check if the window is active
|
// todo: Check if the window is active
|
||||||
|
|
||||||
ActivityStates& states = getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
// Initializes JNI
|
// Initializes JNI
|
||||||
jint lResult;
|
jint lResult;
|
||||||
@ -138,8 +138,8 @@ bool InputImpl::isMouseButtonPressed(Mouse::Button button)
|
|||||||
{
|
{
|
||||||
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
priv::ActivityStates& states = priv::getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
return states.isButtonPressed[button];
|
return states.isButtonPressed[button];
|
||||||
}
|
}
|
||||||
@ -150,8 +150,8 @@ Vector2i InputImpl::getMousePosition()
|
|||||||
{
|
{
|
||||||
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
priv::ActivityStates& states = priv::getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
return states.mousePosition;
|
return states.mousePosition;
|
||||||
}
|
}
|
||||||
@ -183,8 +183,8 @@ bool InputImpl::isTouchDown(unsigned int finger)
|
|||||||
{
|
{
|
||||||
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
priv::ActivityStates& states = priv::getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
return states.touchEvents.find(finger) != states.touchEvents.end();
|
return states.touchEvents.find(finger) != states.touchEvents.end();
|
||||||
}
|
}
|
||||||
@ -195,8 +195,8 @@ Vector2i InputImpl::getTouchPosition(unsigned int finger)
|
|||||||
{
|
{
|
||||||
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
priv::ActivityStates& states = priv::getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
return states.touchEvents.find(finger)->second;
|
return states.touchEvents.find(finger)->second;
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include <SFML/System/Android/Activity.hpp>
|
#include <SFML/System/Android/Activity.hpp>
|
||||||
#include <SFML/System/Vector2.hpp>
|
#include <SFML/System/Vector2.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
#include <SFML/System/Lock.hpp>
|
#include <mutex>
|
||||||
|
|
||||||
namespace sf
|
namespace sf
|
||||||
{
|
{
|
||||||
@ -53,7 +53,7 @@ VideoMode VideoModeImpl::getDesktopMode()
|
|||||||
{
|
{
|
||||||
// Get the activity states
|
// Get the activity states
|
||||||
priv::ActivityStates& states = priv::getActivity();
|
priv::ActivityStates& states = priv::getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
return VideoMode(states.screenSize.x, states.screenSize.y);
|
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/WindowStyle.hpp> // important to be included first (conflict with None)
|
||||||
#include <SFML/Window/Android/WindowImplAndroid.hpp>
|
#include <SFML/Window/Android/WindowImplAndroid.hpp>
|
||||||
#include <SFML/Window/Event.hpp>
|
#include <SFML/Window/Event.hpp>
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <mutex>
|
||||||
#include <android/looper.h>
|
#include <android/looper.h>
|
||||||
|
|
||||||
// Define missing constants for older API levels
|
// Define missing constants for older API levels
|
||||||
@ -65,8 +65,8 @@ WindowImplAndroid::WindowImplAndroid(VideoMode mode, const String& title, unsign
|
|||||||
, m_windowBeingDestroyed(false)
|
, m_windowBeingDestroyed(false)
|
||||||
, m_hasFocus(false)
|
, m_hasFocus(false)
|
||||||
{
|
{
|
||||||
priv::ActivityStates& states = priv::getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
if (style& Style::Fullscreen)
|
if (style& Style::Fullscreen)
|
||||||
states.fullscreen = true;
|
states.fullscreen = true;
|
||||||
@ -92,7 +92,7 @@ WindowImplAndroid::~WindowImplAndroid()
|
|||||||
WindowHandle WindowImplAndroid::getSystemHandle() const
|
WindowHandle WindowImplAndroid::getSystemHandle() const
|
||||||
{
|
{
|
||||||
ActivityStates& states = getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
return states.window;
|
return states.window;
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ void WindowImplAndroid::processEvents()
|
|||||||
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
ALooper_pollAll(0, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
ActivityStates& states = getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
if (m_windowBeingCreated)
|
if (m_windowBeingCreated)
|
||||||
{
|
{
|
||||||
@ -243,7 +243,7 @@ void WindowImplAndroid::forwardEvent(const Event& event)
|
|||||||
int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
int WindowImplAndroid::processEvent(int fd, int events, void* data)
|
||||||
{
|
{
|
||||||
ActivityStates& states = getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
AInputEvent* _event = nullptr;
|
AInputEvent* _event = nullptr;
|
||||||
|
|
||||||
@ -680,7 +680,7 @@ int WindowImplAndroid::getUnicode(AInputEvent* event)
|
|||||||
{
|
{
|
||||||
// Retrieve activity states
|
// Retrieve activity states
|
||||||
ActivityStates& states = getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
// Initializes JNI
|
// Initializes JNI
|
||||||
jint lResult;
|
jint lResult;
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/Window/Context.hpp>
|
#include <SFML/Window/Context.hpp>
|
||||||
#include <SFML/Window/GlContext.hpp>
|
#include <SFML/Window/GlContext.hpp>
|
||||||
#include <SFML/System/ThreadLocalPtr.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +36,7 @@ namespace
|
|||||||
namespace ContextImpl
|
namespace ContextImpl
|
||||||
{
|
{
|
||||||
// This per-thread variable holds the current context for each thread
|
// 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/Window/WindowImpl.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
#include <mutex>
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#ifdef SFML_SYSTEM_ANDROID
|
#ifdef SFML_SYSTEM_ANDROID
|
||||||
#include <SFML/System/Android/Activity.hpp>
|
#include <SFML/System/Android/Activity.hpp>
|
||||||
#endif
|
#endif
|
||||||
@ -58,7 +57,7 @@ namespace
|
|||||||
|
|
||||||
// On Android, its native activity handles this for us
|
// On Android, its native activity handles this for us
|
||||||
sf::priv::ActivityStates& states = sf::priv::getActivity();
|
sf::priv::ActivityStates& states = sf::priv::getActivity();
|
||||||
sf::Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
return states.display;
|
return states.display;
|
||||||
|
|
||||||
@ -144,7 +143,7 @@ m_config (nullptr)
|
|||||||
|
|
||||||
// On Android, we must save the created context
|
// On Android, we must save the created context
|
||||||
ActivityStates& states = getActivity();
|
ActivityStates& states = getActivity();
|
||||||
Lock lock(states.mutex);
|
std::scoped_lock lock(states.mutex);
|
||||||
|
|
||||||
states.context = this;
|
states.context = this;
|
||||||
|
|
||||||
|
@ -28,9 +28,6 @@
|
|||||||
#include <SFML/Window/GlContext.hpp>
|
#include <SFML/Window/GlContext.hpp>
|
||||||
#include <SFML/Window/Context.hpp>
|
#include <SFML/Window/Context.hpp>
|
||||||
#include <SFML/Window/EglContext.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 <SFML/System/Err.hpp>
|
||||||
#include <glad/gl.h>
|
#include <glad/gl.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -42,6 +39,8 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <mutex>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
|
||||||
#if defined(SFML_SYSTEM_WINDOWS)
|
#if defined(SFML_SYSTEM_WINDOWS)
|
||||||
@ -158,13 +157,13 @@ namespace
|
|||||||
// This mutex is also used to protect the shared context
|
// This mutex is also used to protect the shared context
|
||||||
// from being locked on multiple threads and for managing
|
// from being locked on multiple threads and for managing
|
||||||
// the resource count
|
// the resource count
|
||||||
sf::Mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
|
|
||||||
// OpenGL resources counter
|
// OpenGL resources counter
|
||||||
unsigned int resourceCount = 0;
|
unsigned int resourceCount = 0;
|
||||||
|
|
||||||
// This per-thread variable holds the current context for each thread
|
// 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
|
// The hidden, inactive context that will be shared with all other contexts
|
||||||
ContextType* sharedContext = nullptr;
|
ContextType* sharedContext = nullptr;
|
||||||
@ -190,7 +189,7 @@ namespace
|
|||||||
TransientContext() :
|
TransientContext() :
|
||||||
referenceCount (0),
|
referenceCount (0),
|
||||||
context (nullptr),
|
context (nullptr),
|
||||||
sharedContextLock(nullptr),
|
sharedContextLock(),
|
||||||
useSharedContext (false)
|
useSharedContext (false)
|
||||||
{
|
{
|
||||||
if (resourceCount == 0)
|
if (resourceCount == 0)
|
||||||
@ -199,7 +198,7 @@ namespace
|
|||||||
}
|
}
|
||||||
else if (!currentContext)
|
else if (!currentContext)
|
||||||
{
|
{
|
||||||
sharedContextLock = new sf::Lock(mutex);
|
sharedContextLock.emplace(mutex);
|
||||||
useSharedContext = true;
|
useSharedContext = true;
|
||||||
sharedContext->setActive(true);
|
sharedContext->setActive(true);
|
||||||
}
|
}
|
||||||
@ -214,7 +213,7 @@ namespace
|
|||||||
if (useSharedContext)
|
if (useSharedContext)
|
||||||
sharedContext->setActive(false);
|
sharedContext->setActive(false);
|
||||||
|
|
||||||
delete sharedContextLock;
|
sharedContextLock.reset();
|
||||||
delete context;
|
delete context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,13 +222,13 @@ namespace
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
unsigned int referenceCount;
|
unsigned int referenceCount;
|
||||||
sf::Context* context;
|
sf::Context* context;
|
||||||
sf::Lock* sharedContextLock;
|
std::optional<std::scoped_lock<std::recursive_mutex>> sharedContextLock;
|
||||||
bool useSharedContext;
|
bool useSharedContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This per-thread variable tracks if and how a transient
|
// This per-thread variable tracks if and how a transient
|
||||||
// context is currently being used on the current thread
|
// context is currently being used on the current thread
|
||||||
sf::ThreadLocalPtr<TransientContext> transientContext(nullptr);
|
thread_local TransientContext* transientContext(nullptr);
|
||||||
|
|
||||||
// Supported OpenGL extensions
|
// Supported OpenGL extensions
|
||||||
std::vector<std::string> extensions;
|
std::vector<std::string> extensions;
|
||||||
@ -322,7 +321,7 @@ void GlContext::initResource()
|
|||||||
using GlContextImpl::loadExtensions;
|
using GlContextImpl::loadExtensions;
|
||||||
|
|
||||||
// Protect from concurrent access
|
// 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 this is the very first resource, trigger the global context initialization
|
||||||
if (resourceCount == 0)
|
if (resourceCount == 0)
|
||||||
@ -359,7 +358,7 @@ void GlContext::cleanupResource()
|
|||||||
using GlContextImpl::sharedContext;
|
using GlContextImpl::sharedContext;
|
||||||
|
|
||||||
// Protect from concurrent access
|
// Protect from concurrent access
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
// Decrement the resources counter
|
// Decrement the resources counter
|
||||||
resourceCount--;
|
resourceCount--;
|
||||||
@ -392,7 +391,7 @@ void GlContext::acquireTransientContext()
|
|||||||
using GlContextImpl::transientContext;
|
using GlContextImpl::transientContext;
|
||||||
|
|
||||||
// Protect from concurrent access
|
// Protect from concurrent access
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
// If this is the first TransientContextLock on this thread
|
// If this is the first TransientContextLock on this thread
|
||||||
// construct the state object
|
// construct the state object
|
||||||
@ -411,7 +410,7 @@ void GlContext::releaseTransientContext()
|
|||||||
using GlContextImpl::transientContext;
|
using GlContextImpl::transientContext;
|
||||||
|
|
||||||
// Protect from concurrent access
|
// Protect from concurrent access
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
// Make sure a matching acquireTransientContext() was called
|
// Make sure a matching acquireTransientContext() was called
|
||||||
assert(transientContext);
|
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)
|
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||||
assert(sharedContext != nullptr);
|
assert(sharedContext != nullptr);
|
||||||
|
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
GlContext* context = nullptr;
|
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)
|
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||||
assert(sharedContext != nullptr);
|
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
|
// 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
|
// 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)
|
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
|
||||||
assert(sharedContext != nullptr);
|
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
|
// 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
|
// 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)
|
GlFunctionPointer GlContext::getFunction(const char* name)
|
||||||
{
|
{
|
||||||
Lock lock(GlContextImpl::mutex);
|
std::scoped_lock lock(GlContextImpl::mutex);
|
||||||
|
|
||||||
return ContextType::getFunction(name);
|
return ContextType::getFunction(name);
|
||||||
}
|
}
|
||||||
@ -632,7 +631,7 @@ bool GlContext::setActive(bool active)
|
|||||||
{
|
{
|
||||||
if (this != currentContext)
|
if (this != currentContext)
|
||||||
{
|
{
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
// Activate the context
|
// Activate the context
|
||||||
if (makeCurrent(true))
|
if (makeCurrent(true))
|
||||||
@ -656,7 +655,7 @@ bool GlContext::setActive(bool active)
|
|||||||
{
|
{
|
||||||
if (this == currentContext)
|
if (this == currentContext)
|
||||||
{
|
{
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
// Deactivate the context
|
// Deactivate the context
|
||||||
if (makeCurrent(false))
|
if (makeCurrent(false))
|
||||||
|
@ -26,13 +26,12 @@
|
|||||||
// Headers
|
// Headers
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/Window/Unix/Display.hpp>
|
#include <SFML/Window/Unix/Display.hpp>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@ -42,7 +41,7 @@ namespace
|
|||||||
unsigned int referenceCount = 0;
|
unsigned int referenceCount = 0;
|
||||||
XIM sharedXIM = NULL;
|
XIM sharedXIM = NULL;
|
||||||
unsigned int referenceCountXIM = 0;
|
unsigned int referenceCountXIM = 0;
|
||||||
sf::Mutex mutex;
|
std::recursive_mutex mutex;
|
||||||
|
|
||||||
using AtomMap = std::unordered_map<std::string, Atom>;
|
using AtomMap = std::unordered_map<std::string, Atom>;
|
||||||
AtomMap atoms;
|
AtomMap atoms;
|
||||||
@ -55,7 +54,7 @@ namespace priv
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Display* OpenDisplay()
|
Display* OpenDisplay()
|
||||||
{
|
{
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
if (referenceCount == 0)
|
if (referenceCount == 0)
|
||||||
{
|
{
|
||||||
@ -78,7 +77,7 @@ Display* OpenDisplay()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void CloseDisplay(Display* display)
|
void CloseDisplay(Display* display)
|
||||||
{
|
{
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
assert(display == sharedDisplay);
|
assert(display == sharedDisplay);
|
||||||
|
|
||||||
@ -90,7 +89,7 @@ void CloseDisplay(Display* display)
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
XIM OpenXIM()
|
XIM OpenXIM()
|
||||||
{
|
{
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
assert(sharedDisplay != nullptr);
|
assert(sharedDisplay != nullptr);
|
||||||
|
|
||||||
@ -128,7 +127,7 @@ XIM OpenXIM()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void CloseXIM(XIM xim)
|
void CloseXIM(XIM xim)
|
||||||
{
|
{
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
assert(xim == sharedXIM);
|
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/WindowImplX11.hpp> // important to be included first (conflict with None)
|
||||||
#include <SFML/Window/Unix/GlxContext.hpp>
|
#include <SFML/Window/Unix/GlxContext.hpp>
|
||||||
#include <SFML/Window/Unix/Display.hpp>
|
#include <SFML/Window/Unix/Display.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// We check for this definition in order to avoid multiple definitions of GLAD
|
// We check for this definition in order to avoid multiple definitions of GLAD
|
||||||
@ -48,7 +47,7 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
sf::Mutex glxErrorMutex;
|
std::recursive_mutex glxErrorMutex;
|
||||||
bool glxErrorOccurred = false;
|
bool glxErrorOccurred = false;
|
||||||
|
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sf::Lock m_lock;
|
std::scoped_lock<std::recursive_mutex> m_lock;
|
||||||
::Display* m_display;
|
::Display* m_display;
|
||||||
int (*m_previousHandler)(::Display*, XErrorEvent*);
|
int (*m_previousHandler)(::Display*, XErrorEvent*);
|
||||||
};
|
};
|
||||||
|
@ -31,10 +31,12 @@
|
|||||||
#include <SFML/Window/Unix/InputImpl.hpp>
|
#include <SFML/Window/Unix/InputImpl.hpp>
|
||||||
#include <SFML/System/Utf.hpp>
|
#include <SFML/System/Utf.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
#include <SFML/System/Mutex.hpp>
|
|
||||||
#include <SFML/System/Lock.hpp>
|
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
|
|
||||||
#include <X11/Xlibint.h>
|
#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/Xutil.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
@ -49,6 +51,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#ifdef SFML_OPENGL_ES
|
#ifdef SFML_OPENGL_ES
|
||||||
#include <SFML/Window/EglContext.hpp>
|
#include <SFML/Window/EglContext.hpp>
|
||||||
@ -68,7 +71,7 @@ namespace
|
|||||||
{
|
{
|
||||||
sf::priv::WindowImplX11* fullscreenWindow = nullptr;
|
sf::priv::WindowImplX11* fullscreenWindow = nullptr;
|
||||||
std::vector<sf::priv::WindowImplX11*> allWindows;
|
std::vector<sf::priv::WindowImplX11*> allWindows;
|
||||||
sf::Mutex allWindowsMutex;
|
std::recursive_mutex allWindowsMutex;
|
||||||
sf::String windowManagerName;
|
sf::String windowManagerName;
|
||||||
|
|
||||||
sf::String wmAbsPosGood[] = { "Enlightenment", "FVWM", "i3" };
|
sf::String wmAbsPosGood[] = { "Enlightenment", "FVWM", "i3" };
|
||||||
@ -811,7 +814,7 @@ WindowImplX11::~WindowImplX11()
|
|||||||
CloseDisplay(m_display);
|
CloseDisplay(m_display);
|
||||||
|
|
||||||
// Remove this window from the global list of windows (required for focus request)
|
// 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));
|
allWindows.erase(std::find(allWindows.begin(), allWindows.end(), this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1201,7 +1204,7 @@ void WindowImplX11::requestFocus()
|
|||||||
bool sfmlWindowFocused = false;
|
bool sfmlWindowFocused = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
Lock lock(allWindowsMutex);
|
std::scoped_lock lock(allWindowsMutex);
|
||||||
for (sf::priv::WindowImplX11* windowPtr : allWindows)
|
for (sf::priv::WindowImplX11* windowPtr : allWindows)
|
||||||
{
|
{
|
||||||
if (windowPtr->hasFocus())
|
if (windowPtr->hasFocus())
|
||||||
@ -1658,7 +1661,7 @@ void WindowImplX11::initialize()
|
|||||||
XFlush(m_display);
|
XFlush(m_display);
|
||||||
|
|
||||||
// Add this window to the global list of windows (required for focus request)
|
// 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);
|
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/WindowImpl.hpp> // included first to avoid a warning about macro redefinition
|
||||||
#include <SFML/Window/Win32/WglContext.hpp>
|
#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 <SFML/System/Err.hpp>
|
||||||
|
#include <mutex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -48,7 +46,7 @@ namespace
|
|||||||
{
|
{
|
||||||
// Some drivers are bugged and don't track the current HDC/HGLRC properly
|
// 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
|
// 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)
|
if (sharedContext)
|
||||||
{
|
{
|
||||||
static Mutex mutex;
|
static std::recursive_mutex mutex;
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
if (WglContextImpl::currentContext == shared)
|
if (WglContextImpl::currentContext == shared)
|
||||||
{
|
{
|
||||||
@ -718,8 +716,8 @@ void WglContext::createContext(WglContext* shared)
|
|||||||
if (sharedContext)
|
if (sharedContext)
|
||||||
{
|
{
|
||||||
// wglShareLists doesn't seem to be thread-safe
|
// wglShareLists doesn't seem to be thread-safe
|
||||||
static Mutex mutex;
|
static std::recursive_mutex mutex;
|
||||||
Lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
if (WglContextImpl::currentContext == shared)
|
if (WglContextImpl::currentContext == shared)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user