Last active
June 23, 2023 06:06
-
-
Save jclay/a5bb9dcf7044201833a48cdf80536f26 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int demo_modes() { | |
static int counter = 0; | |
auto increment_counter = [] { | |
counter++; | |
println("count: {}", counter); | |
}; | |
// Timer ticks every 100ms and prints the latest count | |
auto t = RepeatingTimer(Milliseconds(100), increment_counter); | |
// Enter the selfish run loop and stop being selfish after 1 second | |
CFRunLoopRunInMode( | |
/* mode */ kSelfishMode, | |
/* seconds to run in this mode */ Seconds(1).ToSecondsF(), | |
/* returnAfterSourceHandled */ false); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct RepeatingTimer { | |
using Callback = std::function<void()>; | |
RepeatingTimer(TimeDelta interval, Callback callback) | |
: callback_holder_(std::move(callback)), interval_(interval) { | |
CFRunLoopTimerContext timerContext = { | |
.version = 0, | |
.info = &callback_holder_, | |
.retain = nullptr, | |
.release = nullptr, | |
.copyDescription = nullptr, | |
}; | |
timer_ref_ = AdoptCFRef(CFRunLoopTimerCreate( | |
/* allocator */ kCFAllocatorDefault, | |
/* fireDate */ CFAbsoluteTimeGetCurrent(), | |
/* interval */ interval_.ToSecondsF(), | |
/* flags */ 0, | |
/* order */ 0, | |
/* callout */ &TimerCallbackTrampoline, | |
/* context */ &timerContext)); | |
CFRunLoopAddTimer(CFRunLoopGetMain(), timer_ref_, kCFRunLoopCommonModes); | |
} | |
~RepeatingTimer() { | |
// Detach the timer, the `ScopedCFTypeRef` will release the ref on the timer after. | |
CFRunLoopRemoveTimer(CFRunLoopGetMain(), timer_ref_, kCFRunLoopCommonModes); | |
} | |
// Move only | |
RepeatingTimer(RepeatingTimer&&) = default; | |
RepeatingTimer& operator=(RepeatingTimer&&) = default; | |
RepeatingTimer(const RepeatingTimer&) = delete; | |
RepeatingTimer& operator=(const RepeatingTimer&) = delete; | |
private: | |
struct CallbackHolder { | |
void Run() { cb_(); } | |
Callback cb_; | |
}; | |
// Called every `interval_` seconds by the CFRunLoop | |
static void TimerCallbackTrampoline(CFRunLoopTimerRef timer, void* info) { | |
// Cast the opaque pointer back to our callback, and run. | |
static_cast<CallbackHolder*>(info)->Run(); | |
} | |
CallbackHolder callback_holder_; | |
TimeDelta interval_; | |
ScopedCFTypeRef<CFRunLoopTimerRef> timer_ref_; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment