C++ timer utilities | sleep_for, sleep_until, and chrono literals
이 글의 핵심
How to delay threads with chrono, avoid system_clock sleep_until pitfalls, fixed-rate loops, and when to use asynchronous timers instead of blocking sleep.
What are timer utilities?
Delays and timing using <thread> and <chrono>.
#include <thread>
#include <chrono>
using namespace std::chrono_literals;
std::this_thread::sleep_for(1s);
auto wakeup = std::chrono::system_clock::now() + 5s;
std::this_thread::sleep_until(wakeup);
sleep_for
using namespace std::chrono_literals;
std::this_thread::sleep_for(100ms);
std::this_thread::sleep_for(2s);
std::this_thread::sleep_for(1min);
Practical examples
Example 1: Periodic loop
using namespace std::chrono_literals;
void periodicTask() {
while (true) {
std::cout << "tick" << std::endl;
std::this_thread::sleep_for(1s);
}
}
Example 2: sleep_until
using namespace std::chrono;
using namespace std::chrono_literals;
void scheduledTask() {
auto now = system_clock::now();
auto nextRun = now + 5s;
std::cout << "Scheduled in 5s" << std::endl;
std::this_thread::sleep_until(nextRun);
std::cout << "run" << std::endl;
}
Example 3: Precision-oriented timer (busy/yield hybrid)
using namespace std::chrono;
using namespace std::chrono_literals;
class PrecisionTimer {
steady_clock::time_point start;
public:
PrecisionTimer() : start(steady_clock::now()) {}
void waitFor(milliseconds duration) {
auto target = start + duration;
while (steady_clock::now() < target) {
std::this_thread::yield();
}
}
auto elapsed() const {
return duration_cast<microseconds>(
steady_clock::now() - start
);
}
};
int main() {
PrecisionTimer timer;
timer.waitFor(100ms);
std::cout << "Elapsed: " << timer.elapsed().count() << " μs" << std::endl;
}
Example 4: Timeout polling
using namespace std::chrono;
using namespace std::chrono_literals;
bool waitForCondition(milliseconds timeout) {
auto deadline = steady_clock::now() + timeout;
while (steady_clock::now() < deadline) {
if (checkCondition()) {
return true;
}
std::this_thread::sleep_for(10ms);
}
return false;
}
int main() {
if (waitForCondition(5s)) {
std::cout << "condition met" << std::endl;
} else {
std::cout << "timeout" << std::endl;
}
}
yield
std::this_thread::yield();
while (!ready) {
std::this_thread::yield();
}
Common pitfalls
Pitfall 1: Accuracy
using namespace std::chrono_literals;
auto start = std::chrono::steady_clock::now();
std::this_thread::sleep_for(100ms);
auto end = std::chrono::steady_clock::now();
auto actual = duration_cast<milliseconds>(end - start);
std::cout << "Actual: " << actual.count() << " ms" << std::endl;
Pitfall 2: Clock choice for sleep_until
// ❌ system_clock — user can change wall time
auto wakeup = std::chrono::system_clock::now() + 5s;
std::this_thread::sleep_until(wakeup);
// ✅ steady_clock for relative deadlines
auto wakeup = std::chrono::steady_clock::now() + 5s;
std::this_thread::sleep_until(wakeup);
Pitfall 3: Busy-wait
while (!ready) { }
while (!ready) {
std::this_thread::yield();
}
while (!ready) {
std::this_thread::sleep_for(1ms);
}
Pitfall 4: Very short sleep
std::this_thread::sleep_for(std::chrono::microseconds(1));
Measuring elapsed time
using namespace std::chrono;
auto start = steady_clock::now();
std::this_thread::sleep_for(100ms);
auto end = steady_clock::now();
auto elapsed = duration_cast<milliseconds>(end - start);
std::cout << "Elapsed: " << elapsed.count() << " ms" << std::endl;
Common patterns
- Relative delay:
sleep_for(d)— at leastd(often longer). - Wake at time_point:
sleep_until(tp)— usesteady_clockfor monotonic deadlines. - Polling: short
sleep_forin a loop to avoid burning CPU. - Deadline style:
deadline = steady_clock::now() + timeout— same idea as steady_clock.
using namespace std::chrono_literals;
void fixed_rate_loop() {
auto next = std::chrono::steady_clock::now();
const auto interval = 1s;
for (int i = 0; i < 10; ++i) {
next += interval;
do_tick();
std::this_thread::sleep_until(next);
}
}
Asio timers (sketch)
For async servers, prefer asio::steady_timer / asio::system_timer on the io_context instead of blocking worker threads.
steady_timer: monotonic—timeouts, retries, heartbeats.system_timer: wall-clock—jobs at a local time of day.
See network guide — post/dispatch/defer for executors and strands.
Thread sleep blocks that thread; Asio timers can fire without blocking other handlers on the same io_context.
Advanced: periodic work
- Fixed rate: naive
sleep_for(interval)drifts by work duration;next += interval; sleep_until(next)tracks wall-clock spacing better. - Backoff: exponential retry with cap and jitter for network clients.
- Shutdown: use
std::stop_token(C++20) or an atomic flag to exit long loops cleanly.
Advanced: retry with deadline
#include <chrono>
#include <thread>
template <class Fn>
bool retry_with_deadline(Fn&& fn, std::chrono::steady_clock::time_point deadline,
std::chrono::milliseconds backoff) {
while (std::chrono::steady_clock::now() < deadline) {
if (fn()) return true;
std::this_thread::sleep_for(backoff);
}
return false;
}
Performance notes
- Sub-millisecond sleep often resolves to tens–hundreds of microseconds on many OSes.
- Tight poll + sleep still costs scheduler wakeups—tune the minimum poll interval.
- yield-only loops can still burn a core—prefer sleep or proper blocking primitives.
- Many threads each sleeping still adds scheduler load—consider one reactor + timer queue.
FAQ
Q1: sleep_for?
A: Block for (at least) a duration.
Q2: sleep_until?
A: Block until a time_point.
Q3: yield?
A: Hint to reschedule; lighter than sleep, heavier than blocking on a condvar.
Q4: Accuracy?
A: Best-effort minimum; actual wait is often longer.
Q5: Very short sleeps?
A: OS scheduler granularity limits usefulness.
Q6: Learning resources?
A: C++ Concurrency in Action, C++ Primer, cppreference — sleep_for.
Related posts (internal)
- C++ Chrono guide
- C++ Chrono
- C++ steady_clock
Practical tips
Debugging
- Fix warnings first.
- Reproduce minimally.
Performance
- Profile before optimizing.
Code review
- Follow team conventions.
Production checklist
Before coding
- Right tool?
- Maintainable?
- Meets timing requirements?
While coding
- Warnings cleared?
- Edge cases covered?
At review
- Intent clear?
- Tests sufficient?
Keywords
C++, timer, sleep, thread, chrono
Related posts
- C++ Chrono guide |
- C++ Calendar & Timezone |
- C++ Chrono literals |
- C++ Chrono |
- C++ duration |