[Xcb] Feature Request: Function "xcb_test_for_event"
Josh Triplett
josh at joshtriplett.org
Mon Apr 8 14:22:58 PDT 2013
On Sat, Apr 06, 2013 at 01:46:14PM +0200, Christian Heller wrote:
> Hi Josh,
>
> thanks for replying.
>
> > Detecting events by polling periodically is highly inefficient; you
> > really want some mechanism that will block until you recieve an event.
> > So, first of all, I would not recommend adding an "xcb_test_for_event"
> > function, because I don't see any way you could use it without polling.
> [..]
>
> you are right in that this kind of "busy waiting" (loop + sleep) that
> I use is not very efficient. A blocking function would be much nicer.
> However, I cannot use "xcb_wait_for_event" for reasons I explain following.
>
> CYBOI tries to offer all possible communication channels transparently.
> Application programmers should write their programme in CYBOL (XML) only.
> All they have to do is write "send" or "receive" and give a "channel",
> e.g.: inline text, file, terminal, serial_port, x_window_system, socket.
> The rest is done by CYBOI internally.
>
> CYBOI starts up, runs the usual event loop, handles events, shuts down.
> This all in the main thread. Additional threads may be started ONLY for
> detection, but NOT for reception or sending of data. This is to avoid
> memory conflicts. Just a design decision that I wouldn't like to change.
>
> Now, the "detection" threads somehow have to inform the "main" thread,
> if data arrived on some channel. This is done via simple "int" variables,
> something like an internal interrupt request (irq) flag. So I have to
> use "busy waiting" at least on this point of the code.
>
> Detection of the different channels is done like this:
> - terminal: fgetwc + ungetwc
> - serial_port: fgetc + ungetc
> - socket: accept
> - x_window_system: int n = XEventsQueued(d, QueuedAfterReading);
>
> The terminal and serial_port functions are blocking, which is nice.
> But I have to write back the received character with "ungetc". Why?
> Because the receiving of data shall be done in the main thread only.
> For the socket, all that is to be stored is a single integer number
> representing the client socket, which is not that problematic.
You don't need to get a character to block on a terminal or serial port.
You should just select() or poll() or epoll() or similar on the file
descriptor. Likewise with sockets, and in fact you can watch many file
descriptors with a single select/poll/epoll/etc. That'll eliminate the
unget.
Ideally, you should use one of those calls on your main thread rather
than flag variables. If you have to wait on something for which you
don't have a file descriptor, you could always spin off a thread and
have it write a byte to a pipe when ready, then add the read end of the
pipe as another file descriptor to block on.
You might also look at timerfd, signalfd, and similar calls; those make
it possible to include even more things in your select/poll/epoll.
Depending on your target platforms, you may also find the portable
libevent or libev wrappers useful, rather than calling epoll or similar
directly.
> Concerning "x_window_system": If using "xcb_wait_for_event", I am
> forced to store the event received in the "detection" thread.
> Then, the main thread gets informed that events are available.
> In the main thread, I would have to use that stored first event
> and receive further events using "xcb_poll_for_event", because the
> main thread is not allowed to block, since further communication
> might occur on other channels.
>
> I'd prefer not to store any event in the "detection" thread.
> It would be nicer to have a function just notifying me if there are
> events available (a simple int flag returned, no event).
> Ideally -- you are right -- that function would be a BLOCKING one!
> So, if you could make "xcb_test_for_event" blocking, even better.
>
> > For your use case, you really want a blocking function like
> > xcb_wait_for_event, but without actually returning the event;
> > it should block until at least one event exists to return.
>
> Yes, exactly. This is what I need. Thanks for clarifying.
OK, glad to hear that blocking would work for you.
Ideally I'd still love to have some way for XCB to just supply a file
descriptor you can block on, but I don't know if the structure of the X
protocol would reasonably allow that. Failing that, an
xcb_block_until_event or xcb_wait_for_event_noret or similar call seems
vaguely reasonable.
> > That still seems suboptimal for the purposes of most event loops (which
> [..]
>
> I am aware of the disadvantages of "busy waiting". But this is the
> price of flexibility in CYBOI. All communication channels shall be
> used easily. In effect, CYBOI with its irq flags (between "detection"
> threads and "main" thread) tries to do what is an operating system's task.
>
> I am constantly looking for optimisations and am thankful for ideas.
You should definitely look into the select/poll/epoll family of
syscalls.
- Josh Triplett
More information about the Xcb
mailing list