Skip to content

Commit

Permalink
Add lottie_init() and lottie_shutdown() c api.
Browse files Browse the repository at this point in the history
To support dynamic loading and unloading of rlottie library safely
we need to deallocate the resource cache as well as safely shutdown all the
worker threads.
current patch only stops the Render and Rle task schedulers when lottie_shutdown is called.

Things yet to be implemented during shutdown phase
- Unload image loader if loaded dynamically.
- Check if we can release some cache resources.
- Currently multiple load and unload of rlottie library will not work as we are not starting the
  scheduler again when lottie_init() called multiple time in the same process.
  • Loading branch information
smohantty committed Dec 10, 2021
1 parent 447cb7d commit 55c6536
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 6 deletions.
30 changes: 30 additions & 0 deletions inc/rlottie_capi.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,36 @@ typedef enum {

typedef struct Lottie_Animation_S Lottie_Animation;

/**
* @brief Runs lottie initialization code when rlottie library is loaded
* dynamically.
*
*
* This api should be called before any other api when rlottie library
* is loaded using dlopen() or equivalent.
*
* @see lottie_shutdown()
*
* @ingroup Lottie_Animation
* @internal
*/
RLOTTIE_API void lottie_init();

/**
* @brief Runs lottie teardown code when rlottie library is loaded
* dynamically.
*
* This api should be called before unloading the rlottie library for
* proper cleanup of the resource without doing so will result in undefined
* behaviour.
*
* @see lottie_init()
*
* @ingroup Lottie_Animation
* @internal
*/
RLOTTIE_API void lottie_shutdown();

/**
* @brief Constructs an animation object from file path.
*
Expand Down
31 changes: 31 additions & 0 deletions src/binding/c/lottieanimation_capi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@

using namespace rlottie;

extern void lottie_init_impl();
extern void lottie_shutdown_impl();

extern "C" {
#include <string.h>
#include <stdarg.h>
Expand All @@ -38,6 +41,34 @@ struct Lottie_Animation_S
LOTMarkerList *mMarkerList;
};

static uint32_t _lottie_lib_ref_count = 0;

RLOTTIE_API void lottie_init()
{
if (_lottie_lib_ref_count > 0) {
_lottie_lib_ref_count++;
return;
}
lottie_init_impl();

_lottie_lib_ref_count = 1;
}

RLOTTIE_API void lottie_shutdown()
{
if (_lottie_lib_ref_count <= 0) {
// lottie_init() is not called before lottie_shutdown()
// or multiple shutdown is getting called.
return;
}

_lottie_lib_ref_count--;

if (_lottie_lib_ref_count == 0) {
lottie_shutdown_impl();
}
}

RLOTTIE_API Lottie_Animation_S *lottie_animation_from_file(const char *path)
{
if (auto animation = Animation::loadFromFile(path) ) {
Expand Down
45 changes: 42 additions & 3 deletions src/lottie/lottieanimation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,20 +178,29 @@ class RenderTaskScheduler {
for (unsigned n = 0; n != _count; ++n) {
_threads.emplace_back([&, n] { run(n); });
}

IsRunning = true;
}

public:
static bool IsRunning;

static RenderTaskScheduler &instance()
{
static RenderTaskScheduler singleton;
return singleton;
}

~RenderTaskScheduler()
~RenderTaskScheduler() { stop(); }

void stop()
{
for (auto &e : _q) e.done();
if (IsRunning) {
IsRunning = false;

for (auto &e : _threads) e.join();
for (auto &e : _q) e.done();
for (auto &e : _threads) e.join();
}
}

std::future<Surface> process(SharedRenderTask task)
Expand All @@ -214,12 +223,16 @@ class RenderTaskScheduler {
#else
class RenderTaskScheduler {
public:
static bool IsRunning;

static RenderTaskScheduler &instance()
{
static RenderTaskScheduler singleton;
return singleton;
}

void stop() {}

std::future<Surface> process(SharedRenderTask task)
{
auto result = task->playerImpl->render(task->frameNo, task->surface,
Expand All @@ -228,8 +241,11 @@ class RenderTaskScheduler {
return std::move(task->receiver);
}
};

#endif

bool RenderTaskScheduler::IsRunning{false};

std::future<Surface> AnimationImpl::renderAsync(size_t frameNo,
Surface &&surface,
bool keepAspectRatio)
Expand Down Expand Up @@ -441,6 +457,29 @@ void Surface::setDrawRegion(size_t x, size_t y, size_t width, size_t height)
mDrawArea.h = height;
}

namespace {
void lottieShutdownRenderTaskScheduler()
{
if (RenderTaskScheduler::IsRunning) {
RenderTaskScheduler::instance().stop();
}
}
} // namespace

// private apis exposed to c interface
void lottie_init_impl()
{
// do nothing for now.
}

extern void lottieShutdownRasterTaskScheduler();

void lottie_shutdown_impl()
{
lottieShutdownRenderTaskScheduler();
lottieShutdownRasterTaskScheduler();
}

#ifdef LOTTIE_LOGGING_SUPPORT
void initLogging()
{
Expand Down
28 changes: 25 additions & 3 deletions src/vector/vraster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,20 +461,29 @@ class RleTaskScheduler {
for (unsigned n = 0; n != _count; ++n) {
_threads.emplace_back([&, n] { run(n); });
}

IsRunning = true;
}

public:
static bool IsRunning;

static RleTaskScheduler &instance()
{
static RleTaskScheduler singleton;
return singleton;
}

~RleTaskScheduler()
~RleTaskScheduler() { stop(); }

void stop()
{
for (auto &e : _q) e.done();
if (IsRunning) {
IsRunning = false;

for (auto &e : _threads) e.join();
for (auto &e : _q) e.done();
for (auto &e : _threads) e.join();
}
}

void process(VTask task)
Expand All @@ -499,12 +508,16 @@ class RleTaskScheduler {
SW_FT_Stroker stroker;

public:
static bool IsRunning;

static RleTaskScheduler &instance()
{
static RleTaskScheduler singleton;
return singleton;
}

void stop() {}

RleTaskScheduler() { SW_FT_Stroker_New(&stroker); }

~RleTaskScheduler() { SW_FT_Stroker_Done(stroker); }
Expand All @@ -513,6 +526,8 @@ class RleTaskScheduler {
};
#endif

bool RleTaskScheduler::IsRunning{false};

struct VRasterizer::VRasterizerImpl {
VRleTask mTask;

Expand Down Expand Up @@ -560,4 +575,11 @@ void VRasterizer::rasterize(VPath path, CapStyle cap, JoinStyle join,
updateRequest();
}

void lottieShutdownRasterTaskScheduler()
{
if (RleTaskScheduler::IsRunning) {
RleTaskScheduler::instance().stop();
}
}

V_END_NAMESPACE

0 comments on commit 55c6536

Please sign in to comment.