Improved thread safety in TextureData and TextureDataManager.

This commit is contained in:
Leon Styhre 2021-11-15 23:33:16 +01:00
parent 7b06e9fb8b
commit 999b9a6c04
2 changed files with 32 additions and 8 deletions

View file

@ -179,7 +179,9 @@ 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);
@ -243,35 +245,51 @@ void TextureData::releaseRAM()
size_t TextureData::width() size_t TextureData::width()
{ {
if (mWidth == 0) std::unique_lock<std::mutex> lock(mMutex);
if (mWidth == 0) {
lock.unlock();
load(); load();
}
return static_cast<size_t>(mWidth); return static_cast<size_t>(mWidth);
} }
size_t TextureData::height() size_t TextureData::height()
{ {
if (mHeight == 0) std::unique_lock<std::mutex> lock(mMutex);
if (mHeight == 0) {
lock.unlock();
load(); load();
}
return static_cast<size_t>(mHeight); return static_cast<size_t>(mHeight);
} }
float TextureData::sourceWidth() float TextureData::sourceWidth()
{ {
if (mSourceWidth == 0) std::unique_lock<std::mutex> lock(mMutex);
if (mSourceWidth == 0) {
lock.unlock();
load(); load();
}
return mSourceWidth; return mSourceWidth;
} }
float TextureData::sourceHeight() float TextureData::sourceHeight()
{ {
if (mSourceHeight == 0) std::unique_lock<std::mutex> lock(mMutex);
if (mSourceHeight == 0) {
lock.unlock();
load(); load();
}
return mSourceHeight; return mSourceHeight;
} }
void TextureData::setSourceSize(float width, float height) void TextureData::setSourceSize(float width, float height)
{ {
if (mScalable) { std::unique_lock<std::mutex> lock(mMutex);
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;
@ -283,6 +301,7 @@ void TextureData::setSourceSize(float width, float height)
size_t TextureData::getVRAMUsage() size_t TextureData::getVRAMUsage()
{ {
std::unique_lock<std::mutex> lock(mMutex);
if (mTextureID != 0 || !mDataRGBA.empty()) if (mTextureID != 0 || !mDataRGBA.empty())
return mWidth * mHeight * 4; return mWidth * mHeight * 4;
else else

View file

@ -16,7 +16,7 @@
TextureDataManager::TextureDataManager() TextureDataManager::TextureDataManager()
{ {
unsigned char data[5 * 5 * 4]; unsigned char data[5 * 5 * 4];
mBlank = std::shared_ptr<TextureData>(new TextureData(false)); mBlank = std::make_shared<TextureData>(false);
for (int i = 0; i < (5 * 5); i++) { for (int i = 0; i < (5 * 5); i++) {
data[i * 4] = (i % 2) * 255; data[i * 4] = (i % 2) * 255;
data[i * 4 + 1] = (i % 2) * 255; data[i * 4 + 1] = (i % 2) * 255;
@ -36,7 +36,7 @@ TextureDataManager::~TextureDataManager()
std::shared_ptr<TextureData> TextureDataManager::add(const TextureResource* key, bool tiled) std::shared_ptr<TextureData> TextureDataManager::add(const TextureResource* key, bool tiled)
{ {
remove(key); remove(key);
std::shared_ptr<TextureData> data(new TextureData(tiled)); std::shared_ptr<TextureData> data = std::make_shared<TextureData>(tiled);
mTextures.push_front(data); mTextures.push_front(data);
mTextureLookup[key] = mTextures.cbegin(); mTextureLookup[key] = mTextures.cbegin();
return data; return data;
@ -158,11 +158,13 @@ TextureLoader::TextureLoader()
TextureLoader::~TextureLoader() TextureLoader::~TextureLoader()
{ {
// Just abort any waiting texture. // Just abort any waiting texture.
std::unique_lock<std::mutex> lock(mMutex);
mTextureDataQ.clear(); mTextureDataQ.clear();
mTextureDataLookup.clear(); mTextureDataLookup.clear();
// 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();
@ -170,7 +172,9 @@ TextureLoader::~TextureLoader()
void TextureLoader::threadProc() void TextureLoader::threadProc()
{ {
while (!mExit) { bool exit = false;
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.
@ -195,6 +199,7 @@ void TextureLoader::threadProc()
mTextureDataLookup.erase(mTextureDataLookup.find(textureData.get())); mTextureDataLookup.erase(mTextureDataLookup.find(textureData.get()));
} }
} }
exit = mExit;
} }
} }