Appearance
Timers: interval
vix::timers::interval() is a tiny utility that runs a repeating timer loop on a dedicated thread, and posts the actual work to an executor.
This design keeps timing separate from execution:
- the timer thread only wakes up and schedules
- the executor runs the callback (potentially on a pool)
Files
vix/timers/interval.hpp
Key types
vix::timers::IntervalHandle
RAII handle that owns:
- a shared stop flag (
IntervalHandle::State) - a worker thread that wakes up every period and posts the task
When the handle is destroyed, it stops the loop and joins the thread.
Important members:
std::shared_ptr<State> statestd::thread t
Important methods:
stopNow()stops and joins (safe to call multiple times)- destructor calls
stopNow()(RAII)
API
IntervalHandle interval(IExecutor& exec, milliseconds period, function<void()> fn, TaskOptions opt = {})
Behavior:
- Creates
IntervalHandlewith a sharedState{stop=false} - Starts a thread that:
- computes
next = now + period - loops:
- exits if handle is gone or
stop=true exec.post(fn, opt)sleep_until(next)next += period
- exits if handle is gone or
- computes
- Returns the handle
Notes:
- The return handle controls lifetime. If you drop it, the interval stops.
- The callback is posted to
exec. It does not run on the timer thread. - The scheduling is “fixed cadence” using
sleep_until(next)thennext += periodto reduce drift.
Typical usage
1) Store the handle in a long-lived owner (server, app)
cpp
#include <vix/timers/interval.hpp>
class MyServer {
public:
explicit MyServer(vix::executor::IExecutor& exec) : exec_(exec) {}
void start() {
metrics_ = vix::timers::interval(
exec_,
std::chrono::seconds(5),
[this] { collectMetrics(); },
{} // TaskOptions
);
}
void stop() {
metrics_.stopNow(); // optional; destructor also stops
}
private:
void collectMetrics() {
// read counters, log, etc
}
vix::executor::IExecutor& exec_;
vix::timers::IntervalHandle metrics_{};
};2) Stop explicitly
cpp
auto h = vix::timers::interval(exec, 250ms, []{ /* ... */ });
/* ... */
h.stopNow(); // stops loop + joins threadConcurrency and safety
IntervalHandleis movable, not copyable.stopNow()is idempotent:- sets
stop=trueif state exists - joins the thread if joinable
- sets
- The worker thread captures
execby reference.- Make sure
execoutlives the interval handle.
- Make sure
- The loop uses a
weak_ptrto detect handle destruction safely.
Practical guidance
- Use it for “background periodic work”:
- executor metrics logging
- housekeeping tasks
- cache refresh
- Keep the posted callback short. If it is heavy, your executor should route it appropriately (priority, heavy routes, separate pool).
- If you need stronger timer semantics (jitter control, cancel callbacks already queued), that logic should live in the executor or in a higher-level scheduler.