CS2-Kit
C++23 library for CS2 Metamod:Source plugin development
Loading...
Searching...
No Matches
Scheduler.cpp
Go to the documentation of this file.
1#include <CS2Kit/Core/Scheduler.hpp>
2
3#include <algorithm>
4#include <chrono>
5
6namespace CS2Kit::Core
7{
8
9int64_t Scheduler::GetCurrentTimeMs() const
10{
11 return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch())
12 .count();
13}
14
15uint64_t Scheduler::Delay(int64_t delayMs, std::function<void()> callback)
16{
17 uint64_t id = _nextId++;
18 _timers.push_back({id, GetCurrentTimeMs() + delayMs, 0, std::move(callback)});
19 return id;
20}
21
22uint64_t Scheduler::Repeat(int64_t intervalMs, std::function<void()> callback)
23{
24 uint64_t id = _nextId++;
25 _timers.push_back({id, GetCurrentTimeMs() + intervalMs, intervalMs, std::move(callback)});
26 return id;
27}
28
29uint64_t Scheduler::DelayAndRepeat(int64_t delayMs, int64_t intervalMs, std::function<void()> callback)
30{
31 uint64_t id = _nextId++;
32 _timers.push_back({id, GetCurrentTimeMs() + delayMs, intervalMs, std::move(callback)});
33 return id;
34}
35
36uint64_t Scheduler::NextTick(std::function<void()> callback)
37{
38 return Delay(0, std::move(callback));
39}
40
41void Scheduler::Cancel(uint64_t id)
42{
43 _timers.erase(std::remove_if(_timers.begin(), _timers.end(), [id](const Timer& t) { return t.Id == id; }),
44 _timers.end());
45}
46
47void Scheduler::CancelAll()
48{
49 _timers.clear();
50}
51
52void Scheduler::OnGameFrame()
53{
54 if (_timers.empty())
55 return;
56
57 int64_t now = GetCurrentTimeMs();
58
59 // Snapshot the IDs to fire instead of indices: callbacks may Cancel() other timers
60 // (or themselves) which erases from _timers and invalidates indices/references.
61 std::vector<uint64_t> toFire;
62 for (const auto& t : _timers)
63 {
64 if (now >= t.NextFireTime)
65 toFire.push_back(t.Id);
66 }
67
68 for (uint64_t id : toFire)
69 {
70 // Re-find by ID — the timer may have been cancelled by an earlier callback in this batch.
71 auto it = std::find_if(_timers.begin(), _timers.end(), [id](const Timer& t) { return t.Id == id; });
72 if (it == _timers.end())
73 continue;
74
75 // Copy out before invoking — the callback can mutate _timers (including reallocating it).
76 int64_t interval = it->Interval;
77 auto callback = it->Callback;
78
79 if (callback)
80 callback();
81
82 // Re-find again: the callback may have cancelled this timer.
83 it = std::find_if(_timers.begin(), _timers.end(), [id](const Timer& t) { return t.Id == id; });
84 if (it == _timers.end())
85 continue;
86
87 if (interval > 0)
88 it->NextFireTime = now + interval;
89 else
90 _timers.erase(it);
91 }
92}
93
94} // namespace CS2Kit::Core