Tell me please, here is a quote from reference section 3 ("Running an event loop") of Nick Mathewson's book on Libevent:
By default, the event_base_loop() function runs an event_base until
there are no more events registered in it.
Honestly, I just can't understand this phrase.
What means - "until there are no more events registered".
How does a loop know that there are no more new events ?? There can be a time interval between events - 1 second, 1 hour ...
How does Libevent know that events are over?
PS: I'm trying to compare the work of the event_base_loop () function with the GetQueuedCompletionStatus () function on windows and I don't get it. Because GetQueuedCompletionStatus works in an infinite loop - whether there are events or not - GetQueuedCompletionStatus waits for an infinitely new event and does not complete if there are none.
PS1:I was in a hurry and did not finish the chapter on "Working with an event loop".
It says that you can redefine the behavior of the event_base_loop () function by passing it a flag in the second parameter - EVLOOP_NO_EXIT_ON_EMPTY.
This will mean that the function will wait for new events indefinitely or until I want to exit the event_base_loop () loop manually via event_base_loopbreak / event_base_loopexit.
Note it says "no more events registered", rather than "no more events". By default, the event loop will exit when the event base runs empty, even though more events could happen later. This is restated in a different way both later in the chapter:
Ordinarily, the loop will exit as soon as it has no pending or active events.
and in the API documentation for event_base_loop():
By default, this loop will run the event base until either there are no more pending or active events, or until something calls event_base_loopbreak() or event_base_loopexit().
As noted in the question, EVLOOP_NO_EXIT_ON_EMPTY can change this behavior to work more like a typical event queue, waiting for events (unless EVLOOP_NONBLOCK was set) and dispatching them when they arrive.
"Running an event loop" contains pseudocode for event_base_loop() that should also help clarify the behavior.
In comparison, GetQueuedCompletionStatus will wait for and operate on a single packet (note: the wait is not likely a busyloop but based on some other multitasking technologies, such as interrupts and thread synchronization primitives; the exact method is an implementation detail, and shouldn't affect use). It's most similar to event_base_loop() with the flags EVLOOP_ONCE | EVLOOP_NO_EXIT_ON_EMPTY, though event_base_loop may process multiple events of the same priority if they happen to come in before the first event is fully handled. Coming from the other direction, if 0 is passed for the dwMilliseconds argument to GetQueuedCompletionStatus, it behaves like event_base_loop()'s default behavior, exiting immediately if there are no packets in the I/O completion queue.
Related
I've been struggling with this for a day now and I can't figure out what is wrong with my code. I'm coding in Rust but this is more of a Windows' api related problem.
// first, I'm installing a keyboard hook for the current thread
let hook = SetWindowsHookExW(
WH_KEYBOARD_LL,
Some(low_level_keyboard_proc), // just forwards the call with CallNextHookEx
ptr::null_mut(),
0,
);
assert!(!hook.is_null(), "Failed to install the hook");
let mut message: MSG = mem::zeroed();
GetMessageW(&mut message, ptr::null_mut(), 0, 0);
// The GetMessageW function is known to block the calling thread until a new message is sent.
// The thing is: my `low_level_keyboard_proc` handle *does get* called, so I know events are being received.
// I don't understand why the GetMessageW function never returns even though events are being processed.
// Note that my handler does not get called when I remove the GetMessageW function.
println!("Unreachable code...");
UnhookWindowsHook(hook);
I tried to use the PeekMessageW function instead but the problem is the same: the function always return FALSE (no events received) even though the handler is getting properly called.
If I remove the SetWindowsHookExW part, GetMessageW is still blocking the thread BUT if I remove the GetMessageW part and put an infinite loop it its place, the handler does not get called anymore.
... so here is the question: why does the GetMessageW function never return? And if this behaviour is normal, how am I supposed to use the message that I provide to GetMessageW.
I'm assuming I don't understand well the relationship between GetMessageW and SetWindowsHookExW.
EDIT: I understand that I can't catch the messages sent to the keyboard hook I created. Now, what would the "right" way to retrieve keyboard messages look like? Because it would be real handy to be able to get those messages directly from the message loop instead of having to send them back from the callback function to my main code using static structures.
I'm trying to create an event loop that can be used regardless of a context or the focus of a window. The idea is retrieving those messages directly from a message loop and dispatch them using a user-defined custom handler that can be used through safe rust code.
There are no window messages or thread messages being posted to the message queue of the thread that is installing the keyboard hook, so there are no messages for GetMessageW() to return TO YOU.
However, SetWindowsHookEx() uses its own messages internally when a low-level keyboard hook crosses thread/process boundaries. That is why you don't need to implement your hook in a DLL when hooking other applications. When a keyboard action occurs, a private message is sent TO THE SYSTEM targeting the thread that installed the hook.
That is why the installing thread needs a message loop. The simple act of performing message retrieval in your code is enough to get those internal messages dispatched properly, which is why your callback function is being called. You just won't see those private messages, which is why GetMessageW() blocks your code.
The same thing happens when you SendMessage() to a window across thread boundaries. The receiving thread needs a message loop in order for the message to be dispatched to the target window, even though the message doesn't go through the receiving thread's message queue. This is described in the SendMessage() documentation:
If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code.
So, what happens with SetWindowsHookEx() is that it creates a hidden window for itself to receive its private messages, sent via SendMessage(), when keyboard activity is detected in a different thread/process and needs to be marshaled back to your installing thread. This is described in the LowLevelKeyboardProc documentation:
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
libuv has a void uv_close(uv_handle_t* handle, uv_close_cb close_cb) method to close handles which takes a callback.
As the title says, is the handle active (in terms of I/O) before close_cb is called? For example, can a UDP handle fire a receive callback and a timer handle fire a timer callback before close_cb?
The closest thing in the documentation I could find is "Handles that wrap file descriptors are closed immediately but close_cb will still be deferred to the next iteration of the event loop." However, I'm not sure which handles fall into this criteria and more importantly, what "closed immediately" means exactly (stops all callbacks? stops only new callbacks? removed from the event loop entirely?).
The type of a libuv handle determines whether the handle would fire its dedicated callback even after un_close(handle) completed and before the uv_close_cb is invoked, so there's no general answer for that.
For example, uv_tcp_t may fire the callback connect_req->cb() or uv_udp_t may fire send_cb() (from uv_udp_send_t) again while many other types of handle don't (see uv__finish_close() in /src/unix/core.c).
All handles are no longer able to use as soon as uv_close() cleared the flag UV_HANDLE_ACTIVE of the given handle and set the flag UV_HANDLE_CLOSING. You are NOT allowed to use the closing handle by invoking corresponding functions immediately after uv_close() , if you still do so, the corresponding functions may either return error or give you assertion failure (e.g. uv_timer_start() and uv_poll_start())
uv_close() doesn't remove the handle from the event loop, instead it moves the closing handle to the internal list of the loop (only for later closing process), then you call uv_run() again, which will actually process all closing handles, depending on the type of closing handle, the closing handle fires its callback whenever necessary (e.g. uv__stream_destroy() in uv__finish_close()) , finally uv_run() invoke the callback uv_close_cb
(see the source at here)
I'm learning libev and I've stumbled upon this question. Assume that I want to process something as soon as possible but not now (i.e. not in the current executing function). For example I want to divide some big synchronous job into multiple pieces that will be queued so that other callbacks can fire in between. In other words I want to schedule a callback with timeout 0.
So the first idea is to use ev_timer with timeout 0. The first question is: is that efficient? Is libev capable of transforming 0 timeout timer into an efficient "call as soon as possible" job? I assume it is not.
I've been digging through libev's docs and I found other options as well:
it can artificially delay invoking the callback by using a prepare or idle watcher
So the idle watcher is probably not going to be good here because
Idle watchers trigger events when no other events of the same or higher priority are pending
Which probably is not what I want. Prepare watchers might work here. But why not check watcher? Is there any crutial difference in the context I'm talking about?
The other option these docs suggest is:
or more sneakily, by reusing an existing (stopped) watcher and pushing it into the pending queue:
ev_set_cb (watcher, callback);
ev_feed_event (EV_A_ watcher, 0);
But that would require to always have a stopped watcher. Also since I don't know a priori how many calls I want to schedule at the same time then I would have to have multiple watchers and additionally keep track of them via some kind of list and increase it when needed.
So am I on the right track? Are these all possibilities or am I missing something simple?
You may want to check out the ev_prepare watcher. That one is scheduled for execution as the last handler in the given event loop iteration. It can be used for 'Execute this task ASAP' implementations. You can create dedicated watcher for each task you want to execute, or you can implement a queue with a one prepare watcher that is started once queue contains at least one task.
Alternatively, you can implement similar mechanism using ev_idle watcher, but this time, it will be executed only if the application doesn't process any 'higher priority' watcher handlers.
I have one problem. I'm creating interface generation library, called libgreattao. It is able to using many backends to rendering GUI, while running in GUI mode. The problem is in GTK+2.0 backend. I must run main loop and on some event exits from it to destroy window in next step. On window's destroy event I will exit from main loop again - and do only this. Why I call main loop again? Because I must handle events created, while destroying window(window must destroy all it's control and hide). The problem is: callback for destroy signal is called once gtk_widget_destroy is called. I must ensure callback pass by application are called in main loop to allow exit from it, so I define custom signal for class GTKWIDGET. Of course, I can use workarounds, like destroying window in first signal type(the signal which ends main loop), but my library should works in any cases.
I have found solution, but not very good. I must add timeout event, which will emit my signal. I didn't find better solution yet.
When running an event loop in libuv using the uv_run function, there's a "mode" parameter that is used with the following values:
UV_RUN_DEFAULT
UV_RUN_ONCE
UV_RUN_NOWAIT
The first two are obvious. UV_RUN_DEFAULT runs the event loop until there are no more events, and UV_RUN_ONCE processing a single event from the loop. However, UV_RUN_NOWAIT doesn't seem to be a separate mode, but rather a flag that can be ORed with one of the other two values.
By default, this function blocks until events are done processing, and UV_RUN_NOWAIT makes it nonblocking, but any documentation I can find on it ends there. My question is, if you run the event loop nonblocking, how are callbacks handled?
The libuv event model is single-threaded (reactor pattern), so I'd assume it needs to block to be able to call the callbacks, but if the main thread is occupied, what happens to an event after it's processed? Will the callback be "queued" until libuv gets control of the main thread again? Or will the callbacks be dispatched on another thread?
Callbacks are handled in the same manner. They will run within the thread that is in uv_run().
Per the documentation:
UV_RUN_DEFAULT: Runs the event loop until the reference count drops to zero. Always returns zero.
UV_RUN_ONCE: Poll for new events once. Note that this function blocks if there are no pending events. Returns zero when done (no active handles or requests left), or non-zero if more events are expected (meaning you should run the event loop again sometime in the future).
UV_RUN_NOWAIT: Poll for new events once but don't block if there are no pending events.
Consider the case where a program has a single watcher listening to a socket. In this scenario, an event would be created when the socket has received data.
UV_RUN_DEFAULT will block the caller even if the socket does not have data. The caller will return from uv_run(), when either:
The loop has been explicitly stopped, via uv_stop()
No more watchers are running in the loop. For example, the only watcher has been stopped.
UV_RUN_ONCE will block the caller even if the socket does not have data. The caller will return from uv_run(), when any of the following occur:
The loop has been explicitly stopped, via uv_stop()
No more watchers are running in the loop. For example, the only watcher has been stopped.
It has handled a max of one event. For example, the socket received data, and the user callback has been invoked. Additional events may be ready to be handled, but will not be handled in the current uv_run() call.
UV_RUN_NOWAIT will return if the socket does not have data.
Often times, running an event-loop in a non-blocking manner is done to integrate with other event-loops. Consider an application that has two event loops: libuv for backend work and Qt UI (which is driven by its own event loop). Being able to run the event loop in a non-blocking manner allows for a single thread to dispatch events on both event-loops. Here is a simplistic overview showing two libuv loops being handled by a single thread:
uv_loop_t *loop1 = uv_loop_new();
uv_loop_t *loop2 = uv_loop_new();
// create, initialize, and start a watcher for each loop.
...
// Handle two event loops with a single thread.
while (uv_run(loop1, UV_RUN_NOWAIT) || uv_run(loop2, UV_RUN_NOWAIT));
Without using UV_RUN_NOWAIT, loop2 would only run once loop1 or loop1's watchers have been stopped.
For more information, consider reading the Advanced Event Loops and Processes sections of An Introduction to libuv.