This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/blenlib/intern/BLI_timer.c
Campbell Barton c434782e3a File headers: SPDX License migration
Use a shorter/simpler license convention, stops the header taking so
much space.

Follow the SPDX license specification: https://spdx.org/licenses

- C/C++/objc/objc++
- Python
- Shell Scripts
- CMake, GNUmakefile

While most of the source tree has been included

- `./extern/` was left out.
- `./intern/cycles` & `./intern/atomic` are also excluded because they
  use different header conventions.

doc/license/SPDX-license-identifiers.txt has been added to list SPDX all
used identifiers.

See P2788 for the script that automated these edits.

Reviewed By: brecht, mont29, sergey

Ref D14069
2022-02-11 09:14:36 +11:00

145 lines
3.3 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2018 Blender Foundation. All rights reserved. */
/** \file
* \ingroup bli
*/
#include "BLI_timer.h"
#include "BLI_listbase.h"
#include "MEM_guardedalloc.h"
#include "PIL_time.h"
#define GET_TIME() PIL_check_seconds_timer()
typedef struct TimedFunction {
struct TimedFunction *next, *prev;
BLI_timer_func func;
BLI_timer_data_free user_data_free;
void *user_data;
double next_time;
uintptr_t uuid;
bool tag_removal;
bool persistent;
} TimedFunction;
typedef struct TimerContainer {
ListBase funcs;
} TimerContainer;
static TimerContainer GlobalTimer = {{0}};
void BLI_timer_register(uintptr_t uuid,
BLI_timer_func func,
void *user_data,
BLI_timer_data_free user_data_free,
double first_interval,
bool persistent)
{
TimedFunction *timed_func = MEM_callocN(sizeof(TimedFunction), __func__);
timed_func->func = func;
timed_func->user_data_free = user_data_free;
timed_func->user_data = user_data;
timed_func->next_time = GET_TIME() + first_interval;
timed_func->tag_removal = false;
timed_func->persistent = persistent;
timed_func->uuid = uuid;
BLI_addtail(&GlobalTimer.funcs, timed_func);
}
static void clear_user_data(TimedFunction *timed_func)
{
if (timed_func->user_data_free) {
timed_func->user_data_free(timed_func->uuid, timed_func->user_data);
timed_func->user_data_free = NULL;
}
}
bool BLI_timer_unregister(uintptr_t uuid)
{
LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) {
if (timed_func->uuid == uuid && !timed_func->tag_removal) {
timed_func->tag_removal = true;
clear_user_data(timed_func);
return true;
}
}
return false;
}
bool BLI_timer_is_registered(uintptr_t uuid)
{
LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) {
if (timed_func->uuid == uuid && !timed_func->tag_removal) {
return true;
}
}
return false;
}
static void execute_functions_if_necessary(void)
{
double current_time = GET_TIME();
LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) {
if (timed_func->tag_removal) {
continue;
}
if (timed_func->next_time > current_time) {
continue;
}
double ret = timed_func->func(timed_func->uuid, timed_func->user_data);
if (ret < 0) {
timed_func->tag_removal = true;
}
else {
timed_func->next_time = current_time + ret;
}
}
}
static void remove_tagged_functions(void)
{
for (TimedFunction *timed_func = GlobalTimer.funcs.first; timed_func;) {
TimedFunction *next = timed_func->next;
if (timed_func->tag_removal) {
clear_user_data(timed_func);
BLI_freelinkN(&GlobalTimer.funcs, timed_func);
}
timed_func = next;
}
}
void BLI_timer_execute()
{
execute_functions_if_necessary();
remove_tagged_functions();
}
void BLI_timer_free()
{
LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) {
timed_func->tag_removal = true;
}
remove_tagged_functions();
}
static void remove_non_persistent_functions(void)
{
LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) {
if (!timed_func->persistent) {
timed_func->tag_removal = true;
}
}
}
void BLI_timer_on_file_load(void)
{
remove_non_persistent_functions();
}