9 #include <condition_variable>
12 using std::future, std::condition_variable, std::thread, std::mutex, std::future_status, std::lock_guard, std::chrono_literals::operator
""ms, std::shared_ptr, std::make_shared;
18 template <
typename TFutureResult>
20 return f.wait_for(0ms) == future_status::ready;
23 future<void> *futurePtr =
nullptr;
28 template <
typename... TArgs>
29 function<
void(TArgs...)>
debounce(
function<
void(TArgs...)>
f,
int periodMillis) {
30 auto state = make_shared<DebouceState>();
31 function<
void(TArgs...)> fn = [
f, periodMillis, state](TArgs... args) {
32 const lock_guard<mutex> lock(state->futureMutex);
34 if (state->futurePtr !=
nullptr &&
isFutureDone(*state->futurePtr)) {
35 delete state->futurePtr;
36 state->futurePtr =
nullptr;
38 if (state->futurePtr ==
nullptr) {
40 auto callWithWait = std::bind(
41 [&,
f, periodMillis, state](TArgs... args) {
42 sleepMillis(periodMillis);
43 while (nowMillis() < state->expectedEndTimestampMillis) {
44 sleepMillis(state->expectedEndTimestampMillis - nowMillis());
49 state->futurePtr =
new future<void>(std::move(std::async(std::launch::async, callWithWait)));
51 state->expectedEndTimestampMillis =
nowMillis() + periodMillis;
63 bool timeoutReached();
67 timespec beginTime, lastMeasuredTime;
71 bool executeWithTimeout(
const function<
void()> &action, std::chrono::milliseconds timeoutMillis);