13 #include <condition_variable>
36 using slot = std::function<void()>;
66 ~TimerObservable()
override{};
69 timerMode(mode), m_observable(observer),
interval(ms), isFinish(
false)
71 this->nextExecution = std::chrono::system_clock::now() + ms;
77 if (std::chrono::system_clock::now() >= this->nextExecution)
79 this->isFinished = std::async(std::launch::async,
82 if (this->m_observable !=
nullptr)
84 this->m_observable->Update();
89 this->nextExecution = std::chrono::system_clock::now() +
interval;
94 this->isFinish =
true;
102 return isFinish && this->timerMode ==
singleshot;
109 std::chrono::time_point<std::chrono::system_clock> nextExecution;
110 std::future<void> isFinished;
117 ~SlotObservable()
override
121 SlotObservable(
slot fPointer,
timer_mode mode, std::chrono::milliseconds ms) :
122 timerMode(mode),
interval(ms), functionPointer(std::move(fPointer)), isFinish(
false)
125 this->nextExecution = std::chrono::system_clock::now() + ms;
131 if (std::chrono::system_clock::now() >= this->nextExecution)
134 auto p = std::async(std::launch::async,
139 if (this->functionPointer !=
nullptr)
141 this->functionPointer();
142 this->promise.set_value(
true);
144 this->promise.set_value(
false);
146 catch (std::future_error& e)
148 std::cout <<
"future already satisfied" << e.what()
154 this->nextExecution = std::chrono::system_clock::now() +
interval;
159 this->isFinish =
true;
167 return isFinish && this->timerMode ==
singleshot;
173 return this->isFinished;
179 std::chrono::time_point<std::chrono::system_clock> nextExecution;
180 std::future<bool> isFinished;
181 std::promise<bool> promise;
182 slot functionPointer;
189 ~FutureObservable()
override
193 FutureObservable(
slot fPointer, std::shared_future<bool> sfuture) :
194 sfut(std::move(sfuture)), functionPointer(std::move(fPointer)), isFinish(
false)
201 if (this->sfut.valid())
203 if (this->sfut.get())
205 this->isFinished = this->isFinishedPromise.get_future();
206 auto promise = std::async(std::launch::async,
209 if (this->functionPointer !=
nullptr)
211 this->functionPointer();
212 this->isFinish =
true;
213 this->isFinishedPromise.set_value(
true);
215 this->isFinishedPromise.set_value(
false);
224 return this->isFinish;
230 return this->isFinished;
234 std::future<bool> isFinished;
235 std::promise<bool> isFinishedPromise;
236 std::shared_future<bool> sfut;
237 slot functionPointer;
243 static std::shared_ptr<Timer>
246 if (instance ==
nullptr)
248 instance = std::make_shared<Timer>();
253 static std::future<bool>&
265 static std::future<bool>&
273 for (
auto it = this->v_observables.begin(); it != this->v_observables.end(); it++)
275 this->v_observables.erase(it--);
277 this->b_isRunning =
false;
283 Timer::instance->b_isRunning =
false;
289 return Timer::instance->b_isRunning;
298 this->wait_thread->detach();
310 this->v_observables.push_back(std::make_unique<TimerObservable>(observer, mode, ms));
321 this->wait_thread = std::make_unique<std::thread>(&Timer::dispatcher,
this);
322 this->time = std::chrono::milliseconds(1000);
327 AttachFutureWatcher(
const slot& functionPointer,
const std::shared_future<bool>& sfut)
330 auto o = std::make_unique<FutureObservable>(functionPointer, sfut);
331 std::future<bool>& fut{o->getFut()};
332 this->v_observables.push_back(std::move(o));
337 AttachSingleshot(
const slot& functionPointer, std::chrono::milliseconds ms)
344 auto o = std::make_unique<SlotObservable>(functionPointer,
singleshot, ms);
345 auto& fut = o->getFut();
346 this->v_observables.push_back(std::move(o));
358 this->v_observables.push_back(std::make_unique<SlotObservable>(functionPointer, mode, ms));
366 std::unique_lock<std::mutex> lck{mtx};
367 for (
int i{10}; i > 0 && b_isRunning; --i)
369 cv.wait_for(lck, time / 10);
371 for (
auto it = this->v_observables.begin(); it != this->v_observables.end(); it++)
374 if ((*it)->toDestroy())
376 (*it).reset(
nullptr);
377 this->v_observables.erase(it--);
383 }
while (this->b_isRunning);
384 for (
auto it = this->v_observables.begin(); it != this->v_observables.end(); it++)
386 this->v_observables.erase(it--);
391 std::condition_variable
cv{};
392 std::vector<std::unique_ptr<IObservable>> v_observables;
394 std::unique_ptr<std::thread> wait_thread;
395 std::atomic_bool b_isRunning{};
396 std::chrono::milliseconds time{};
398 static std::shared_ptr<Timer> instance;