Asynchronous Streams and Stream Buffers

In the standard C++ libraries, streams and stream buffers are intimately related, but distinct. The two concepts separate the concern of formatting data for input and output from the concern of writing and reading bytes or collections of bytes to/from some underlying medium such as a TCP socket, a disk file, or even a memory buffer. Thus, streams build on stream buffers in a way that allows the former to be essentially oblivious to what kind of medium is used. This separation is sound and also appears (with different names) in other well-designed I/O libraries.

In Casablanca, we retain this design as well as the nomenclature, but we make the APIs asynchronous: for most functions where there is a possibility of it blocking the library will return a PPL task instead of a value.

The two header files that implement the base stream and stream buffer classes are:
  • cpprest\streams.h
  • cpprest\astreambuf.h
The concrete implementations of these streams buffers are as follows:
  • Producer Consumer (cpprest\producerconsumerstream.h): This is a memory-based stream buffer that supports both reading and writing a sequence of bytes. A single consumer and producer pair can communicate via the buffer from different threads.
  • File Streams (cpprest\filestream.h) : Supports input and output operations for files.
  • Container Streams (cpprest\containerstream.h): This is a stream that is backed by a basic STL container. It is a memory-based stream that supports both reading and writing.
  • Raw Pointer Streams (cpprest\rawptrstream.h) : A stream buffer that is based on a raw pointer and block size. The buffer cannot be expanded or contracted, it has a fixed capacity. This stream buffer class is used to create a memory backed stream that supports both reading and writing sequence of characters from a fixed block size.
  • Interop Streams (cpprest\interopstream.h) : Supports interop between STL iostreams or WinRT streams and Casablanca async streams. Read the section below to learn more.
These files bring in everything necessary, including the Casablanca version of PPL tasks and base stream and stream buffer classes. Take a look at the samples to learn more about Asynchronous Streams.

Interop with STL iostreams

It's sometimes going to be the case that you either have an existing library that takes an std::istream or std::ostream, or returns one from one of its functions. To combine such a library with Casablanca, or other libraries you may build using Casablanca, you will need to have some means of integrating between the two. Casablanca provides two sets of classes, one to give an async stream interface to an iostream, one to give an iostream interface to an async stream.

For example, if you have an asynchronous (Casablanca) stream, but wish to use it as a standard stream, you may use one of the classes 'async_istream<CharType>', 'async_stream<CharType>,' or 'async_iostream<CharType>':

#include <cpprest\interopstream.h>
#include <cpprest\containerstream.h>

concurrency::streams::stringstreambuf strbuf;
concurrency::streams::basic_ostream<char> ss(strbuf.create_ostream());
std::basic_ostream<char> stream(concurrency::streams::async_ostream<char>(ss).rdbuf());

stream << "hello" << ", there, this is " << 4711;

Likewise, if you have a standard stream, but need to place an asynchronous facade on top of it, you can use 'stdio_istream<CharType>' or 'stdio_ostream<CharType>':

 std::stringstream stream; 
 stream << "abcdefghijklmnopqrstuvwxyz";

 concurrency::streams::stdio_istream<char> astream(stream);
 concurrency::streams::container_buffer<std::string> buffer;

Last edited Mar 15, 2014 at 12:50 AM by stevetgates, version 28