From 4bd42ec7b1b7a77c014829fb6953972c36b28869 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Sat, 6 Jul 2024 19:23:31 +0900 Subject: [PATCH] lottie: ++thread safety. comp pointer is used for checking if the header is ready. It can be written in a worker thread and needs a critical section on the reader side. This also potentally improve the thread efficiency from the segment() / marker() function calls. --- src/loaders/lottie/tvgLottieLoader.cpp | 45 ++++++++++++++------------ src/loaders/lottie/tvgLottieLoader.h | 3 ++ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/loaders/lottie/tvgLottieLoader.cpp b/src/loaders/lottie/tvgLottieLoader.cpp index 0d880025..c3ada835 100644 --- a/src/loaders/lottie/tvgLottieLoader.cpp +++ b/src/loaders/lottie/tvgLottieLoader.cpp @@ -39,7 +39,10 @@ void LottieLoader::run(unsigned tid) } else { LottieParser parser(content, dirName); if (!parser.parse()) return; - comp = parser.comp; + { + ScopedLock lock(key); + comp = parser.comp; + } builder->build(comp); } rebuild = false; @@ -58,7 +61,7 @@ LottieLoader::LottieLoader() : FrameModule(FileType::Lottie), builder(new Lottie LottieLoader::~LottieLoader() { - this->done(); + done(); if (copy) free((char*)content); free(dirName); @@ -79,16 +82,17 @@ bool LottieLoader::header() h = static_cast(comp->h); frameDuration = comp->duration(); frameCnt = comp->frameCnt(); + frameRate = comp->frameRate; return true; } else { return false; } + LoadModule::read(); } //Quickly validate the given Lottie file without parsing in order to get the animation info. auto startFrame = 0.0f; auto endFrame = 0.0f; - auto frameRate = 0.0f; uint32_t depth = 0; auto p = content; @@ -249,7 +253,7 @@ bool LottieLoader::read() if (!content || size == 0) return false; //the loading has been already completed - if (comp || !LoadModule::read()) return true; + if (!LoadModule::read()) return true; TaskScheduler::request(this); @@ -269,9 +273,7 @@ Paint* LottieLoader::paint() bool LottieLoader::override(const char* slot) { - done(); - - if (!comp || comp->slots.count == 0) return false; + if (!ready() || comp->slots.count == 0) return false; auto success = true; @@ -351,11 +353,7 @@ float LottieLoader::curFrame() float LottieLoader::duration() { if (segmentBegin == 0.0f && segmentEnd == 1.0f) return frameDuration; - - if (!comp) done(); - if (!comp) return 0.0f; - - return frameCnt * (segmentEnd - segmentBegin) / comp->frameRate; + return frameCnt * (segmentEnd - segmentBegin) / frameRate; } @@ -369,16 +367,13 @@ void LottieLoader::sync() uint32_t LottieLoader::markersCnt() { - done(); - return comp ? comp->markers.count : 0; + return ready() ? comp->markers.count : 0; } const char* LottieLoader::markers(uint32_t index) { - done(); - - if (!comp || index >= comp->markers.count) return nullptr; + if (!ready() || index >= comp->markers.count) return nullptr; auto marker = comp->markers.begin() + index; return (*marker)->name; } @@ -386,9 +381,7 @@ const char* LottieLoader::markers(uint32_t index) bool LottieLoader::segment(const char* marker, float& begin, float& end) { - done(); - - if (!comp) return false; + if (!ready() || comp->markers.count == 0) return false; for (auto m = comp->markers.begin(); m < comp->markers.end(); ++m) { if (!strcmp(marker, (*m)->name)) { @@ -399,3 +392,15 @@ bool LottieLoader::segment(const char* marker, float& begin, float& end) } return false; } + + +bool LottieLoader::ready() +{ + { + ScopedLock lock(key); + if (comp) return true; + } + done(); + if (comp) return true; + return false; +} \ No newline at end of file diff --git a/src/loaders/lottie/tvgLottieLoader.h b/src/loaders/lottie/tvgLottieLoader.h index cb451195..977573b1 100644 --- a/src/loaders/lottie/tvgLottieLoader.h +++ b/src/loaders/lottie/tvgLottieLoader.h @@ -38,10 +38,12 @@ public: float frameNo = 0.0f; //current frame number float frameCnt = 0.0f; float frameDuration = 0.0f; + float frameRate = 0.0f; LottieBuilder* builder; LottieComposition* comp = nullptr; + Key key; char* dirName = nullptr; //base resource directory bool copy = false; //"content" is owned by this loader bool overriden = false; //overridden properties with slots @@ -70,6 +72,7 @@ public: bool segment(const char* marker, float& begin, float& end); private: + bool ready(); bool header(); void clear(); float startFrame();