Replaced some mutex locks with atomic variables.

Also removed an SDL audio issue workaround from AudioManager.
This commit is contained in:
Leon Styhre 2021-11-16 17:49:05 +01:00
parent 7f5fe3fcbf
commit 9937476e18
14 changed files with 51 additions and 169 deletions

View file

@ -194,9 +194,7 @@ void AudioManager::mixAudio(void* /*unused*/, Uint8* stream, int len)
// stream is not played when the video player has been stopped. Otherwise there would // stream is not played when the video player has been stopped. Otherwise there would
// be a short time period when the audio would keep playing after the video was stopped // be a short time period when the audio would keep playing after the video was stopped
// and before the stream was cleared in clearStream(). // and before the stream was cleared in clearStream().
std::unique_lock<std::mutex> audioLock{mAudioLock};
bool muteStream = sMuteStream; bool muteStream = sMuteStream;
audioLock.unlock();
if (muteStream) { if (muteStream) {
SDL_MixAudioFormat(stream, &converted.at(0), sAudioFormat.format, processedLength, 0); SDL_MixAudioFormat(stream, &converted.at(0), sAudioFormat.format, processedLength, 0);
} }
@ -290,41 +288,4 @@ void AudioManager::clearStream()
SDL_LockAudioDevice(sAudioDevice); SDL_LockAudioDevice(sAudioDevice);
SDL_AudioStreamClear(sConversionStream); SDL_AudioStreamClear(sConversionStream);
SDL_UnlockAudioDevice(sAudioDevice); SDL_UnlockAudioDevice(sAudioDevice);
// TEMPORARY: For evaluating if SDL_AudioStreamClear is stable.
return;
// If sSoundVector is empty it means we are shutting down. In this case don't attempt
// to clear the stream as this could lead to a crash.
if (sSoundVector.empty())
return;
SDL_LockAudioDevice(sAudioDevice);
// This code is required as there's seemingly a bug in SDL_AudioStreamAvailable().
// The function sometimes returns 0 even if there is data left in the buffer, possibly
// because the remaining data is less than the configured sample size. It happens almost
// permanently on NetBSD but also on at least Linux from time to time. Adding some data
// to the stream buffer to get above this threshold before calling the function will
// return the proper number. So adding 10000 as we do here would give a return value of
// for instance 10880 instead of 0, assuming there were 880 bytes of data left in the buffer.
// Fortunately the SDL_AudioStreamGet() function acts correctly on any arbitrary sample size
// so we can actually clear the entire buffer. If this workaround was not implemented, there
// would be a sound glitch when some samples from the previous video would play any time a
// new video was started (assuming the issue was triggered by some remaining stream data).
std::vector<Uint8> writeBuffer(10000);
if (SDL_AudioStreamPut(sConversionStream, reinterpret_cast<const void*>(&writeBuffer.at(0)),
10000) == -1) {
LOG(LogError) << "Failed to put samples in the conversion stream:";
LOG(LogError) << SDL_GetError();
SDL_UnlockAudioDevice(sAudioDevice);
return;
}
int length = SDL_AudioStreamAvailable(sConversionStream);
std::vector<Uint8> readBuffer(length);
SDL_AudioStreamGet(sConversionStream, static_cast<void*>(&readBuffer.at(0)), length);
SDL_UnlockAudioDevice(sAudioDevice);
} }

View file

@ -10,8 +10,8 @@
#define ES_CORE_AUDIO_MANAGER_H #define ES_CORE_AUDIO_MANAGER_H
#include <SDL2/SDL_audio.h> #include <SDL2/SDL_audio.h>
#include <atomic>
#include <memory> #include <memory>
#include <mutex>
#include <vector> #include <vector>
class Sound; class Sound;
@ -36,16 +36,8 @@ public:
void processStream(const void* samples, unsigned count); void processStream(const void* samples, unsigned count);
void clearStream(); void clearStream();
void muteStream() void muteStream() { sMuteStream = true; }
{ void unmuteStream() { sMuteStream = false; }
std::unique_lock<std::mutex> audioLock{mAudioLock};
sMuteStream = true;
}
void unmuteStream()
{
std::unique_lock<std::mutex> audioLock{mAudioLock};
sMuteStream = false;
}
bool getHasAudioDevice() { return sHasAudioDevice; } bool getHasAudioDevice() { return sHasAudioDevice; }
@ -58,10 +50,9 @@ private:
static void mixAudio(void* unused, Uint8* stream, int len); static void mixAudio(void* unused, Uint8* stream, int len);
static void mixAudio2(void* unused, Uint8* stream, int len); static void mixAudio2(void* unused, Uint8* stream, int len);
inline static std::mutex mAudioLock;
inline static SDL_AudioStream* sConversionStream; inline static SDL_AudioStream* sConversionStream;
inline static std::vector<std::shared_ptr<Sound>> sSoundVector; inline static std::vector<std::shared_ptr<Sound>> sSoundVector;
inline static bool sMuteStream = false; inline static std::atomic<bool> sMuteStream = false;
inline static bool sHasAudioDevice = true; inline static bool sHasAudioDevice = true;
}; };

View file

@ -151,8 +151,6 @@ void Sound::play()
SDL_LockAudioDevice(AudioManager::sAudioDevice); SDL_LockAudioDevice(AudioManager::sAudioDevice);
std::unique_lock<std::mutex> playerLock(mMutex);
if (mPlaying) if (mPlaying)
// Replay from start. rewind the sample to the beginning. // Replay from start. rewind the sample to the beginning.
mSamplePos = 0; mSamplePos = 0;
@ -160,8 +158,6 @@ void Sound::play()
// Flag our sample as playing. // Flag our sample as playing.
mPlaying = true; mPlaying = true;
playerLock.unlock();
SDL_UnlockAudioDevice(AudioManager::sAudioDevice); SDL_UnlockAudioDevice(AudioManager::sAudioDevice);
// Tell the AudioManager to start playing samples. // Tell the AudioManager to start playing samples.
AudioManager::getInstance().play(); AudioManager::getInstance().play();
@ -171,7 +167,6 @@ void Sound::stop()
{ {
// Flag our sample as not playing and rewind its position. // Flag our sample as not playing and rewind its position.
SDL_LockAudioDevice(AudioManager::sAudioDevice); SDL_LockAudioDevice(AudioManager::sAudioDevice);
std::unique_lock<std::mutex> playerLock(mMutex);
mPlaying = false; mPlaying = false;
mSamplePos = 0; mSamplePos = 0;
SDL_UnlockAudioDevice(AudioManager::sAudioDevice); SDL_UnlockAudioDevice(AudioManager::sAudioDevice);
@ -182,7 +177,6 @@ void Sound::setPosition(Uint32 newPosition)
mSamplePos = newPosition; mSamplePos = newPosition;
if (mSamplePos >= mSampleLength) { if (mSamplePos >= mSampleLength) {
// Got to or beyond the end of the sample. stop playing. // Got to or beyond the end of the sample. stop playing.
std::unique_lock<std::mutex> playerLock(mMutex);
mPlaying = false; mPlaying = false;
mSamplePos = 0; mSamplePos = 0;
} }

View file

@ -11,9 +11,9 @@
#define ES_CORE_SOUND_H #define ES_CORE_SOUND_H
#include <SDL2/SDL_audio.h> #include <SDL2/SDL_audio.h>
#include <atomic>
#include <map> #include <map>
#include <memory> #include <memory>
#include <mutex>
#include <sstream> #include <sstream>
#include <string> #include <string>
#include <vector> #include <vector>
@ -31,11 +31,7 @@ public:
void loadFile(const std::string& path); void loadFile(const std::string& path);
void play(); void play();
bool isPlaying() const bool isPlaying() const { return mPlaying; }
{
std::unique_lock<std::mutex> playerLock(mMutex);
return mPlaying;
}
void stop(); void stop();
const Uint8* getData() const { return mSampleData; } const Uint8* getData() const { return mSampleData; }
@ -51,14 +47,13 @@ public:
private: private:
Sound(const std::string& path = ""); Sound(const std::string& path = "");
inline static std::mutex mMutex;
static std::map<std::string, std::shared_ptr<Sound>> sMap; static std::map<std::string, std::shared_ptr<Sound>> sMap;
std::string mPath; std::string mPath;
SDL_AudioSpec mSampleFormat; SDL_AudioSpec mSampleFormat;
Uint8* mSampleData; Uint8* mSampleData;
Uint32 mSamplePos; Uint32 mSamplePos;
Uint32 mSampleLength; Uint32 mSampleLength;
bool mPlaying; std::atomic<bool> mPlaying;
}; };
enum NavigationSoundsID { enum NavigationSoundsID {

View file

@ -799,26 +799,14 @@ void Window::closeLaunchScreen()
mRenderLaunchScreen = false; mRenderLaunchScreen = false;
} }
void Window::increaseVideoPlayerCount() void Window::increaseVideoPlayerCount() { mVideoPlayerCount++; }
{
mVideoCountMutex.lock();
mVideoPlayerCount++;
mVideoCountMutex.unlock();
}
void Window::decreaseVideoPlayerCount() void Window::decreaseVideoPlayerCount() { mVideoPlayerCount--; }
{
mVideoCountMutex.lock();
mVideoPlayerCount--;
mVideoCountMutex.unlock();
}
int Window::getVideoPlayerCount() int Window::getVideoPlayerCount()
{ {
int videoPlayerCount; int videoPlayerCount;
mVideoCountMutex.lock();
videoPlayerCount = mVideoPlayerCount; videoPlayerCount = mVideoPlayerCount;
mVideoCountMutex.unlock();
return videoPlayerCount; return videoPlayerCount;
} }

View file

@ -16,8 +16,8 @@
#include "Settings.h" #include "Settings.h"
#include "resources/TextureResource.h" #include "resources/TextureResource.h"
#include <atomic>
#include <memory> #include <memory>
#include <mutex>
#include <queue> #include <queue>
class FileData; class FileData;
@ -192,8 +192,7 @@ private:
bool mCachedBackground; bool mCachedBackground;
bool mInvalidatedCachedBackground; bool mInvalidatedCachedBackground;
int mVideoPlayerCount; std::atomic<int> mVideoPlayerCount;
std::mutex mVideoCountMutex;
float mTopScale; float mTopScale;
bool mRenderedHelpPrompts; bool mRenderedHelpPrompts;

View file

@ -90,12 +90,9 @@ void VideoComponent::setImage(std::string path)
void VideoComponent::onShow() void VideoComponent::onShow()
{ {
std::unique_lock<std::mutex> playerLock(mPlayerMutex);
mBlockPlayer = false; mBlockPlayer = false;
mPause = false; mPause = false;
mShowing = true; mShowing = true;
playerLock.unlock();
manageState(); manageState();
} }
@ -113,30 +110,22 @@ void VideoComponent::onStopVideo()
void VideoComponent::onPauseVideo() void VideoComponent::onPauseVideo()
{ {
std::unique_lock<std::mutex> playerLock(mPlayerMutex);
mBlockPlayer = true; mBlockPlayer = true;
mPause = true; mPause = true;
playerLock.unlock();
manageState(); manageState();
} }
void VideoComponent::onUnpauseVideo() void VideoComponent::onUnpauseVideo()
{ {
std::unique_lock<std::mutex> playerLock(mPlayerMutex);
mBlockPlayer = false; mBlockPlayer = false;
mPause = false; mPause = false;
playerLock.unlock();
manageState(); manageState();
} }
void VideoComponent::onScreensaverActivate() void VideoComponent::onScreensaverActivate()
{ {
std::unique_lock<std::mutex> playerLock(mPlayerMutex);
mBlockPlayer = true; mBlockPlayer = true;
mPause = true; mPause = true;
playerLock.unlock();
if (Settings::getInstance()->getString("ScreensaverType") == "dim") if (Settings::getInstance()->getString("ScreensaverType") == "dim")
stopVideo(); stopVideo();
@ -170,20 +159,16 @@ void VideoComponent::onGameLaunchedDeactivate()
void VideoComponent::topWindow(bool isTop) void VideoComponent::topWindow(bool isTop)
{ {
if (isTop) { if (isTop) {
std::unique_lock<std::mutex> playerLock(mPlayerMutex);
mBlockPlayer = false; mBlockPlayer = false;
mPause = false; mPause = false;
playerLock.unlock();
// Stop video when closing the menu to force a reload of the // Stop video when closing the menu to force a reload of the
// static image (if the theme is configured as such). // static image (if the theme is configured as such).
stopVideo(); stopVideo();
} }
else { else {
std::unique_lock<std::mutex> playerLock(mPlayerMutex);
mBlockPlayer = true; mBlockPlayer = true;
mPause = true; mPause = true;
playerLock.unlock();
} }
manageState(); manageState();
} }

View file

@ -12,7 +12,7 @@
#include "GuiComponent.h" #include "GuiComponent.h"
#include "components/ImageComponent.h" #include "components/ImageComponent.h"
#include <mutex> #include <atomic>
#include <string> #include <string>
class MediaViewer; class MediaViewer;
@ -110,7 +110,6 @@ private:
protected: protected:
Window* mWindow; Window* mWindow;
ImageComponent mStaticImage; ImageComponent mStaticImage;
std::mutex mPlayerMutex;
unsigned mVideoWidth; unsigned mVideoWidth;
unsigned mVideoHeight; unsigned mVideoHeight;
@ -124,9 +123,9 @@ protected:
std::string mPlayingVideoPath; std::string mPlayingVideoPath;
unsigned mStartTime; unsigned mStartTime;
bool mStartDelayed; bool mStartDelayed;
bool mIsPlaying; std::atomic<bool> mIsPlaying;
bool mIsActuallyPlaying; std::atomic<bool> mIsActuallyPlaying;
bool mPause; std::atomic<bool> mPause;
bool mShowing; bool mShowing;
bool mDisable; bool mDisable;
bool mMediaViewerMode; bool mMediaViewerMode;

View file

@ -130,10 +130,8 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans)
if (mIsPlaying && mFormatContext) { if (mIsPlaying && mFormatContext) {
unsigned int color; unsigned int color;
std::unique_lock<std::mutex> pictureLock(mPictureMutex);
bool decodedFrame = mDecodedFrame; if (mDecodedFrame && mFadeIn < 1) {
pictureLock.unlock();
if (decodedFrame && mFadeIn < 1) {
const unsigned int fadeIn = static_cast<int>(mFadeIn * 255.0f); const unsigned int fadeIn = static_cast<int>(mFadeIn * 255.0f);
color = color =
Renderer::convertRGBAToABGR((fadeIn << 24) | (fadeIn << 16) | (fadeIn << 8) | 255); Renderer::convertRGBAToABGR((fadeIn << 24) | (fadeIn << 16) | (fadeIn << 8) | 255);
@ -162,13 +160,11 @@ void VideoFFmpegComponent::render(const glm::mat4& parentTrans)
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
vertices[i].pos = glm::round(vertices[i].pos); vertices[i].pos = glm::round(vertices[i].pos);
pictureLock.lock();
// This is needed to avoid a slight gap before the video starts playing. // This is needed to avoid a slight gap before the video starts playing.
if (!mDecodedFrame) { if (!mDecodedFrame)
pictureLock.unlock();
return; return;
}
std::unique_lock<std::mutex> pictureLock(mPictureMutex);
if (!mOutputPicture.hasBeenRendered) { if (!mOutputPicture.hasBeenRendered) {
// Move the contents of mOutputPicture to a temporary vector in order to call // Move the contents of mOutputPicture to a temporary vector in order to call
@ -238,11 +234,12 @@ void VideoFFmpegComponent::updatePlayer()
} }
if (mIsActuallyPlaying && mStartTimeAccumulation) { if (mIsActuallyPlaying && mStartTimeAccumulation) {
mAccumulatedTime += mAccumulatedTime =
mAccumulatedTime +
static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>( static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::high_resolution_clock::now() - mTimeReference) std::chrono::high_resolution_clock::now() - mTimeReference)
.count()) / .count()) /
1000000000.0l; 1000000000.0l;
} }
mTimeReference = std::chrono::high_resolution_clock::now(); mTimeReference = std::chrono::high_resolution_clock::now();
@ -268,18 +265,16 @@ void VideoFFmpegComponent::frameProcessing()
if (mAudioCodecContext) if (mAudioCodecContext)
audioFilter = setupAudioFilters(); audioFilter = setupAudioFilters();
bool isPlaying = true; while (mIsPlaying && !mPause && videoFilter && (!mAudioCodecContext || audioFilter)) {
bool pause = false;
while (isPlaying && !pause && videoFilter && (!mAudioCodecContext || audioFilter)) {
readFrames(); readFrames();
getProcessedFrames(); if (!mIsPlaying)
outputFrames(); break;
std::unique_lock<std::mutex> playerLock(mPlayerMutex); getProcessedFrames();
isPlaying = mIsPlaying; if (!mIsPlaying)
pause = mPause; break;
playerLock.unlock();
outputFrames();
// This 1 ms wait makes sure that the thread does not consume all available CPU cycles. // This 1 ms wait makes sure that the thread does not consume all available CPU cycles.
SDL_Delay(1); SDL_Delay(1);
@ -672,10 +667,8 @@ void VideoFFmpegComponent::readFrames()
} }
} }
if (readFrameReturn < 0) { if (readFrameReturn < 0)
std::unique_lock<std::mutex> playerLock(mPlayerMutex);
mEndOfVideo = true; mEndOfVideo = true;
}
} }
void VideoFFmpegComponent::getProcessedFrames() void VideoFFmpegComponent::getProcessedFrames()
@ -761,11 +754,7 @@ void VideoFFmpegComponent::outputFrames()
// Process the audio frames that have a PTS value below mAccumulatedTime (plus a small // Process the audio frames that have a PTS value below mAccumulatedTime (plus a small
// buffer to avoid underflows). // buffer to avoid underflows).
while (!mAudioFrameQueue.empty()) { while (!mAudioFrameQueue.empty()) {
std::unique_lock<std::mutex> audioLock(mAudioMutex); if (mAudioFrameQueue.front().pts < mAccumulatedTime + AUDIO_BUFFER) {
auto accumulatedTime = mAccumulatedTime;
audioLock.unlock();
if (mAudioFrameQueue.front().pts < accumulatedTime + AUDIO_BUFFER) {
// Enable only when needed, as this generates a lot of debug output. // Enable only when needed, as this generates a lot of debug output.
if (DEBUG_VIDEO) { if (DEBUG_VIDEO) {
LOG(LogDebug) << "Processing audio frame with PTS: " LOG(LogDebug) << "Processing audio frame with PTS: "
@ -787,7 +776,7 @@ void VideoFFmpegComponent::outputFrames()
if (outputSound) { if (outputSound) {
// The audio is output to AudioManager from updatePlayer() in the main thread. // The audio is output to AudioManager from updatePlayer() in the main thread.
audioLock.lock(); std::unique_lock<std::mutex> audioLock(mAudioMutex);
mOutputAudio.insert(mOutputAudio.end(), mOutputAudio.insert(mOutputAudio.end(),
mAudioFrameQueue.front().resampledData.begin(), mAudioFrameQueue.front().resampledData.begin(),
@ -803,19 +792,11 @@ void VideoFFmpegComponent::outputFrames()
} }
} }
std::unique_lock<std::mutex> playerLock(mPlayerMutex);
bool isActuallyPlaying = mIsActuallyPlaying;
playerLock.unlock();
// Process all available video frames that have a PTS value below mAccumulatedTime. // Process all available video frames that have a PTS value below mAccumulatedTime.
// But if more than one frame is processed here, it means that the computer can't // But if more than one frame is processed here, it means that the computer can't
// keep up for some reason. // keep up for some reason.
while (isActuallyPlaying && !mVideoFrameQueue.empty()) { while (mIsActuallyPlaying && !mVideoFrameQueue.empty()) {
std::unique_lock<std::mutex> audioLock(mAudioMutex); if (mVideoFrameQueue.front().pts < mAccumulatedTime) {
double accumulatedTime = mAccumulatedTime;
audioLock.unlock();
if (mVideoFrameQueue.front().pts < accumulatedTime) {
// Enable only when needed, as this generates a lot of debug output. // Enable only when needed, as this generates a lot of debug output.
if (DEBUG_VIDEO) { if (DEBUG_VIDEO) {
LOG(LogDebug) << "Processing video frame with PTS: " LOG(LogDebug) << "Processing video frame with PTS: "
@ -843,7 +824,7 @@ void VideoFFmpegComponent::outputFrames()
// can't keep up. This approach primarily decreases stuttering for videos with frame // can't keep up. This approach primarily decreases stuttering for videos with frame
// rates close to, or at, the rendering frame rate, for example 59.94 and 60 FPS. // rates close to, or at, the rendering frame rate, for example 59.94 and 60 FPS.
if (mDecodedFrame && !mOutputPicture.hasBeenRendered) { if (mDecodedFrame && !mOutputPicture.hasBeenRendered) {
double timeDifference = accumulatedTime - mVideoFrameQueue.front().pts - double timeDifference = mAccumulatedTime - mVideoFrameQueue.front().pts -
mVideoFrameQueue.front().frameDuration * 2.0l; mVideoFrameQueue.front().frameDuration * 2.0l;
if (timeDifference < mVideoFrameQueue.front().frameDuration) { if (timeDifference < mVideoFrameQueue.front().frameDuration) {
pictureLock.unlock(); pictureLock.unlock();
@ -1408,13 +1389,11 @@ void VideoFFmpegComponent::startVideo()
void VideoFFmpegComponent::stopVideo() void VideoFFmpegComponent::stopVideo()
{ {
std::unique_lock<std::mutex> playerLock(mPlayerMutex);
mIsPlaying = false; mIsPlaying = false;
mIsActuallyPlaying = false; mIsActuallyPlaying = false;
mStartDelayed = false; mStartDelayed = false;
mPause = false; mPause = false;
mEndOfVideo = false; mEndOfVideo = false;
playerLock.unlock();
mTexture.reset(); mTexture.reset();
if (mFrameProcessingThread) { if (mFrameProcessingThread) {
@ -1459,11 +1438,7 @@ void VideoFFmpegComponent::pauseVideo()
void VideoFFmpegComponent::handleLooping() void VideoFFmpegComponent::handleLooping()
{ {
std::unique_lock<std::mutex> playerLock(mPlayerMutex); if (mIsPlaying && mEndOfVideo) {
bool endOfVideo = mEndOfVideo;
playerLock.unlock();
if (mIsPlaying && endOfVideo) {
// If the screensaver video swap time is set to 0, it means we should // If the screensaver video swap time is set to 0, it means we should
// skip to the next game when the video has finished playing. // skip to the next game when the video has finished playing.
if (mScreensaverMode && if (mScreensaverMode &&

View file

@ -23,6 +23,7 @@ extern "C" {
#include <libavutil/imgutils.h> #include <libavutil/imgutils.h>
} }
#include <atomic>
#include <chrono> #include <chrono>
#include <mutex> #include <mutex>
#include <queue> #include <queue>
@ -161,10 +162,10 @@ private:
int mVideoFrameReadCount; int mVideoFrameReadCount;
int mVideoFrameDroppedCount; int mVideoFrameDroppedCount;
double mAccumulatedTime; std::atomic<double> mAccumulatedTime;
bool mStartTimeAccumulation; std::atomic<bool> mStartTimeAccumulation;
bool mDecodedFrame; std::atomic<bool> mDecodedFrame;
bool mEndOfVideo; std::atomic<bool> mEndOfVideo;
bool mSWDecoder; bool mSWDecoder;
}; };

View file

@ -179,9 +179,7 @@ bool TextureData::load()
const ResourceData& data = rm->getFileData(mPath); const ResourceData& data = rm->getFileData(mPath);
// Is it an SVG? // Is it an SVG?
if (Utils::String::toLower(mPath.substr(mPath.size() - 4, std::string::npos)) == ".svg") { if (Utils::String::toLower(mPath.substr(mPath.size() - 4, std::string::npos)) == ".svg") {
std::unique_lock<std::mutex> lock(mMutex);
mScalable = true; mScalable = true;
lock.unlock();
std::string dataString; std::string dataString;
dataString.assign(std::string(reinterpret_cast<char*>(data.ptr.get()), data.length)); dataString.assign(std::string(reinterpret_cast<char*>(data.ptr.get()), data.length));
retval = initSVGFromMemory(dataString); retval = initSVGFromMemory(dataString);
@ -285,11 +283,7 @@ float TextureData::sourceHeight()
void TextureData::setSourceSize(float width, float height) void TextureData::setSourceSize(float width, float height)
{ {
std::unique_lock<std::mutex> lock(mMutex); if (mScalable) {
bool scalable = mScalable;
lock.unlock();
if (scalable) {
if ((mSourceWidth != width) || (mSourceHeight != height)) { if ((mSourceWidth != width) || (mSourceHeight != height)) {
mSourceWidth = width; mSourceWidth = width;
mSourceHeight = height; mSourceHeight = height;

View file

@ -11,6 +11,7 @@
#include "utils/MathUtil.h" #include "utils/MathUtil.h"
#include <atomic>
#include <cmath> #include <cmath>
#include <mutex> #include <mutex>
#include <string> #include <string>
@ -79,7 +80,7 @@ private:
int mHeight; int mHeight;
float mSourceWidth; float mSourceWidth;
float mSourceHeight; float mSourceHeight;
bool mScalable; std::atomic<bool> mScalable;
bool mLinearMagnify; bool mLinearMagnify;
bool mReloadable; bool mReloadable;
bool mForceRasterization; bool mForceRasterization;

View file

@ -161,10 +161,11 @@ TextureLoader::~TextureLoader()
std::unique_lock<std::mutex> lock(mMutex); std::unique_lock<std::mutex> lock(mMutex);
mTextureDataQ.clear(); mTextureDataQ.clear();
mTextureDataLookup.clear(); mTextureDataLookup.clear();
lock.unlock();
// Exit the thread. // Exit the thread.
mExit = true; mExit = true;
lock.unlock();
mEvent.notify_one(); mEvent.notify_one();
mThread->join(); mThread->join();
mThread.reset(); mThread.reset();
@ -172,9 +173,7 @@ TextureLoader::~TextureLoader()
void TextureLoader::threadProc() void TextureLoader::threadProc()
{ {
bool exit = false; while (!mExit) {
while (!exit) {
std::shared_ptr<TextureData> textureData; std::shared_ptr<TextureData> textureData;
{ {
// Wait for an event to say there is something in the queue. // Wait for an event to say there is something in the queue.
@ -199,7 +198,6 @@ void TextureLoader::threadProc()
mTextureDataLookup.erase(mTextureDataLookup.find(textureData.get())); mTextureDataLookup.erase(mTextureDataLookup.find(textureData.get()));
} }
} }
exit = mExit;
} }
} }

View file

@ -9,6 +9,7 @@
#ifndef ES_CORE_RESOURCES_TEXTURE_DATA_MANAGER_H #ifndef ES_CORE_RESOURCES_TEXTURE_DATA_MANAGER_H
#define ES_CORE_RESOURCES_TEXTURE_DATA_MANAGER_H #define ES_CORE_RESOURCES_TEXTURE_DATA_MANAGER_H
#include <atomic>
#include <condition_variable> #include <condition_variable>
#include <list> #include <list>
#include <map> #include <map>
@ -41,7 +42,7 @@ private:
std::unique_ptr<std::thread> mThread; std::unique_ptr<std::thread> mThread;
std::mutex mMutex; std::mutex mMutex;
std::condition_variable mEvent; std::condition_variable mEvent;
bool mExit; std::atomic<bool> mExit;
}; };
// //