To my knowledge, the select() function in C can only wait for file descriptors to become active (i.e. for reading them to not block.)
This is useful for a command-line messaging application since everything will be either a socket file descriptor, or stdin.
However, what if I want to incorporate this with a GUI application (for example, one written in Gtk?)
I assume there's no way to tell select() to wait for a button to be pressed, right? So will I have to use multithreading?
If you want to incorporate non-fd activity into a select-based event loop (or other fd-related alternatives like epoll), you can do that by using a pipe. The action triggered by the event (such as a button press) writes a description of the event into the pipe, and the select mask includes the read end of the pipe, so it will be notified of the data availability.
If the events and the handlers are in the same process, it's not necessary to fully serialise the event description, since some other mechanism could be used (a in-memory queue of events, or some such). However, since most events can be easily and efficiently described in a few bytes, serialising the event provides an easily scalable architecture.
Related
In linux, how does one generate an event to break out a select / poll / epoll loop on thread termination? Processes have a pidfd and SIGCHILD. Is there something similar for threads?
Edit: this is to directly monitor the thread termination event.
Well the most obvious solution, that comes to mind, is that one of the file descriptors being polled/selected for would be a very special file descriptor, that's reserved for that particular purpose. When you want to "break out" of the select/poll/epoll you simply need to make the appropriate arrangements for this, very special, file descriptor to become available for reading, and this will make it happen.
After select/poll/epoll returns you'll check that file descriptor, just like you would check any other one, and proceed according to whatever should happen in that event. So the only remaining part of this question is what kind of a very special file descriptor would this be?
Well, since you tagged your question with linux, you have many Linux-specific options to choose from.
You can turn off native signal handling in your process, and create a signal file descriptor. Then a sent signal to the process translates to the signal file descriptor becoming available for reading, and reading from it, as documented in the manual page, tells you that the signal has been received.
An event file descriptor could be another option, this one's more suitable for different threads in the same process notifying each other.
Both event and signal file descriptors are eminently pollable/selectable. And there's always the old-school approach of creating a pipe(), selecting/polling the read end of the pipe, and writing to the write end of the pipe to effect the notification.
On my journey to get a Software running under Windows and Linux, I had to rewrite the socket layer. On Windows I changed from select to WSAPoll and use a WSAWaitForMultipleEvents before including a standard event to cancel the operation before timeout when necessary. As I have to handle more than 1024 in and out sockets, I have to change from select to poll on linux to. Is there any way to cancel the wait on poll under linux. I have to add remoe connections, which will be slowed down by the wait timeout by the poll.
Create a pseudo internal event using pipe() and add the read side of this to the poll() list, making it the first event.
When you want to cancel the poll write a character to the pipe and poll() will return. You will know it's an internal event as it will have index 0.
You can even make this a crude messaging system by passing different values down the pipe.
You can do the same this with your Windows code using a manual event.
See this IoEvent class that does just that.
I'm doing some research on the Linux kernel, particularly the input subsystem. I'm interested in reading /dev/input/eventX device(s) for different input events (mainly keyboard and mouse).
However the read() operation blocks. The only thing I can think of is creating a state of all the keyboard keys and mouse buttons, and then create a new thread for reading keyboard and mouse states (those threads might be blocked from time to time), and from my main process, access the state of the keyboard and mouse.
However, I'm not very experienced in non blocking programming under C++ and Linux and I think that a thread for each device might be an overkill.
I'd like to know if there are other ways to handle input in non blocking way, or using threads is fine?
Thanks, skwee.
You can check out the poll system call for this. Is for handling I/O on multiple file descriptors. One possibility would be to spawn only one thread to poll for events on multiple file descriptors.
Here is some reading material : http://www.makelinux.net/ldd3/chp-6-sect-3
You can set the file description to non blocking. You can also use select/poll to check to see if data is available to be read in which case you don't need non blocking. See this thread;
Non-blocking call for reading descriptor
I have a C++ console app that uses open() [O_RDWR | O_NONBLOCK], write(), select(), read() and close() to work with device file. Also ioctl() can be called to cancel current operation. At any given time only one user can work with device.
I need to come up with C++ class having libsigc++ signals that get fired when data is available from device.
The problem: when calling select() application becomes unresponsive as it waits for the data. How to make it responsive - by calling select() in worker thread? If so - how will worker thread communicate with main thread? Maybe I should look into boost::asio?
How to make it responsive - by calling select() in worker thread
you can use dup(), this will duplicated your file descriptors... thus you can move entire read operations into another thread. thus your write thread and processing thread will be responsive, even when the read [select()] thread is in sleeping.
signal emitting overhead of libsigc++ is minimal, thus i think you can embedded code inside the read thread itself. slots can exist in different thread, this is where you will receive your signals...
I think Thrift source code [entirely boost based] might be of your interest, though thrift does not use libsigc++.
It sounds as though you've misunderstood select; the purpose of select (or poll, epoll, etc) is not "wait for data" but "wait for one or more events to occur on a series of file descriptors or a timer, or a signal to be raised".
What "responsiveness" is going missing while you're in your select call? You said it's a console app so you're not talking about a GUI loop, so presumably it is IO related? If so, then you need to refactor your select so that waiting for the data you're talking about is one element; that is, if you're using select, build FD_SETs of ALL file/socket descriptors (and stdin and stdout are file descriptors) that you want to wait on input for.
Or build a loop that periodically calls "select" with a short timeout to /test/ for any pending input and only try and read it when select tells you there is something to read.
It sounds like you have a producer-consumer style problem. There are various way to implement a solution to this problem, but most folks these days tend to use condition variable based approaches (see this C++11 based example).
There are also a number of design patterns that when implemented can help alleviate your concurrency problem, such as:
Half-Sync / Half-Async
A producer-consumer style pattern that introduces a queue between an asynchronous layer that fills the queue with events, and a synchronous layer that processes those events.
Leader / Followers
Multiple threads take turns handling events
A related discussion is available here.
I'm designing event loop for asynchronous socket IO using epoll/devpoll/kqueue/poll/select (including windows-select).
I have two options of performing, IO operation:
Non-blocking mode, poll on EAGAIN
Set socket to non-blocking mode.
Read/Write to socket.
If operation succeeds, post completion notification to event loop.
If I get EAGAIN, add socket to "select list" and poll socket.
Polling mode: poll and then execute
Add socket to select list and poll it.
Wait for notification that it is readable writable
read/write
Post completion notification to event loop of sucseeds
To me it looks like first would require less system calls when using in normal mode,
especially for writing to socket (buffers are quite big).
Also it looks like that it would be possible to reduce the overhead over number of "select"
executions, especially it is nice when you do not have something that scales well
as epoll/devpoll/kqueue.
Questions:
Are there any advantages of the second approach?
Are there any portability issues with non-blocking operations on sockets/file descriptors over numerous operating systems: Linux, FreeBSD, Solaris, MacOSX, Windows.
Notes: Please do not suggest using existing event-loop/socket-api implementations
I'm not sure there's any cross-platform problem; at the most you would have to use Windows Sockets API, but with the same results.
Otherwise, you seem to be polling in either case (avoiding blocking waits), so both approaches are fine. As long as you don't put yourself in a position to block (ex. read when there's no data, write when buffer's full), it makes no difference at all.
Maybe the first approach is easier to code/understand; so, go with that.
It might be of interest to you to check out the documentation of libev and the c10k problem for interesting ideas/approaches on this topic.
The first design is the Proactor Pattern, the second is the Reactor Pattern
One advantage of the reactor pattern is that you can design your API such that you don't have to allocate read buffers until the data is actually there to be read. This reduces memory usage while you're waiting for I/O.
from my experience with low latency socket apps:
for writes - try to write directly into the socket from writing thread (you need to obtain event loop mutex for that), if write is incomplete subscribe to write readiness with event loop (select/waitformultipleobjects) and write from event loop thread when socket gets writable
for reads - be always "subscribed" for read readiness for all sockets, so you always read from within event loop thread when the socket gets readable