I wann transfer data between threads by eventfd. So I write the following codes to meet my need. My host OS is openSUSE v12.3 64bit.
#include "stdio.h"
#include "unistd.h"
#include "pthread.h"
#include "sys/eventfd.h"
#include "sys/epoll.h"
#define nil NULL
int efd = -1;
void* read_thread(void* arg) {
int ret = 0;
uint64_t count = 0;
int ep_fd = -1;
struct epoll_event events[10];
(void)(arg);
if (efd < 0) {
printf("efd not inited.\n");
return nil;
}
ep_fd = epoll_create(1024);
if (ep_fd < 0) {
perror("epoll_create fail: ");
return nil;
}
{
struct epoll_event read_event;
read_event.events = EPOLLIN;
read_event.data.fd = efd;
ret = epoll_ctl(ep_fd, EPOLL_CTL_ADD, efd, &read_event);
if (ret < 0) {
perror("epoll ctl failed:");
return nil;
}
}
while (1) {
ret = epoll_wait(ep_fd, events, 10, 5000);
if (ret > 0) {
int i = 0;
for (i = 0; i < ret; i++) {
if (events[i].events & (EPOLLHUP | EPOLLERR)) {
printf("epoll eventfd has epoll hup.\n");
break;
} else if (events[i].events & EPOLLIN) {
int event_fd = events[i].data.fd;
ret = eventfd_read(event_fd, &count);
if (ret < 0) {
perror("read fail:");
break;
} else {
printf("read %llu\n", count);
}
}
}
} else if (ret == 0) {
break;
} else {
perror("epoll wait error:");
break;
}
}
close(ep_fd);
return nil;
}
int main(int argc, char *argv[]) {
pthread_t pid = 0;
uint64_t count = 0;
int ret = 0;
int i = 0;
efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
if (efd < 0) {
perror("eventfd failed.");
return -1;
}
ret = pthread_create(&pid, NULL, read_thread, NULL);
if (ret < 0) {
perror("pthread create:");
close(efd);
return -2;
}
for (i = 0; i < 5; i++) {
count = i + 1;
ret = eventfd_write(efd, count);
if (ret < 0) {
perror("write event fd fail:");
break;
} else {
printf("write %llu\n", count);
}
}
sleep(3);
pthread_join(pid, NULL);
close(efd);
efd = -1;
return 0;
}
I think the behaviour of eventfd should be like a pipe. So the program's output result may be as follows:
write 1 read 1 write 2 read 2 write 3 read 3 write 4 read 4 write 5 read 5
However, its actual result is:
write 1 write 2 write 3 write 4 write 5 read 15
or
write 1 write 2 write 3 write 4 write 5 read 1 read 14
Can some nice guys tell me why the output results is the sum of input results?
I can not tranfer data correctly by eventfd between threads. I also do not like the pipe. How can I transfer data one by one correctly between threads?
eventfd uses a counter maintained by the kernal starting with the value provided to eventfd(). this counter is incremented by the value 'sent' via write(), so if you create the eventfd with the initial value of 1 and then write() 2, the value that you read will be 3. if you then write() 5, the read() value will be 8 and so on.
eventfd is commonly used by threads within event driven patterns, but you'll need to use a queue or other container to pass an actual value, or check out signalfd() which can be used to recive data attached to signals by sigqueue().
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With