Search code examples
csynchronizationpthreadspipepolling

C: connection between threads with pipe, synchronization needed?


I'm dealing with pipe communications between threads in C programming. I have 2 threads:

-thread 1 just manage some events,

-thread 2 communicates with a serial port;

Thread 1 and 2 communicates with a pipe.

The "events manager" thread if there are some conditions should send a string to the "serial manager" with e.g. pipe[1], which is polling out from serial port and from pipe[0]. Then if there's a string from pipe[0] it should do his work.

The problem is that thread 1 writes faster than threads 2 reads. So my question is: how do I have to properly read from pipe[0]? How do I have a queue? Because if I use read simply in blocking way just typing in thread 2:

read(pipe[0], string, sizeof(string)-1)

thread 2 reads all the thread 1 overload messages;

The only solution that I found is to create another pipe that blocks thread 1 (because thread 1 starts to read after writing, read is in blocking way), so thread 1 waits until thread 2 has done is work (this is useful 'cause I can get response from thread2), but my question is: is this the correct way? My convinction is that I'm missing something about read function.


Solution

  • "[I]s this the correct way [to read variable-length asynchronous messages over a FIFO, processing them one at a time]?"

    No, you do not need to synchronize a single producer sending variable-length messages over a FIFO to a single consumer to process the messages one at a time.

    As you documented in your own answer, you could add a record terminator to the messages. You could implement a simple protocol that describes the length of each message (c.f. netstrings).

    There's a lot of prior practice you can borrow here. For example, you don't need to read record-terminated messages one character at a time, but could locally buffer partial messages — think of what stdio does to turn bytestreams into lines. The constraint that there's only one consumer makes some things easy.

    "[I]s this the correct way [to send variable-length asynchronous messages between threads]?"

    It's serviceable but perhaps not ideal.

    A message-oriented, queuing channel might be better suited here: message queues or a datagram socket pair.