16 #include <condition_variable>
35 using slot = std::function<void()>;
62 ~TimerObservable()
override {
67 m_observable(observer),
70 this->nextExecution = std::chrono::system_clock::now() + ms;
74 void notify()
override {
75 if (std::chrono::system_clock::now() >= this->nextExecution) {
76 this->isFinished = std::async(std::launch::async, [
this] {
77 if (this->m_observable !=
nullptr) {
78 this->m_observable->Update();
82 this->nextExecution = std::chrono::system_clock::now() +
interval;
85 this->isFinish =
true;
90 bool toDestroy()
override {
91 return isFinish && this->timerMode ==
singleshot;
98 std::chrono::time_point<std::chrono::system_clock> nextExecution;
99 std::future<void> isFinished;
105 ~SlotObservable()
override {
108 SlotObservable(
slot fPointer,
timer_mode mode, std::chrono::milliseconds ms) :
111 functionPointer(std::move(fPointer)),
114 this->nextExecution = std::chrono::system_clock::now() + ms;
117 void notify()
override {
118 if (std::chrono::system_clock::now() >= this->nextExecution) {
120 auto p = std::async(std::launch::async, [
this] {
122 if (this->functionPointer !=
nullptr) {
123 this->functionPointer();
124 this->promise.set_value(
true);
126 this->promise.set_value(
false);
127 }
catch(std::future_error &e) {
128 std::cout <<
"future already satisfied" << e.what() << std::endl;
132 this->nextExecution = std::chrono::system_clock::now() +
interval;
135 this->isFinish =
true;
140 bool toDestroy()
override {
141 return isFinish && this->timerMode ==
singleshot;
144 std::future<bool>& getFut() {
145 return this->isFinished;
151 std::chrono::time_point<std::chrono::system_clock> nextExecution;
152 std::future<bool> isFinished;
153 std::promise<bool> promise;
154 slot functionPointer;
161 ~FutureObservable()
override {
164 FutureObservable(
slot fPointer, std::shared_future<bool> sfuture) : sfut(std::move(sfuture)),
165 functionPointer(std::move(fPointer)),
169 void notify()
override {
170 if (this->sfut.valid()) {
171 if(this->sfut.get()) {
172 this->isFinished = this->isFinishedPromise.get_future();
173 auto promise = std::async(std::launch::async, [
this] {
174 if (this->functionPointer !=
nullptr) {
175 this->functionPointer();
176 this->isFinish =
true;
177 this->isFinishedPromise.set_value(
true);
179 this->isFinishedPromise.set_value(
false);
186 bool toDestroy()
override {
187 return this->isFinish;
190 std::future<bool>& getFut() {
191 return this->isFinished;
195 std::future<bool> isFinished;
196 std::promise<bool> isFinishedPromise;
197 std::shared_future<bool> sfut;
198 slot functionPointer;
207 if (instance ==
nullptr) {
208 instance = std::make_shared<Timer>();
213 static std::future<bool>&
singleShot(
const slot &functionPointer, std::chrono::milliseconds ms) {
221 static std::future<bool>&
futureWatch(
const slot &functionPointer,
const std::shared_future<bool>& fut) {
226 for (
auto it = this->v_observables.begin(); it != this->v_observables.end(); it++) {
227 this->v_observables.erase(it--);
229 this->b_isRunning =
false;
233 Timer::instance->b_isRunning =
false;
237 return Timer::instance->b_isRunning;
243 this->wait_thread->detach();
249 if (this->time > ms) {
252 this->v_observables.push_back(std::make_unique<TimerObservable>(observer, mode, ms));
261 this->wait_thread = std::make_unique<std::thread>(&Timer::dispatcher,
this);
262 this->time = std::chrono::milliseconds(1000);
266 std::future<bool>& AttachFutureWatcher(
const slot &functionPointer,
const std::shared_future<bool>& sfut) {
268 auto o = std::make_unique<FutureObservable>(functionPointer, sfut);
269 std::future<bool> &fut{o->getFut()};
270 this->v_observables.push_back(std::move(o));
274 std::future<bool>& AttachSingleshot(
const slot &functionPointer, std::chrono::milliseconds ms) {
276 if (this->time > ms) {
279 auto o = std::make_unique<SlotObservable>(functionPointer,
singleshot, ms);
280 auto &fut = o->getFut();
281 this->v_observables.push_back(std::move(o));
287 if (this->time > ms) {
290 this->v_observables.push_back(std::make_unique<SlotObservable>(functionPointer, mode, ms));
295 std::unique_lock<std::mutex> lck{mtx};
296 for (
int i{10}; i > 0 && b_isRunning; --i) {
297 cv.wait_for(lck, time / 10);
299 for (
auto it = this->v_observables.begin(); it != this->v_observables.end(); it++) {
301 if ((*it)->toDestroy()) {
302 (*it).reset(
nullptr);
303 this->v_observables.erase(it--);
309 }
while (this->b_isRunning);
310 for (
auto it = this->v_observables.begin(); it != this->v_observables.end(); it++) {
311 this->v_observables.erase(it--);
317 std::condition_variable
cv{};
318 std::vector<std::unique_ptr<IObservable>> v_observables;
320 std::unique_ptr<std::thread> wait_thread;
321 std::atomic_bool b_isRunning{};
322 std::chrono::milliseconds time{};
324 static std::shared_ptr<Timer> instance;