diff options
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_timer.h | 58 | ||||
-rw-r--r-- | source/blender/blenlib/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_timer.c | 186 |
3 files changed, 246 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_timer.h b/source/blender/blenlib/BLI_timer.h new file mode 100644 index 00000000000..6dfb13fd738 --- /dev/null +++ b/source/blender/blenlib/BLI_timer.h @@ -0,0 +1,58 @@ +/* + * ***** 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) 2008 Blender Foundation. + * All rights reserved. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_TIMER_H__ +#define __BLI_TIMER_H__ + +#include "BLI_utildefines.h" + +/** \file BLI_timer.h + * \ingroup BLI + */ + +/* ret < 0: the timer will be removed. + * ret >= 0: the timer will be called again in ret seconds */ +typedef double (*BLI_timer_func)(uintptr_t uuid, void *user_data); +typedef void (*BLI_timer_data_free)(uintptr_t uuid, void *user_data); + +/* `func(...) < 0`: The timer will be removed. + * `func(...) >= 0`: The function will be called again in that many seconds. */ +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); + +bool BLI_timer_is_registered(uintptr_t uuid); + +/* Returns False when the timer does not exist (anymore). */ +bool BLI_timer_unregister(uintptr_t uuid); + +/* Execute all registered functions that are due. */ +void BLI_timer_execute(void); + +void BLI_timer_free(void); + +#endif /* __BLI_TIMER_H__ */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 5e6764a5c0e..91887c1ef5e 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -55,6 +55,7 @@ set(SRC intern/BLI_memarena.c intern/BLI_memiter.c intern/BLI_mempool.c + intern/BLI_timer.c intern/DLRB_tree.c intern/array_store.c intern/array_store_utils.c @@ -214,6 +215,7 @@ set(SRC BLI_task.h BLI_threads.h BLI_timecode.h + BLI_timer.h BLI_utildefines.h BLI_utildefines_iter.h BLI_utildefines_stack.h diff --git a/source/blender/blenlib/intern/BLI_timer.c b/source/blender/blenlib/intern/BLI_timer.c new file mode 100644 index 00000000000..875b667de46 --- /dev/null +++ b/source/blender/blenlib/intern/BLI_timer.c @@ -0,0 +1,186 @@ +/* + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file, with exception of below: + * + * ***** 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 Main; +struct ID; +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; + } +} |