Files
test2/source/blender/blenlib/intern/BLI_timer.cc
Bastien Montagne dd168a35c5 Refactor: Replace MEM_cnew with a type-aware template version of MEM_callocN.
The general idea is to keep the 'old', C-style MEM_callocN signature, and slowly
replace most of its usages with the new, C++-style type-safer template version.

* `MEM_cnew<T>` allocation version is renamed to `MEM_callocN<T>`.
* `MEM_cnew_array<T>` allocation version is renamed to `MEM_calloc_arrayN<T>`.
* `MEM_cnew<T>` duplicate version is renamed to `MEM_dupallocN<T>`.

Similar templates type-safe version of `MEM_mallocN` will be added soon
as well.

Following discussions in !134452.

NOTE: For now static type checking in `MEM_callocN` and related are slightly
different for Windows MSVC. This compiler seems to consider structs using the
`DNA_DEFINE_CXX_METHODS` macro as non-trivial (likely because their default
copy constructors are deleted). So using checks on trivially
constructible/destructible instead on this compiler/system.

Pull Request: https://projects.blender.org/blender/blender/pulls/134771
2025-03-05 16:35:09 +01:00

148 lines
3.3 KiB
C++

/* SPDX-FileCopyrightText: 2018 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bli
*/
#include "BLI_timer.h"
#include "BLI_listbase.h"
#include "BLI_time.h"
#include "MEM_guardedalloc.h"
#define GET_TIME() BLI_time_now_seconds()
struct TimedFunction {
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;
};
struct TimerContainer {
ListBase funcs;
};
static TimerContainer GlobalTimer = {{nullptr}};
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<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 = nullptr;
}
}
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()
{
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()
{
for (TimedFunction *timed_func = static_cast<TimedFunction *>(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()
{
LISTBASE_FOREACH (TimedFunction *, timed_func, &GlobalTimer.funcs) {
if (!timed_func->persistent) {
timed_func->tag_removal = true;
}
}
}
void BLI_timer_on_file_load()
{
remove_non_persistent_functions();
}