i want to generate interrupt every 100 microseconds on windows. Actually i couldnt do this on windows,because windows does not guarantee the interrupts less then 500 microseconds. So, i generate 2 threads. One of them is for timer counter(query performance counter), the other thread is the actual work. When timer counter is 100 microseconds, it change the state of the other thread(actual work) . But i have problem with race condition, because i dont want the threads wait each others, they must always run. So actually i need interrupts. How do i write such fast interrupt on windows with c++?

- 109,796
- 11
- 89
- 185

- 47
- 8
-
2Operating systems schedule your process at their own discretion. They very rarely provide any sort of guarantee of when your process will be scheduled, other than minimum delays. – Thomas Jager Jul 06 '20 at 12:32
-
I cannot understand what you mean? @Thomas Jager – DikotaLolly Jul 06 '20 at 12:36
-
1Windows decides when your program is running. You don't have full control over when you run, you can only ask and hope that Windows does what you want. 100 us is a very small amount of time. What are you actually trying to accomplish? It seems like you're trying to do something real-time, which is not particularly well-suited to full desktop operating systems. – Thomas Jager Jul 06 '20 at 12:38
-
1Unrelated: Do it in one thread. `auto sleeper = std::chrono::steady_clock::now(); while(true) { sleeper += 100us;
; std::this_thread::sleep_until(sleeper); }` – Ted Lyngmo Jul 06 '20 at 12:51 -
1With that kind of constraints, you need a real-time OS. Please explain your use case in more detail. To be able to help you, we need a better understanding why "the state of the other thread" (?) needs to be changed at such a high frequency. – Ruud Helderman Jul 06 '20 at 12:53
-
2[XY problem](http://xyproblem.info)? I suspect that whatever you want to do, you'r doing it wrong *and* You are not telling us what you *actually* want to do, so we can help you do it properly. – Jesper Juhl Jul 06 '20 at 13:47
1 Answers
To avoid having two threads communicating when you have these short time windows, I'd put both the work and the timer in a loop in one thread.
- Take a sample of the clock when the thread starts and add 100μs to that each loop.
- Sleep until the calculated time occurs. Normally, one would use
std::this_thread::sleep_until
to do such a sleep, but in this case, when the naps are so short, it often becomes a little too inaccurate, so I suggest busy-waiting in a tight loop that just checks the time. - Do your work.
In this example a worker thread runs for 10s without doing any real work. On my machine I could add work consisting of ~3000 additions in the slot where you are supposed to do your work before the whole loop started taking more than 100μs, so you'd better do what you aim to do really fast.
Example:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
using namespace std::chrono_literals;
static std::atomic<bool> running = true;
using myclock = std::chrono::steady_clock;
void worker() {
int loops = 0;
auto sleeper = myclock::now();
while(running) {
++loops; // count loops to check that it's good enough afterwards
// add 100us to the sleeper time_point
sleeper += 100us;
// busy-wait until it's time to do some work
while(myclock::now() < sleeper);
// do your work here
}
std::cout << loops << " (should be ~100000)\n";
}
int main() {
auto th = std::thread(worker);
// let the thread work for 10 seconds
std::this_thread::sleep_for(10s);
running = false;
th.join();
}
Possible output:
99996 (should be ~100000)
It takes a few clock cycles to get the thread started so don't worry about the number of loops not being exactly on target. Double the time the thread runs and you should still stay close to the target number of loops. What matters is that it's pretty good (but not realtime-good) once it's started running.

- 93,841
- 5
- 60
- 108
-
I just found a loop just like this in Unreal Engine. It was chewing up 4% of all CPUs. You should use several thread yield calls per each call to get the time, if you have anything else running at all. – JeffW Jan 18 '23 at 16:38
-
@JeffW _"You should use several thread yield calls per each call to get the time"_ - No, that defeats the purpose of making these short busy wait sleeps as accurate as possible. If the sleeps are a bit longer than "short", I'd suggest to `sleep_for` or `sleep_until` - but for a shorter period than what you actually want and then busy wait the remaining time. – Ted Lyngmo Jan 18 '23 at 16:43
-
That's what I thought at first, too. So I do it in 3 loops, based on the time left to sleep. 7 yields per get time call, then 3, then 1 at the end. It gets within 1 context switch worth of time that way, without hammering the cpu unnecessarily. – JeffW Jan 19 '23 at 17:11
-
@JeffW Yielding will have very different results in different implementations. In some, it's more or less a no-op and I've found that sleeping for 1ns is needed to actually make it yield. In that case, sleeping _almost_ until it's time to wake up and then busy waiting a very short time does get it very close the target. The only platform dependent questionmark in that solution is to find a good value for how long the duration _almost_ needs to be to always sleep short. If the chosen constant is too big, it'll busy wait longer than necessary. To small and it'll miss the target. – Ted Lyngmo Jan 19 '23 at 17:24