I have been looking around and I can't seem to find a module that allows me to block the current process until the timer is done. What I don't want to do is utilize the CPU while waiting (busy waiting). I want the process to be blocked/suspended by the operating system and will be automatically notified when the timer is done.
# use a system call to create a waitable timer
timer = CreateWaitableTime()
# use another system call that waits on a waitable object
WaitFor(timer) # this will block the current process until the timer is signaled
# .. sometime in the future, the timer might expire and it's object will be signaled
# causing the WaitFor(timer) call to resume operation
do_other_stuff() # after timer
Edit
The reason for this is that I am going to have another process spawn this processes, therefore it doesn't matter if these get blocked. They need to be able to wait without wasting CPU time.
from threading import Event
evnt = Event()
wait_for = 5 #seconds
evnt.wait(wait_for) # will block for 5 seconds, or unless set early
another thread can call set to early finish the wait above
evnt.set()
Related
How can I pause execution for a certain amount of time in Godot?
I can't really find a clear answer.
The equivalent of Thread.Sleep(1000); for Godot is OS.DelayMsec(1000). The documentation says:
Delays execution of the current thread by msec milliseconds. msec must be greater than or equal to 0. Otherwise, delay_msec will do nothing and will print an error message.
Note: delay_msec is a blocking way to delay code execution. To delay code execution in a non-blocking way, see SceneTree.create_timer. Yielding with SceneTree.create_timer will delay the execution of code placed below the yield without affecting the rest of the project (or editor, for EditorPlugins and EditorScripts).
Note: When delay_msec is called on the main thread, it will freeze the project and will prevent it from redrawing and registering input until the delay has passed. When using delay_msec as part of an EditorPlugin or EditorScript, it will freeze the editor but won't freeze the project if it is currently running (since the project is an independent child process).
One-liner:
yield(get_tree().create_timer(1), "timeout")
This will delay the execution of the following line for 1 second.
Usually I make this to a sleep() function for convenience:
func sleep(sec):
yield(get_tree().create_timer(sec), "timeout")
Call it with sleep(1) to delay 1 second.
How does libuv and the operating system actually schedule timers like setTimeout and setInterval in Node.js? I see that no CPU is used by the node process until a timer fires. Does this mean the OS schedules the timer, and wakes up the Node process when the timer is fired? If so, how does an OS schedule a timer and how exactly does the hardware execute it?
Timer callbacks are executed as part of the NodeJS event loop. When you call setTimeout or setInterval, libuv (the C library which implements the NodeJS event loop) creates a timer in a 'min heap' data structure which is called the timers heap. In this data structure, it keeps track of the timestamp that each timer expires at.
At the start of each fresh iteration of the event loop, libuv calls uv__update_time which in turn calls a syscall to get the current time and updates the current loop time up to a millisecond precision. (https://github.com/nodejs/node/blob/master/deps/uv/src/unix/core.c#L375)
Right after that step comes the first major phase of the event loop iteration, which is timers phase. At this phase, libuv calls uv__run_timers to process all the callbacks of expired timers. During this phase, libuv traverses the timers heap to identify expired timers based on the 'loop time' it just updated using uv__update_time. Then it invokes the callbacks of all those expired timers.
Following is a redacted snippet from the event loop implementation in NodeJS to highlight what I just described.
while (r != 0 && loop->stop_flag == 0) {
uv__update_time(loop);
uv__run_timers(loop);
// ...redacted for brevity...
r = uv__loop_alive(loop);
if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
break;
}
I wrote a series of articles on NodeJS event loop some time back. I hope this article from that series would be helpful. https://blog.insiderattack.net/timers-immediates-and-process-nexttick-nodejs-event-loop-part-2-2c53fd511bb3
Node uses libuv underneath to take care of this. While setTimeout has some internal managing of its own, it ends up using the uv_timer_t facility provided by libuv.
Lets assume that the only thing the event loop is doing is the timer. libuv will calculate the poll timeout, which will actually be the timer's due time (in this example). Then the event loop will block for i/o by using the appropriate syscall (epoll_wait, kevent, etc). At that point it's up to the kernel to decide what to do, but the current thread of execution is blocked until the kernel wakes it up again, so there is no used CPU here, because nothing is happening.
Once the timeout expires, the aforementioned syscall will return, and libuv will process the due timers and i/o.
I have a requirement wherein I start a timer and will do a particular task for a certain time. Once the timer expires,I shall set a global variable in the handler. This variable is checked continuously by my process. The process stops once the global variable is set.
But the problem with setitimer as in its description is " When any timer expires, a signal is sent to the process, and the timer (potentially) restarts. "
How do I stop the timer in my handler?
From the getitimer(3p) man page:
Setting it_value to 0 shall disable a timer, regardless of the value of
it_interval.
if a threadA is sleeping, how will another thread threadB call threadA to start ?
Please provide an example if possible.
Instead of sleeping you will want to create an EventWaitHandle and use WaitOne with a timeout.
When you want the thread to wake-up early, you will simply set the event to signaled.
First create the EventWaitHandle:
wakeUpEvent = new EventWaitHandle(false, EventResetMode.ManualReset);
Then in your thread:
wakeUpEvent.WaitOne(new TimeSpan(1, 0, 0));
When the main program wants to wake up the thread early:
wakeUpEvent.Set();
Note: You can either set the event to auto reset or manual reset. Auto reset means once WaitOne returns from the event, it will set it back to non signaled. This is useful if you are in a loop and you signal multiple times.
A thread can be started by waiting on a WaitObject and having the other thread calling the Set method on it. Look at the WaitHandle.WaitOne method.
Here's article that may be of help as well.
I have designed an application which is running 20 instance of a thread.
for(int i = 0;i<20;i++)
{
threadObj[i].start();
}
How can I wait in the main thread until those 20 threads finish?
You need to use QThread::wait().
bool QThread::wait ( unsigned long time = ULONG_MAX )
Blocks the thread until either of
these conditions is met:
The thread associated with this
QThread object has finished execution (i.e. when it returns from
run()). This function will return true if the thread has finished. It
also returns true if the thread has
not been started yet.
time milliseconds has elapsed. If time is
ULONG_MAX (the default), then the wait
till never timeout (the thread must
return from run()). This function
will return false if the wait timed
out.
This provides similar functionality to
the POSIX pthread_join() function.
Just loop over the threads and call wait() for each one.
for(int i = 0;i < 20;i++)
{
threadObj[i].wait();
}
If you want to let the main loop run while you're waiting. (E.g. to process events and avoid rendering the application unresponsible.) You can use the signals & slots of the threads. QThread's got a finished() singal which you can connect to a slot that remembers which threads have finished yet.
You can also use QWaitCondition
What Georg has said is correct. Also remember you can call signal slot from across threads. So you can have your threads emit a signal to you upon completion. SO you can keep track of no of threads that have completed their tasks/have exited. This could be useful if you don't want your Main thread to go in a blocking call wait.