This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/blenlib/intern/BLI_timer.c
Campbell Barton c0f88ed8a8 Cleanup: sort forward declarations of enum & struct
Done using:
  source/tools/utils_maintenance/c_sort_blocks.py
2019-01-28 21:17:58 +11:00

185 lines
4.5 KiB
C

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2018 Blender Foundation.
* All rights reserved.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/blenlib/intern/BLI_timer.c
* \ingroup bli
*/
#include "BLI_timer.h"
#include "BLI_listbase.h"
#include "BLI_callbacks.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;
bool file_load_cb_registered;
} TimerContainer;
static TimerContainer GlobalTimer = {{0}};
static void ensure_callback_is_registered(void);
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)
{
ensure_callback_is_registered();
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) {
if (timed_func->tag_removal) {
return false;
}
else {
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();
}
struct ID;
struct Main;
static void remove_non_persistent_functions(struct Main *UNUSED(_1), struct ID *UNUSED(_2), void *UNUSED(_3))
{
LISTBASE_FOREACH(TimedFunction *, timed_func, &GlobalTimer.funcs) {
if (!timed_func->persistent) {
timed_func->tag_removal = true;
}
}
}
static bCallbackFuncStore load_post_callback = {
NULL, NULL, /* next, prev */
remove_non_persistent_functions, /* func */
NULL, /* arg */
0 /* alloc */
};
static void ensure_callback_is_registered()
{
if (!GlobalTimer.file_load_cb_registered) {
BLI_callback_add(&load_post_callback, BLI_CB_EVT_LOAD_POST);
GlobalTimer.file_load_cb_registered = true;
}
}