renderer/loader: improve thread safety

activeLoaders can be accessed by loaders within the worker thread.

the issue came up with the Loader cache feature:
ff6ea4b6c4

Issue: https://github.com/thorvg/thorvg/issues/1874
This commit is contained in:
Hermet Park 2023-12-29 12:05:37 +09:00 committed by Hermet Park
parent ea4662a927
commit 217c53e823

View file

@ -63,6 +63,7 @@ uint64_t HASH_KEY(const char* data, uint64_t size)
/* Internal Class Implementation */ /* Internal Class Implementation */
/************************************************************************/ /************************************************************************/
static mutex mtx;
static Inlist<LoadModule> _activeLoaders; static Inlist<LoadModule> _activeLoaders;
@ -208,6 +209,8 @@ static LoadModule* _findByType(const string& mimeType)
static LoadModule* _findFromCache(const string& path) static LoadModule* _findFromCache(const string& path)
{ {
unique_lock<mutex> lock{mtx};
auto loader = _activeLoaders.head; auto loader = _activeLoaders.head;
while (loader) { while (loader) {
@ -226,6 +229,7 @@ static LoadModule* _findFromCache(const char* data, uint32_t size, const string&
auto type = _convert(mimeType); auto type = _convert(mimeType);
if (type == FileType::Unknown) return nullptr; if (type == FileType::Unknown) return nullptr;
unique_lock<mutex> lock{mtx};
auto loader = _activeLoaders.head; auto loader = _activeLoaders.head;
auto key = HASH_KEY(data, size); auto key = HASH_KEY(data, size);
@ -272,7 +276,10 @@ bool LoaderMgr::retrieve(LoadModule* loader)
{ {
if (!loader) return false; if (!loader) return false;
if (loader->close()) { if (loader->close()) {
_activeLoaders.remove(loader); {
unique_lock<mutex> lock{mtx};
_activeLoaders.remove(loader);
}
delete(loader); delete(loader);
} }
return true; return true;
@ -288,7 +295,10 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid)
if (auto loader = _findByPath(path)) { if (auto loader = _findByPath(path)) {
if (loader->open(path)) { if (loader->open(path)) {
loader->hashpath = strdup(path.c_str()); loader->hashpath = strdup(path.c_str());
_activeLoaders.back(loader); {
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader);
}
return loader; return loader;
} }
delete(loader); delete(loader);
@ -328,6 +338,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim
if (auto loader = _findByType(mimeType)) { if (auto loader = _findByType(mimeType)) {
if (loader->open(data, size, rpath, copy)) { if (loader->open(data, size, rpath, copy)) {
loader->hashkey = HASH_KEY(data, size); loader->hashkey = HASH_KEY(data, size);
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader); _activeLoaders.back(loader);
return loader; return loader;
} else { } else {
@ -342,7 +353,10 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim
if (loader) { if (loader) {
if (loader->open(data, size, rpath, copy)) { if (loader->open(data, size, rpath, copy)) {
loader->hashkey = HASH_KEY(data, size); loader->hashkey = HASH_KEY(data, size);
_activeLoaders.back(loader); {
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader);
}
return loader; return loader;
} }
delete(loader); delete(loader);
@ -362,7 +376,10 @@ LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool
auto loader = new RawLoader; auto loader = new RawLoader;
if (loader->open(data, w, h, premultiplied, copy)) { if (loader->open(data, w, h, premultiplied, copy)) {
loader->hashkey = HASH_KEY((const char*)data, w * h); loader->hashkey = HASH_KEY((const char*)data, w * h);
_activeLoaders.back(loader); {
unique_lock<mutex> lock{mtx};
_activeLoaders.back(loader);
}
return loader; return loader;
} }
delete(loader); delete(loader);