As an example of using poll let’s return to the socket server described in the previous chapter. If this isn't the case we need to make the call to accept non-blocking. The simplest way of doing this is to OR SOCK_NONBLOCK in the call to socket:
int sockfd = socket(server→ai_family,
server->ai_socktype| SOCK_NONBLOCK,
server->ai_protocol);
This change makes the attempt to read from the socket:
int client_fd = accept(sockfd, (struct sockaddr *) &client_addr, &addr_size);
return immediately but with -1 if there is no data to read. Our only solution is to repeatedly attempt to read the data using accept:
for(;;){
int client_fd = accept(sockfd,
(struct sockaddr *) &client_addr, &addr_size);
if(client_fd>0){
process the data;
}
You can see that this keeps the thread busy in a tight polling loop.
A much better solution is to use poll to suspend the thread until there is data to read:
The call now waits until there is data read to read from the socket or timeout occurs after 10 seconds. This means we can follow the call with code to read the data, but only after checking that the event occurred and it wasn’t a timeout or a signal:
if (fdset[0].revents & POLLIN) {
int client_fd = accept(sockfd, (struct sockaddr *) &client_addr, &addr_size);
process data:
Of course this only allows one client to use the server. We still need to put the poll and the processing in a loop:
struct pollfd fdset[1];
for (;;) {
fdset[0].fd = sockfd;
fdset[0].events = POLLIN;
fdset[0].revents = 0;
poll(fdset, 1, 10000);
if (fdset[0].revents & POLLIN) {
int client_fd = accept(sockfd, (struct sockaddr *) &client_addr, &addr_size);
int n = read(client_fd, buffer, 2048);
printf("%s", buffer);
n = write(client_fd, data, strlen(data));
close(client_fd);
printf("client request");
fflush(stdout);
}
if (fdset[0].revents == 0) {
printf("timeout");
fflush(stdout);
}
}
Notice that you have to initialize the struct for each call to poll and you can also add a check for a timeout.
You can make this much more sophisticated but this is the basic idea. It is common for example to pass the request on to a separate thread so that the loop can go back to waiting for the next client.
Under Linux the closest you can get to an interrupt in user space is to use the poll or select function to wait on a file descriptor.
This might seem restrictive, but as most things in Linux are presented as files it usually provides a way of achieving the same result as a true interrupt.
If you use poll or select on a thread then the thread is suspended until the file descriptor is ready to be processed. This looks wasteful, but the system can run another thread while the original is waiting.
The closest you can get to an interrupt in user space is to poll or select on a new thread. The new thread waits for the event and then runs the equivalent of the interrupt handler.
Lightbend, the company that developed Akka, has announced Akka 3, and has changed its name to Akka. The company produces cloud-native microservices frameworks, and Akka is used for building distribute [ ... ]
The Wasmer team has released Wasmer 5.0. The WebAssembly runtime adds experimental support for more back ends including V8, Wasmi and WAMR. It also now has iOS support, and upgraded compilers includin [ ... ]