You haven't made it worse, doing your own research is always praiseworthy.
The DOS times are long gone, now you can't use such things as hardware interrupts unless you're driver developer.
At the other hand the software environment is vastly improved now and you have plenty of options at your disposal.
The only thing is that you must have a knowledge how to use them.
I suspect the sleep/delay you want to do is part of some bigger plan you have, but what's the point, what you don't like about the existing ones?
About DOS times, it's as much as you said, but after the reading I 've done, damn those days were good!
As I posted here and in the lnet thread, I need more precise control for limiting CPU usage. Sleep/delay (and some other methods, waitable-something (the link is in my laptop, away)) reduce the CPU usage but their, lets say it quantum, is very large (what about microsecond or nanosecond delay?). Still, having the CPU *magicaly* triggering the next code line instead of running a loop and asking it continiously, I cannot find any reason why not.
(micro/nano seconds are too small quantities, you must have dedicated hardware to perform tasks at such a speed, as it is in micro-controllers)
But you should look more carefully at my example in reply #18.
At line 46:
Sleep(Min(100, TckTimerRemaining(T))); Here the program will sleep for the remaining time but no more than 100 ms. This is with a dual purpose: first - not to loop continuously, and second - for giving a chance to do some other work at regular intervals (100 ms) if needed.
At the first iteration it will {do some work, line 37}, will sleep 100 ms at line 46 then will wake up and repeat. Next iterations up to 20-th will do the same until the condition at line 39 satisfied (timer expired) then it will write I, increment I and re-init the timer. Thus the tick counter will be asked just 20 times (2000/100), not continuously. The figures can be modified as needed, of course. But the ratio between the timer delay and the sleep parameter is what matters for how many times the timer will be asked.
If you remove the sleep at line 46 it will bump up to 100% CPU just because the thread is
always active, but even then it will be preempted by the scheduler.
If you leave the sleep, even with a minimal value of e.g. 1, it will send the thread into the 'waiting' queue of the scheduler and that will
dramatically reduce the %CPU almost to 0. You can try it.
(Next explanation is greatly simplified) OS threads have a 'state': one of 'active', 'ready', 'waiting', etc. Usually one of them is active, few are 'ready' and all others 'waiting'. Each time the quanta of the 'active' thread expires, the scheduler makes it 'ready', picks one of other 'ready' threads and makes it the current 'active'. Those 'waiting' doesn't take CPU time, they are just waiting for their event to happen (timer or I/O). After the event they became 'ready' and candidates to be next 'active'.
According to this:
- if you don't use sleep, the thread will run until quanta expires and then will become 'ready'
- if you use sleep(0) (aka yield), the thread will voluntarily give up the remaining of its quanta and will become 'ready'
- if you use sleep(n) (n>0), the thread will yield and then will become 'waiting' for time of n ms and after that - 'ready'
In the first two cases the CPU will be at 100% and all such threads will use the CPU more or less proportionally
In the third case the thread will use just the time for executing {do some work} on each 100 ms which usually is a tiny fraction and trends to 0% compared to all others.
In addition to that there is always a special Idle process which never 'waits' anything but is of very low priority and the purpose is to always have at least one 'ready' thread. But it's not shown on the CPU graph.
Hope that shed some light on the matter