Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can starting multiple asyncronous read/write operations on the same Stream corrupt the data?

I'm using asynchronous I/O because it does not block the calling thread and does the threading stuff behind the scenes. If I invoke multiple async operations like BeginWrite()'s on the same Stream, should I need to worry about that data buffer contents are mixed together?

Let's assume I want to send 3 buffers:

Buffer1: 1111111111
Buffer2: 2222222222
Buffer3: 3333333333

I don't mind if the buffers are sent in incorrect order, so

333333333311111111112222222222

is ok, but is it possible that buffer contents are got completely mixed together?

122213121212122333313111223333

PS: I'm 100% sure that someone already asked this in some form...

like image 718
Calmarius Avatar asked May 20 '11 20:05

Calmarius


1 Answers

It depends on the implementation of the Stream. For instance sockets support multiple overlapped requests both for read and for write, and so does the file API. They guarantee consistency of each operation (no interleaving content) and also order of operations: for instance for socket reads the bytes received will be placed in the buffers posted in the order posted. If these guarantees would not be provided it would impossible to write high performance network application, as overlapping Sends are desired but overlapping Receives are actually required for high performance network IO. This behavior is described in many articles, including good ole' Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports and is documented on MSDN Overlapped Input/Output:

Both send and receive operations can be overlapped. The receive functions may be invoked multiple times to post receive buffers in preparation for incoming data, and the send functions may be invoked multiple times to queue up multiple buffers to be sent. Note that while a series of overlapped send buffers will be sent in the order supplied, the corresponding completion indications may occur in a different order. Likewise, on the receiving side, buffers will be filled in the order they are supplied, but completion indications may occur in a different order.

Not surprisingly, the same guarantees carry over to the managed side of the world, eg. the NetworkStream class:

Read and write operations can be performed simultaneously on an instance of the NetworkStream class without the need for synchronization. As long as there is one unique thread for the write operations and one unique thread for the read operations, there will be no cross-interference between read and write threads and no synchronization is required.

That being said, throwing randomly async reads and writes on a Stream will result in chaos pretty quickly. Applications need to carefully orchestrate the order in which threads submit the operations so that the order is deterministic. Usually this means keeping accounting in a (synchronized) list with special care to do the async operation invocation while holding the synchronization lock.

One final note is that all these async APIs make a special note in calling out that the order of completion is not guaranteed to match the order of submission.

like image 53
Remus Rusanu Avatar answered Sep 28 '22 08:09

Remus Rusanu