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

BLI_timer.c « intern « blenlib « blender « source - git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 8aa5521870f429c2988cafc6ebd7a777902d3166 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* 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();
}