4

I have a pipe handle that was created as overlapped. I need to read and write data to it in parallel. How can I achieve this?

Named Pipe Server Using Overlapped I/O documentation page shows an example how to read and write to many pipes, but "it avoids simultaneous operations on a single pipe instance".

What is the right way to do this in C++ on Windows? I can't file the right example nor some help on the topic.

The main problem I face that normal ReadFile blocks when there is no data to read and eventually I can't write with WriteFile. I haven't found any method that can tell me is there something to read that don't block. As far as I understand I need to pass OVERLAPPED structure but don't know how to use it in case of parallel read and write to one pipe (not many).

It should be possible as it is said in Synchronous and Overlapped Pipe I/O:

Overlapped operations make it possible for one pipe to read and write data simultaneously and for a single thread to perform simultaneous I/O operations on multiple pipe handles.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Dmitry Trofimov
  • 7,371
  • 1
  • 30
  • 34
  • "*I haven't found any method that can tell me is there something to read that don't block.*" - look at [`PeekNamedPipe()`](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365779.aspx). – Remy Lebeau Mar 27 '15 at 21:28

2 Answers2

2

All you need to do is to provide a different OVERLAPPED structure to each of the simultaneous operations. In your case, all that means is that each of the two threads needs its own OVERLAPPED structure. Since the threads are presumably running different functions, this should happen automatically unless you mess it up by using a global variable.

Note that you're over-complicating things by starting from that sample, which is focused on using overlapped I/O to avoid the need for multiple threads.

Instead, pretend you're writing each of the two functions using non-overlapped I/O, but whenever you would call ReadFile or WriteFile, include a valid OVERLAPPED structure with an event handle and follow up with WaitForSingleObject. There are a few things you should know: you have to make sure that the threads each create their own event object, and you have to handle the case where the I/O operation completes immediately (i.e., returns ERROR_SUCCESS instead of ERROR_IO_PENDING). Otherwise it's all fairly straightforward.

If you can't make it work, show your code.

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158
1

As the documentation for pipes says, one process writes, another process reads. If you want to READ and WRITE, you will want two pipes, one for the "write to the other process", and one for "read the data from the other process".

[This is not unique to Windows, but since you are asking about Windows pipes, I thought it best to give the Windows docs. Linux/Unix pipes are the same way - they have two ends, a read end and a write end]

Of course, as the comment says, it seems like Windows documentations is rather contradictory (and I've only ever used windows pipes in one direction at a time).

Whilst this example doesn't read and write SIMULTANEOUSLY, I think it could relatively easily be altered so that it does.

I suspect (but since the code isn't posted) the problem is either in the call to ReadFile or in setting up the pipe itself. Overlapped calls to ReadFile are asynchronous, and you'd be required to wait for the event associated with the overlapped structure with WaitForMultipleObjects, before checking the results.

Obviously, if you are reading and writing simultaneously, you need one overlapped struct for read and one for write, to indicate which side "completed".

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • As [Synchronous and Overlapped Pipe I/O documentation](http://msdn.microsoft.com/en-us/library/windows/desktop/aa365788(v=vs.85).aspx) says: Overlapped operations make it possible for one pipe to read and write data simultaneously and for a single thread to perform simultaneous I/O operations on multiple pipe handles. – Dmitry Trofimov Aug 03 '13 at 22:09
  • Ok, I'm looking into it. – Mats Petersson Aug 03 '13 at 22:18
  • @DmitryTrofimov: As my edit says, I think you need to show what you are doing (in a small, complete, compileable example, if at all possible). – Mats Petersson Aug 03 '13 at 22:48
  • So this is the reason I've asked the question: how can the example be easily altered to work with one pipe? When do I need to Write and Read and Wait? What events should I wait? – Dmitry Trofimov Aug 03 '13 at 23:20
  • You need (at least) one overlapped structure with an event in it each for read and write. You call `ReadFile` to set up a trigger on some data arriving from the other side. When you have some data to write, you call `WriteFile`. If you have called either `ReadFile` or `WriteFile`, you shouldn't call either again until the respective event has "fired". There are several dozen different ways to achieve this, and what is "right" or "wrong" depends on what you are actually trying to do. – Mats Petersson Aug 03 '13 at 23:25
  • In one thread I read all the data that available. In another I write if I have data to write. The thing I don't get what should I check before I invoke WriteFile to be sure it is not reading now, and what to check to be sure it is not writing. Also what and when I need to wait :) – Dmitry Trofimov Aug 03 '13 at 23:55
  • As I understand it, you should be able to simultaneously read and write - in other words it shouldn't be an issue to write to the pipe and read at the same time. So in your thread that reads, after you issue a ReadFile, wait for the read overlapped event, and the thread the writes, wait for the even in the write overlapped structure. – Mats Petersson Aug 03 '13 at 23:57
  • Pipes (in Windows) can definitely be duplex. I've used duplex pipes with overlapped I/O with no problems, though I wasn't reading and writing simultaneously. – Harry Johnston Aug 08 '13 at 01:29
  • @DmitryTrofimov, I'm dealing with this issue now, and noticed the article that states _Overlapped operations make it possible for one pipe to read and write data simultaneously_. The example it points to is a sequential read/write state machine which isn't exactly concurrent. – bvj Mar 29 '15 at 01:52