The correct way to pause a C++ program is std::this_thread::sleep_for(std::chrono::milliseconds(500)), from <thread> and <chrono>. It is portable, it releases the CPU while it waits, and unlike the old platform specific calls it takes a typed duration rather than a bare integer whose unit you have to remember. If you know the exact moment you want to wake up rather than how long to wait, use sleep_until instead.
<thread> and <chrono>, add using namespace std::chrono_literals;, then write std::this_thread::sleep_for(2s); or sleep_for(250ms);. Compile with g++ -std=c++20 -Wall -Wextra -pthread. Never spin in an empty loop to pass time.Every program below was compiled and run with GCC 13.3 using g++ -std=c++20 -Wall -Wextra -pthread and produced the output shown. Sleep durations are always a lower bound: the standard promises you will sleep at least as long as requested, never that you will wake up exactly then.
sleep_for with chrono literals
The chrono literals turn a duration into something readable. Bring them into scope with a using declaration inside the function, not at namespace scope in a header.
#include <iostream>
#include <thread>
#include <chrono>
int main() {
using namespace std::chrono_literals;
std::cout << "start\n" << std::flush;
std::this_thread::sleep_for(2s);
std::cout << "two seconds later\n";
std::this_thread::sleep_for(250ms);
std::this_thread::sleep_for(std::chrono::microseconds(500));
std::cout << "done\n";
return 0;
}g++ -std=c++20 -Wall -Wextra -pthread delay.cpp -o delay
./delay
# start
# two seconds later
# doneNote the std::flush on the first line. Standard output to a terminal is line buffered, but redirect it to a file and it becomes fully buffered, so without the flush all three lines appear at once when the program exits. That trips people up when they are using a delay to watch progress.
| Literal | Long form | Meaning |
|---|---|---|
2h | std::chrono::hours(2) | Two hours |
30min | std::chrono::minutes(30) | Half an hour |
2s | std::chrono::seconds(2) | Two seconds |
250ms | std::chrono::milliseconds(250) | A quarter second |
500us | std::chrono::microseconds(500) | Half a millisecond |
100ns | std::chrono::nanoseconds(100) | Below scheduler resolution |
You can mix them freely, because chrono durations compose: sleep_for(1s + 500ms) compiles and means what it looks like. That is the real advantage over an integer API where you have to know whether the argument is seconds or milliseconds.
sleep_until for absolute deadlines
When you are pacing work rather than pausing between steps, sleeping until a point in time avoids accumulating drift.
#include <iostream>
#include <thread>
#include <chrono>
int main() {
using namespace std::chrono_literals;
auto deadline = std::chrono::steady_clock::now() + 1500ms;
for (int i = 0; i < 3; ++i) {
std::cout << "tick " << i << '\n' << std::flush;
std::this_thread::sleep_for(300ms);
}
std::this_thread::sleep_until(deadline);
std::cout << "deadline reached\n";
return 0;
}The loop takes about 900 ms, then the final sleep_until waits out whatever remains of the 1500 ms budget. Had the loop overrun the deadline, sleep_until would have returned immediately rather than adding more delay, which is exactly the behavior you want in a frame loop.
A fixed rate loop without drift
This is the pattern to reach for whenever you need something to happen every N milliseconds. Advance a target time by the period each iteration instead of sleeping for the period.
#include <iostream>
#include <chrono>
#include <thread>
int main() {
using namespace std::chrono_literals;
const auto period = 200ms;
auto next = std::chrono::steady_clock::now();
auto origin = next;
for (int i = 0; i < 5; ++i) {
next += period;
std::this_thread::sleep_until(next);
std::chrono::duration<double, std::milli> since = std::chrono::steady_clock::now() - origin;
std::cout << "frame " << i << " at " << static_cast<long>(since.count()) << " ms\n";
}
return 0;
}# frame 0 at 200 ms
# frame 1 at 400 ms
# frame 2 at 600 ms
# frame 3 at 800 ms
# frame 4 at 1000 msExactly on the multiples of 200. Write the same loop with sleep_for(200ms) and each iteration adds the work time plus the scheduler’s overshoot, so by frame 100 you are visibly behind. The absolute deadline absorbs both.
Measuring how long you actually slept
Use steady_clock for any duration measurement. It is monotonic, so an NTP correction or a user changing the system clock cannot make your interval negative.
#include <iostream>
#include <thread>
#include <chrono>
int main() {
using namespace std::chrono_literals;
auto t0 = std::chrono::steady_clock::now();
std::this_thread::sleep_for(200ms);
auto t1 = std::chrono::steady_clock::now();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0);
std::chrono::duration<double, std::milli> exact = t1 - t0;
std::cout << "requested 200 ms\n";
std::cout << "slept " << ms.count() << " ms (integer)\n";
std::cout << "slept " << exact.count() << " ms (double)\n";
return 0;
}# requested 200 ms
# slept 200 ms (integer)
# slept 200.132 ms (double)An overshoot of a fraction of a millisecond on an idle machine is typical. On a loaded machine, or on a general purpose desktop kernel, expect single digit milliseconds of jitter. Any design that needs tighter guarantees than that needs a real time kernel, not a different sleep function.
steady_clock measures elapsed time and never goes backward. system_clock gives wall clock time you can convert to a date, and it can jump. high_resolution_clock is an alias for one of the other two on most implementations, so prefer naming the one you actually want.Why busy waiting is wrong
Spinning in a loop until a deadline passes does produce a delay. It also pins a CPU core at 100 percent for the entire interval, which on a laptop means the fan spins up and the battery drains, and in a container means you burn your CPU quota for nothing.
#include <iostream>
#include <chrono>
#include <thread>
// Busy wait: burns a full CPU core for the whole interval. Do not do this.
void busy_wait_ms(int ms) {
auto end = std::chrono::steady_clock::now() + std::chrono::milliseconds(ms);
while (std::chrono::steady_clock::now() < end) {
// spin
}
}
int main() {
using namespace std::chrono_literals;
auto a = std::chrono::steady_clock::now();
busy_wait_ms(100);
auto b = std::chrono::steady_clock::now();
std::this_thread::sleep_for(100ms);
auto c = std::chrono::steady_clock::now();
std::chrono::duration<double, std::milli> spin = b - a;
std::chrono::duration<double, std::milli> slept = c - b;
std::cout << "spin " << spin.count() << " ms\n";
std::cout << "sleep " << slept.count() << " ms\n";
return 0;
}# spin 100 ms
# sleep 100.101 mswhile (true) {} loop with no side effects is worse than wasteful, it is undefined behavior in C++. A loop with no observable effect and no volatile access may be assumed to terminate, so the optimizer is permitted to delete it or to treat the code after it as unreachable. The version above is safe only because the clock read counts as an observable effect.The legacy platform calls
You will still meet these in older code. They work, but there is no reason to write new code with them.
| Call | Platform | Unit | Status |
|---|---|---|---|
Sleep(500) | Windows, <windows.h> | Milliseconds | Works, not portable |
sleep(2) | POSIX, <unistd.h> | Seconds | Works, whole seconds only |
usleep(500000) | POSIX, <unistd.h> | Microseconds | Removed from POSIX, avoid |
nanosleep(&ts, nullptr) | POSIX, <ctime> | Nanoseconds | The modern POSIX call |
sleep_for | Standard C++11 and later | Any chrono duration | Use this |
The unit column is the argument for switching. Reading Sleep(500) and usleep(500) side by side, one is half a second and the other half a millisecond, and nothing in the call site tells you which. sleep_for(500ms) cannot be misread and cannot be miscompiled into the wrong unit.
Waiting for an event instead of a fixed time
Very often a fixed delay is a workaround for not having a signal to wait on. If another thread will tell you when something is ready, wait on a condition variable with a timeout: you wake immediately when the work is done and still have an upper bound.
#include <iostream>
#include <chrono>
#include <thread>
#include <condition_variable>
#include <mutex>
std::condition_variable cv;
std::mutex m;
bool ready = false;
int main() {
using namespace std::chrono_literals;
std::jthread producer([]{
std::this_thread::sleep_for(300ms);
{
std::lock_guard<std::mutex> lock(m);
ready = true;
}
cv.notify_one();
});
std::unique_lock<std::mutex> lock(m);
if (cv.wait_for(lock, 2s, []{ return ready; })) {
std::cout << "woke early on the signal\n";
} else {
std::cout << "timed out after 2 s\n";
}
return 0;
}This printed woke early on the signal after about 300 ms rather than sitting through the full two seconds. The predicate form of wait_for also handles spurious wakeups for you, which the plain overload does not. For more on the threading pieces here, see our guide to using threads in C++.
Troubleshooting
The delay is ignored and everything prints at once. The sleep happened; the output did not flush. Add << std::flush or use std::endl on the lines you want to see as they happen. This is almost always the explanation when output is redirected to a file or a pipe.
error: ‘sleep_for’ is not a member of ‘std::this_thread’. Missing #include <thread>. Including <chrono> alone is not enough, and some standard libraries pull one in through the other, so a program can compile on one toolchain and fail on the next.
error: unable to find numeric literal operator ‘operator””ms’. The chrono literals are not in scope. Add using namespace std::chrono_literals; inside the function, or write the long form std::chrono::milliseconds(250).
The program sleeps far longer than requested. On Windows the default timer resolution is coarse, historically around 15 ms, so a request for 1 ms can take considerably longer. Batch small waits into one larger wait rather than issuing many tiny ones.
Sleeping in a GUI or game loop freezes the window. You blocked the thread that pumps events. Never sleep on a UI thread. Do the waiting on a worker thread, or let the framework’s own timer or vertical sync mechanism pace the loop.
Frequently asked questions
Is sleep_for accurate to the millisecond?
It guarantees a minimum, not a maximum. On a normally loaded Linux desktop, overshoot is typically well under a millisecond, and my test run of a 200 ms sleep measured 200.132 ms. Under load, or on Windows with its coarser default timer, expect several milliseconds of jitter.
What is the difference between sleep_for and sleep_until?
The first takes a duration relative to now, the second an absolute point on a clock. Use sleep_until in loops that must run at a fixed rate, because it absorbs the time your work took instead of adding to it. Use sleep_for for one off pauses.
Can I sleep for less than a millisecond?
You can request it, and the call accepts nanoseconds. Whether you get it depends on the scheduler, and a request below roughly the timer tick usually rounds up. If you truly need sub microsecond timing, you need a busy wait with a pause instruction and a good reason.
Does sleep_for block other threads?
No. It blocks only the thread that calls it, which is why it is spelled this_thread. Other threads keep running and the operating system reuses the core. That is the core difference from a busy wait, which occupies the core the whole time.
Do I need -pthread to use sleep_for?
On Linux with GCC or Clang, yes, because <thread> pulls in the threading runtime. Leaving it out may produce a link error or a binary that aborts at run time. On Windows with MSVC no extra flag is required.
Wrapping up
Reach for sleep_for with a chrono literal for a one off pause, and sleep_until with an advancing deadline whenever something has to happen at a steady rate. Measure with steady_clock, never with system_clock, and treat every sleep duration as a floor rather than a promise.
The bigger question is usually whether you need a delay at all. A fixed sleep waiting for a file to appear or a service to start is a race condition with a comfortable margin. Wait on the actual event with a condition variable and a timeout and you get both correctness and an upper bound. The cppreference page for sleep_for documents the exact guarantees, and our guides on declaring float variables in C++ and joining two vectors in C++ cover the numeric and container fundamentals that sit alongside it.
