I need to create many FIFO queues in a program, which is used for communication between threads in the same process.
I think I can use pipe() for this purpose, because in this way, I can use select or poll on the thread which fetch nodes from the queue.
int* fd_pipe = (int*)malloc(2*sizeof(int));
pipe(fd_pipe);
now the problem is how to put pointer into the queue since each node is a strucutre, I want to put the pointer into the queue, something like
typedef{ struct Packet *pkt; struct Info *info; int seq; }Node;
on threads which put node into the queue:
Node* node = (Node*)malloc(sizeof(Node));
Node->info = ...;
Node->seq = ...;
Node->pkt = ...;
write(fd_pipe[1], node, sizeof(node));
on threads which read node from the queue:
char buf[1000];
read(fd_pipe[0], buf, sizeof(node))
Node* mynode = (Node*)buf;
then the mynode is what I want.
is there anything wrong in my program? especially strict aliasing or pun type problems? thanks!
You do not have aliasing issues. Here the only issue I see is read(fd_pipe[0], buf, sizeof(node))
, this should be read(fd_pipe[0], buf, sizeof(Node *))
.
I am not sure why you use a char buffer here, I prefer
Node *node;
if (read(fd_pipe[0], &node, sizeof(node)) <= 0) {
// error, deal with it
}
It's simpler and clearer.
Now, your code will only work as is if you use blocking i/o which is the default. Also, technically, you should handle short read/writes but writing/reading on a pipe is atomic if the read/written size is less than PIPE_BUF (which is always much larger than a pointer)
You have a bit of a grey area in your code about memory synchronization before the write but since this is a system call, it will work.
A pipe is an unusual way to communicate between threads. Usually, people use in-memory queues to communicate between threads. One example is http://www.boost.org/doc/libs/1_53_0/doc/html/boost/lockfree/queue.html