public void Start()
        {
            _sharedBuffer = new RingBufferStream();

            _writer = new InternalBigEndianWriter((b, off, c) =>
            {
                _sharedBuffer.Insert(b, off, c);
            });

            _reader = new InternalBigEndianReader(_sharedBuffer);
        }
		public void Start()
		{
			_sharedBuffer = new RingBufferStream();

			_writer = new InternalBigEndianWriter((b,off,c) =>
			{
				_sharedBuffer.Insert(b, off, c);
			});

			_reader = new InternalBigEndianReader(_sharedBuffer);
		}
        public async Task Insert_1_byte_by_1()
        {
            Console.WriteLine("Insert_1_byte_by_1");

            var cancelationTokenSource = new CancellationTokenSource();
            var rbuffer = new RingBufferStream(cancelationTokenSource.Token);

            int expectedLast = 0;

            for (int i = 0; i < 1024 * 100; i++)
            {
                await rbuffer.Insert(new[] { (byte)(i % 256) }, 0, 1);

                if (i % 99 == 0)
                {
                    var temp = new byte[101];
                    var read = rbuffer.Read(temp, 0, temp.Length);

                    Console.WriteLine("[Dump] read: " + read + " [" + temp.Aggregate("", (s, b) => s + b + ", ") + "]");

                    if (i == 0)
                    {
                        read.Should().Be(1);
                        temp[read - 1].Should().Be((byte)expectedLast);
                    }
                    else
                    {
                        read.Should().Be(99);
                        temp[read - 1].Should().Be((byte)expectedLast);
                    }
                    expectedLast += 99;
                    expectedLast %= 256;
                }
            }

            {
                var temp = new byte[101];
                var read = rbuffer.Read(temp, 0, temp.Length);
                Console.WriteLine("[Final] read: " + read + " [" + temp.Aggregate("", (s, b) => s + b + ", ") + "]");
            }
        }
        public async Task Fast_producer_slow_consumer()
        {
            Console.WriteLine("Fast_producer_slow_consumer");

            var  cancelationTokenSource = new CancellationTokenSource();
            var  rbuffer = new RingBufferStream(cancelationTokenSource.Token);
            bool done    = false;

            const int mod = 37;

            var producerTask = Task.Run(async() =>
            {
                for (int i = 0; i < 1024 * 1000; i += 10)
                {
                    var buffer = new []
                    {
                        (byte)(i % mod),
                        (byte)((i + 1) % mod),
                        (byte)((i + 2) % mod),
                        (byte)((i + 3) % mod),
                        (byte)((i + 4) % mod),
                        (byte)((i + 5) % mod),
                        (byte)((i + 6) % mod),
                        (byte)((i + 7) % mod),
                        (byte)((i + 8) % mod),
                        (byte)((i + 9) % mod),
                    };

                    await rbuffer.Insert(buffer, 0, buffer.Length);
                }

                done = true;
            });

            var consumed = new List <byte>(capacity: 1024 * 1000);

            var consumerTask = Task.Run(async() =>
            {
                int totalRead = 0;
                while (true)
                {
                    await Task.Delay(_rnd.Next(10));

//					Console.WriteLine("will read...");
                    var temp   = new byte[199];
                    var read   = rbuffer.Read(temp, 0, temp.Length);
                    totalRead += read;

                    if (read == 0)
                    {
                        continue;
                    }

                    for (int i = 0; i < read; i++)
                    {
                        consumed.Add(temp[i]);
                    }

                    // Console.WriteLine("[Dump] read: " + read + " total " + totalRead);// + " [" + temp.Aggregate("", (s, b) => s + b + ", ") + "]");

                    if (done && rbuffer.Position == rbuffer.Length)
                    {
                        break;
                    }
                }
                Console.WriteLine("Done");
            });

            Task.WaitAll(producerTask, consumerTask);

            Console.WriteLine("Checking consistency...");

            for (int i = 0; i < consumed.Count; i++)
            {
                var isValid = consumed[i] == i % mod;
                isValid.Should().BeTrue();
            }

            Console.WriteLine("Completed");
        }
        public async Task GC_min_allocation_test()
        {
            Console.WriteLine("GC_min_allocation_test Starting...");
//			await Task.Delay(3000);

            Console.WriteLine("Started");

            var  cancelationTokenSource = new CancellationTokenSource();
            var  rbuffer = new RingBufferStream(cancelationTokenSource.Token);
            bool done    = false;

            const int mod            = 37;
            var       producerBuffer = new byte[10];

            var watch = Stopwatch.StartNew();

            // long iterations = 1000000000000000000;
            long iterations = 100000000;

            var producerTask = Task.Run(async() =>
            {
                for (var i = 0L; i < iterations; i += 10L)
                {
                    producerBuffer[0] = (byte)(i % mod);
                    producerBuffer[1] = (byte)((i + 1) % mod);
                    producerBuffer[2] = (byte)((i + 2) % mod);
                    producerBuffer[3] = (byte)((i + 3) % mod);
                    producerBuffer[4] = (byte)((i + 4) % mod);
                    producerBuffer[5] = (byte)((i + 5) % mod);
                    producerBuffer[6] = (byte)((i + 6) % mod);
                    producerBuffer[7] = (byte)((i + 7) % mod);
                    producerBuffer[8] = (byte)((i + 8) % mod);
                    producerBuffer[9] = (byte)((i + 9) % mod);

                    await rbuffer.Insert(producerBuffer, 0, producerBuffer.Length);
                }

                done = true;
            });

            var temp = new byte[199];

            var consumerTask = Task.Run(async() =>
            {
                int totalRead = 0;
                while (true)
                {
//					await Task.Delay(_rnd.Next(10));

                    // Console.WriteLine("will read...");

                    var read   = rbuffer.Read(temp, 0, temp.Length);
                    totalRead += read;

                    if (read == 0)
                    {
                        continue;
                    }

                    // Console.WriteLine("[Dump] read: " + read + " total " + totalRead);// + " [" + temp.Aggregate("", (s, b) => s + b + ", ") + "]");

                    if (done && rbuffer.Position == rbuffer.Length)
                    {
                        break;
                    }
                }
                Console.WriteLine("Done");
            });

            Task.WaitAll(producerTask, consumerTask);
            watch.Stop();
            // Console.WriteLine("Checking consistency...");

            Console.WriteLine("Completed in " + watch.Elapsed.TotalMilliseconds + "ms");
        }
		public async Task Fast_producer_slow_consumer()
		{
			Console.WriteLine("Fast_producer_slow_consumer");

			var cancelationTokenSource = new CancellationTokenSource();
			var rbuffer = new RingBufferStream(cancelationTokenSource.Token);
			bool done = false;

			const int mod = 37;

			var producerTask = Task.Run(async () =>
			{
				for (int i = 0; i < 1024*1000; i += 10)
				{
					var buffer = new []
					{
						(byte) (i%mod), 
						(byte) ((i + 1) %mod),
						(byte) ((i + 2) %mod),
						(byte) ((i + 3) %mod),
						(byte) ((i + 4) %mod),
						(byte) ((i + 5) %mod),
						(byte) ((i + 6) %mod),
						(byte) ((i + 7) %mod),
						(byte) ((i + 8) %mod),
						(byte) ((i + 9) %mod),
					};

					await rbuffer.Insert(buffer, 0, buffer.Length);
				}

				done = true;
			});

			var consumed = new List<byte>(capacity: 1024 * 1000);

			var consumerTask = Task.Run(async () =>
			{
				int totalRead = 0;
				while (true)
				{
					await Task.Delay(_rnd.Next(10));

//					Console.WriteLine("will read...");
					var temp = new byte[199];
					var read = rbuffer.Read(temp, 0, temp.Length);
					totalRead += read;

					if (read == 0) continue;

					for (int i = 0; i < read; i++)
					{
						consumed.Add(temp[i]);
					}

					// Console.WriteLine("[Dump] read: " + read + " total " + totalRead);// + " [" + temp.Aggregate("", (s, b) => s + b + ", ") + "]");

					if (done && rbuffer.Position == rbuffer.Length)
					{
						break;
					}
				}
				Console.WriteLine("Done");
			});

			Task.WaitAll(producerTask, consumerTask);

			Console.WriteLine("Checking consistency...");

			for (int i = 0; i < consumed.Count; i++)
			{
				var isValid = consumed[i] == i % mod;
				isValid.Should().BeTrue();
			}

			Console.WriteLine("Completed");
		}
		public async Task GC_min_allocation_test()
		{
			Console.WriteLine("GC_min_allocation_test Starting...");
//			await Task.Delay(3000);

			Console.WriteLine("Started");

			var cancelationTokenSource = new CancellationTokenSource();
			var rbuffer = new RingBufferStream(cancelationTokenSource.Token);
			bool done = false;

			const int mod = 37;
			var producerBuffer = new byte[10];

			var watch = Stopwatch.StartNew();

			// long iterations = 1000000000000000000;
			long iterations = 100000000;

			var producerTask = Task.Run(async () =>
			{
				for (var i = 0L; i < iterations; i += 10L)
				{
					producerBuffer[0] = (byte) (i % mod);
					producerBuffer[1] = (byte) ((i + 1) % mod);
					producerBuffer[2] = (byte) ((i + 2) % mod);
					producerBuffer[3] = (byte) ((i + 3) % mod);
					producerBuffer[4] = (byte) ((i + 4) % mod);
					producerBuffer[5] = (byte) ((i + 5) % mod);
					producerBuffer[6] = (byte) ((i + 6) % mod);
					producerBuffer[7] = (byte) ((i + 7) % mod);
					producerBuffer[8] = (byte) ((i + 8) % mod);
					producerBuffer[9] = (byte) ((i + 9) % mod);

					await rbuffer.Insert(producerBuffer, 0, producerBuffer.Length);
				}

				done = true;
			});

			var temp = new byte[199];

			var consumerTask = Task.Run(async () =>
			{
				int totalRead = 0;
				while (true)
				{
//					await Task.Delay(_rnd.Next(10));

					// Console.WriteLine("will read...");
					
					var read = rbuffer.Read(temp, 0, temp.Length);
					totalRead += read;

					if (read == 0) continue;

					// Console.WriteLine("[Dump] read: " + read + " total " + totalRead);// + " [" + temp.Aggregate("", (s, b) => s + b + ", ") + "]");

					if (done && rbuffer.Position == rbuffer.Length)
					{
						break;
					}
				}
				Console.WriteLine("Done");
			});

			Task.WaitAll(producerTask, consumerTask);
			watch.Stop();
			// Console.WriteLine("Checking consistency...");

			Console.WriteLine("Completed in " + watch.Elapsed.TotalMilliseconds + "ms");
		}
		public async Task Variable_size_writes_slow_consumer()
		{
			Console.WriteLine("Variable_size_writes_slow_consumer");

			var cancelationTokenSource = new CancellationTokenSource();
			var rbuffer = new RingBufferStream(cancelationTokenSource.Token);
			bool done = false;

			const int mod = 37;
			const int sizeOfSet = 1024*100;

			var producerTask = Task.Run(async () =>
			{
				int stepAndBufferSize = 0;
				for (int i = 0; i < sizeOfSet; i += stepAndBufferSize)
				{
					var buffer = new[]
					{
						(byte) (i%mod), 
						(byte) ((i + 1) %mod),
						(byte) ((i + 2) %mod),
						(byte) ((i + 3) %mod),
						(byte) ((i + 4) %mod),
						(byte) ((i + 5) %mod),
						(byte) ((i + 6) %mod),
						(byte) ((i + 7) %mod),
						(byte) ((i + 8) %mod),
						(byte) ((i + 9) %mod),
						(byte) ((i + 10) %mod),
						(byte) ((i + 11) %mod),
						(byte) ((i + 12) %mod),
						(byte) ((i + 13) %mod),
						(byte) ((i + 14) %mod),
						(byte) ((i + 15) %mod),
						(byte) ((i + 16) %mod),
						(byte) ((i + 17) %mod),
						(byte) ((i + 18) %mod),
						(byte) ((i + 19) %mod),
						(byte) ((i + 20) %mod),
						(byte) ((i + 21) %mod),
						(byte) ((i + 22) %mod),
						(byte) ((i + 23) %mod),
						(byte) ((i + 24) %mod),
						(byte) ((i + 25) %mod),
						(byte) ((i + 26) %mod),
						(byte) ((i + 27) %mod),
						(byte) ((i + 28) %mod),
						(byte) ((i + 29) %mod),
					};

					stepAndBufferSize = _rnd.Next(buffer.Length);

					await rbuffer.Insert(buffer, 0, stepAndBufferSize);
				}

				done = true;
			});

			var consumed = new List<byte>(capacity: sizeOfSet);

			var consumerTask = Task.Run(async () =>
			{
				int totalRead = 0;
				while (true)
				{
					await Task.Delay(_rnd.Next(10));

					// Console.WriteLine("will read...");
					var temp = new byte[400];

					var readSize = _rnd.Next(temp.Length - 1) + 1;

					var read = rbuffer.Read(temp, 0, readSize);
					totalRead += read;

					if (read == 0) continue;

					for (int i = 0; i < read; i++)
					{
						consumed.Add(temp[i]);
					}

//					Console.WriteLine("[Dump] read: " + read + " total " + totalRead);// + " [" + temp.Aggregate("", (s, b) => s + b + ", ") + "]");

					if (done && rbuffer.Position == rbuffer.Length)
					{
						break;
					}
				}
				Console.WriteLine("Done");
			});

			Task.WaitAll(producerTask, consumerTask);

			Console.WriteLine("Checking consistency...");

			for (int i = 0; i < consumed.Count; i++)
			{
				var isValid = consumed[i] == i % mod;
				isValid.Should().BeTrue();
			}

			Console.WriteLine("Completed");
		}
		public async Task Insert_1_byte_by_1()
		{
			Console.WriteLine("Insert_1_byte_by_1");

			var cancelationTokenSource = new CancellationTokenSource();
			var rbuffer = new RingBufferStream(cancelationTokenSource.Token);

			int expectedLast = 0;

			for (int i = 0; i < 1024 * 100; i++)
			{
				await rbuffer.Insert(new[] { (byte)(i % 256) }, 0, 1);

				if (i % 99 == 0)
				{
					var temp = new byte[101];
					var read = rbuffer.Read(temp, 0, temp.Length);

					Console.WriteLine("[Dump] read: " + read + " [" + temp.Aggregate("", (s, b) => s + b + ", ") + "]");

					if (i == 0)
					{
						read.Should().Be(1);
						temp[read - 1].Should().Be((byte)expectedLast);
					}
					else
					{
						read.Should().Be(99);
						temp[read - 1].Should().Be((byte)expectedLast);
					}
					expectedLast += 99;
					expectedLast %= 256;
				}
			}

			{
				var temp = new byte[101];
				var read = rbuffer.Read(temp, 0, temp.Length);
				Console.WriteLine("[Final] read: " + read + " [" + temp.Aggregate("", (s, b) => s + b + ", ") + "]");
			}
		}