mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-08 05:33:36 +00:00
common: ++loader thread safety
fortitfy the thread safety in multi-threaded resource loading. issue: https://github.com/thorvg/thorvg/issues/3306
This commit is contained in:
parent
72a1b0339b
commit
6708fae17b
5 changed files with 12 additions and 43 deletions
|
@ -201,9 +201,7 @@ void LottieFont::prepare()
|
|||
{
|
||||
if (!data.b64src || !name) return;
|
||||
|
||||
TaskScheduler::async(false);
|
||||
Text::load(name, data.b64src, data.size, "ttf", false);
|
||||
TaskScheduler::async(true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -214,13 +212,9 @@ void LottieImage::prepare()
|
|||
auto picture = Picture::gen().release();
|
||||
|
||||
//force to load a picture on the same thread
|
||||
TaskScheduler::async(false);
|
||||
|
||||
if (data.size > 0) picture->load((const char*)data.b64Data, data.size, data.mimeType, false);
|
||||
else picture->load(data.path);
|
||||
|
||||
TaskScheduler::async(true);
|
||||
|
||||
picture->size(data.width, data.height);
|
||||
PP(picture)->ref();
|
||||
|
||||
|
@ -231,13 +225,11 @@ void LottieImage::prepare()
|
|||
void LottieImage::update()
|
||||
{
|
||||
//Update the picture data
|
||||
TaskScheduler::async(false);
|
||||
for (auto p = pooler.begin(); p < pooler.end(); ++p) {
|
||||
if (data.size > 0) (*p)->load((const char*)data.b64Data, data.size, data.mimeType, false);
|
||||
else (*p)->load(data.path);
|
||||
(*p)->size(data.width, data.height);
|
||||
}
|
||||
TaskScheduler::async(true);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -573,8 +573,6 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
|||
if (!node->node.image.href || !strlen(node->node.image.href)) return nullptr;
|
||||
auto picture = Picture::gen();
|
||||
|
||||
TaskScheduler::async(false); //force to load a picture on the same thread
|
||||
|
||||
const char* href = node->node.image.href;
|
||||
if (!strncmp(href, "data:", sizeof("data:") - 1)) {
|
||||
href += sizeof("data:") - 1;
|
||||
|
@ -586,14 +584,12 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
|||
auto size = b64Decode(href, strlen(href), &decoded);
|
||||
if (picture->load(decoded, size, mimetype, false) != Result::Success) {
|
||||
free(decoded);
|
||||
TaskScheduler::async(true);
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
auto size = svgUtilURLDecode(href, &decoded);
|
||||
if (picture->load(decoded, size, mimetype, false) != Result::Success) {
|
||||
free(decoded);
|
||||
TaskScheduler::async(true);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -605,7 +601,6 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
|||
const char *dot = strrchr(href, '.');
|
||||
if (dot && !strcmp(dot, ".svg")) {
|
||||
TVGLOG("SVG", "Embedded svg file is disabled.");
|
||||
TaskScheduler::async(true);
|
||||
return nullptr;
|
||||
}
|
||||
string imagePath = href;
|
||||
|
@ -614,13 +609,10 @@ static unique_ptr<Picture> _imageBuildHelper(SvgLoaderData& loaderData, SvgNode*
|
|||
imagePath = svgPath.substr(0, (last == string::npos ? 0 : last + 1)) + imagePath;
|
||||
}
|
||||
if (picture->load(imagePath) != Result::Success) {
|
||||
TaskScheduler::async(true);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
TaskScheduler::async(true);
|
||||
|
||||
float w, h;
|
||||
Matrix m = {1, 0, 0, 0, 1, 0, 0, 0, 1};
|
||||
if (picture->size(&w, &h) == Result::Success && w > 0 && h > 0) {
|
||||
|
@ -931,9 +923,7 @@ static void _loadFonts(Array<FontFace>& fonts)
|
|||
|
||||
auto size = b64Decode(p->src + shift, p->srcLen - shift, &p->decoded);
|
||||
|
||||
TaskScheduler::async(false);
|
||||
if (Text::load(p->name, p->decoded, size) != Result::Success) TVGERR("SVG", "Error while loading the ttf font named \"%s\".", p->name);
|
||||
TaskScheduler::async(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ uintptr_t HASH_KEY(const char* data)
|
|||
|
||||
ColorSpace ImageLoader::cs = ColorSpace::ARGB8888;
|
||||
|
||||
static Key key;
|
||||
static Key _key;
|
||||
static Inlist<LoadModule> _activeLoaders;
|
||||
|
||||
|
||||
|
@ -215,7 +215,7 @@ static LoadModule* _findByType(const string& mimeType)
|
|||
|
||||
static LoadModule* _findFromCache(const string& path)
|
||||
{
|
||||
ScopedLock lock(key);
|
||||
ScopedLock lock(_key);
|
||||
|
||||
auto loader = _activeLoaders.head;
|
||||
|
||||
|
@ -235,11 +235,10 @@ static LoadModule* _findFromCache(const char* data, uint32_t size, const string&
|
|||
auto type = _convert(mimeType);
|
||||
if (type == FileType::Unknown) return nullptr;
|
||||
|
||||
ScopedLock lock(key);
|
||||
auto loader = _activeLoaders.head;
|
||||
|
||||
auto key = HASH_KEY(data);
|
||||
ScopedLock lock(_key);
|
||||
|
||||
auto loader = _activeLoaders.head;
|
||||
while (loader) {
|
||||
if (loader->type == type && loader->hashkey == key) {
|
||||
++loader->sharing;
|
||||
|
@ -285,9 +284,9 @@ bool LoaderMgr::term()
|
|||
bool LoaderMgr::retrieve(LoadModule* loader)
|
||||
{
|
||||
if (!loader) return false;
|
||||
|
||||
if (loader->close()) {
|
||||
if (loader->cached()) {
|
||||
ScopedLock lock(key);
|
||||
_activeLoaders.remove(loader);
|
||||
}
|
||||
delete(loader);
|
||||
|
@ -316,7 +315,7 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid)
|
|||
loader->hashpath = strdup(path.c_str());
|
||||
loader->pathcache = true;
|
||||
{
|
||||
ScopedLock lock(key);
|
||||
ScopedLock lock(_key);
|
||||
_activeLoaders.back(loader);
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +331,7 @@ LoadModule* LoaderMgr::loader(const string& path, bool* invalid)
|
|||
loader->hashpath = strdup(path.c_str());
|
||||
loader->pathcache = true;
|
||||
{
|
||||
ScopedLock lock(key);
|
||||
ScopedLock lock(_key);
|
||||
_activeLoaders.back(loader);
|
||||
}
|
||||
}
|
||||
|
@ -390,7 +389,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim
|
|||
if (loader->open(data, size, copy)) {
|
||||
if (allowCache) {
|
||||
loader->hashkey = HASH_KEY(data);
|
||||
ScopedLock lock(key);
|
||||
ScopedLock lock(_key);
|
||||
_activeLoaders.back(loader);
|
||||
}
|
||||
return loader;
|
||||
|
@ -407,7 +406,7 @@ LoadModule* LoaderMgr::loader(const char* data, uint32_t size, const string& mim
|
|||
if (loader->open(data, size, copy)) {
|
||||
if (allowCache) {
|
||||
loader->hashkey = HASH_KEY(data);
|
||||
ScopedLock lock(key);
|
||||
ScopedLock lock(_key);
|
||||
_activeLoaders.back(loader);
|
||||
}
|
||||
return loader;
|
||||
|
@ -433,7 +432,7 @@ LoadModule* LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool
|
|||
if (loader->open(data, w, h, copy)) {
|
||||
if (!copy) {
|
||||
loader->hashkey = HASH_KEY((const char*)data);
|
||||
ScopedLock lock(key);
|
||||
ScopedLock lock(_key);
|
||||
_activeLoaders.back(loader);
|
||||
}
|
||||
return loader;
|
||||
|
@ -455,7 +454,7 @@ LoadModule* LoaderMgr::loader(const char* name, const char* data, uint32_t size,
|
|||
if (loader->open(data, size, copy)) {
|
||||
loader->hashpath = strdup(name);
|
||||
loader->pathcache = true;
|
||||
ScopedLock lock(key);
|
||||
ScopedLock lock(_key);
|
||||
_activeLoaders.back(loader);
|
||||
return loader;
|
||||
}
|
||||
|
|
|
@ -40,8 +40,6 @@ static TaskSchedulerImpl* inst = nullptr;
|
|||
|
||||
#ifdef THORVG_THREAD_SUPPORT
|
||||
|
||||
static thread_local bool _async = true;
|
||||
|
||||
struct TaskQueue {
|
||||
Inlist<Task> taskDeque;
|
||||
mutex mtx;
|
||||
|
@ -157,7 +155,7 @@ struct TaskSchedulerImpl
|
|||
void request(Task* task)
|
||||
{
|
||||
//Async
|
||||
if (threads.count > 0 && _async) {
|
||||
if (threads.count > 0) {
|
||||
task->prepare();
|
||||
auto i = idx++;
|
||||
for (uint32_t n = 0; n < threads.count; ++n) {
|
||||
|
@ -178,8 +176,6 @@ struct TaskSchedulerImpl
|
|||
|
||||
#else //THORVG_THREAD_SUPPORT
|
||||
|
||||
static bool _async = true;
|
||||
|
||||
struct TaskSchedulerImpl
|
||||
{
|
||||
TaskSchedulerImpl(TVG_UNUSED uint32_t threadCnt) {}
|
||||
|
@ -219,11 +215,4 @@ uint32_t TaskScheduler::threads()
|
|||
{
|
||||
if (inst) return inst->threadCnt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void TaskScheduler::async(bool on)
|
||||
{
|
||||
//toggle async tasking for each thread on/off
|
||||
_async = on;
|
||||
}
|
|
@ -103,7 +103,6 @@ struct TaskScheduler
|
|||
static void init(uint32_t threads);
|
||||
static void term();
|
||||
static void request(Task* task);
|
||||
static void async(bool on);
|
||||
};
|
||||
|
||||
} //namespace
|
||||
|
|
Loading…
Add table
Reference in a new issue