Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

CoStream, A Bufferless Pipe Stream

5.00/5 (1 vote)
15 Dec 2014CPOL1 min read 14K   130  
This is an alternative for PipeStream, a Memory Efficient and Thread-Safe Stream

Introduction

CoStream is a bufferless alternative for PipeStream.

Background

In a producer/consumer pattern, if we know that there is a consumer that is guaranteed to read the stream to the end, or dispose it in case it can't, the synchronizing stream doesn't need to maintain its own internal buffer, relying entirely on the buffers provided by the caller(s) of the Read method. In the Read method, CoStream saves the reference to the target buffer and waits until it is filled. The Write method, on the other hand, copies data from the source buffer to the target one, signals to the reader if the buffer is ready and either waits for another Read call if there are some unconsumed data left in the source buffer, or returns to the Write caller.

Using the Code

CoStream cannot be used in a single thread. There should be at least two, reading and writing threads. Both are required to close (or dispose) the stream so that the counterpart could resume at the end.

The test program that you will find in the attached archive loads some XML file in the XmlDocument, then writes it to the instance of the CoStream:

C#
static CoStream costream = new TestCoStream();
static string outpath;

static void Main(string[] args)
{
  // ...

  XmlDocument doc = new XmlDocument();
  doc.Load(args[0]);
  outpath = args[1];

  var reading_thread = new Thread(ReaderBody);
  reading_thread.Start();

  using (var pipe = XmlWriter.Create(costream, new XmlWriterSettings { CloseOutput = true }))
    doc.Save(pipe);

  reading_thread.Join();
}

The reading thread simply copies it to the output file:

C#
static void ReaderBody()
{
  using (var reader = XmlReader.Create(costream, new XmlReaderSettings { CloseInput = true }))
  using (var writer = XmlWriter.Create(outpath))
    writer.WriteNode(reader, false);
}

TestCoStream class overrides Read, Write and Flush methods of the CoStream to show what happens in the background.

Running the program with a sample XML input file that is longer than the internal buffers used by default implementations of the XmlReader and XmlWriter (for example, this one: http://www.w3.org/2001/xml.xsd) will result in something like this:

<Writing 6143 bytes.
>Reading 4096 bytes.
>4096 bytes read.
>Reading 4096 bytes.
<Written.
<Writing 2163 bytes.
>4096 bytes read.
>Reading 4096 bytes.
<Written.
<Flushing.
>114 bytes read.
>Reading 4096 bytes.
<Writing 0 bytes.
<Written.
<Flushing.
<Writing 0 bytes.
<Written.
<Flushing.
>0 bytes read.

History

  • 2014-12-14 - Version 1.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)