Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <mail@jlucke.com>2018-11-26 22:25:15 +0300
committerJacques Lucke <mail@jlucke.com>2018-11-26 22:25:15 +0300
commitc1adf938e6c8ecaec805f4cf95c73480de1bf980 (patch)
tree2e097af6b8bbf8383463b0d4f54ad011321177ff /source/blender/blenlib/intern
parentd5778b5bc1663b14449c90d4bc0e84d56f64c156 (diff)
Timer: Generic BLI_timer with Python wrapper
There is a new `bpy.app.timers` api. For more details, look in the Python API documentation. Reviewers: campbellbarton Differential Revision: https://developer.blender.org/D3994
Diffstat (limited to 'source/blender/blenlib/intern')
-rw-r--r--source/blender/blenlib/intern/BLI_timer.c186
1 files changed, 186 insertions, 0 deletions
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;
+ }
+}