protected virtual LinkedListNode <IStreamPartition> GetNextPartitionNode(LinkedListNode <IStreamPartition> node)
 {
     try
     {
         PartitionEditorLock.EnterReadLock();
         if (node == null)
         {
             return(Partitions.First);
         }
         else
         {
             return(node.Next);
         }
     }
     finally
     {
         PartitionEditorLock.ExitReadLock();
     }
 }
        public async Task FromAsync(Stream source, bool disposeWhenDone = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                VerifyDisposure();

                IPartitionGenerator partitioner = null;

                lock (Partitions)
                {
                    if (source == null)
                    {
                        throw new ArgumentNullException(nameof(source));
                    }
                    if (HasSource)
                    {
                        throw new Exceptions.MultipleSourceException();
                    }
                    HasSource   = true;
                    partitioner = this.PartitionGenerator;
                }

                if (partitioner == null)
                {
                    partitioner = PartitionGeneratorFactory.Create();
                }

                var asyncGenerator = partitioner.GenerateAsync(source, cancellationToken);
                while (await asyncGenerator.MoveNext())
                {
                    var part = asyncGenerator.Current();
                    if (part != null)
                    {
                        try
                        {
                            PartitionEditorLock.EnterWriteLock();
                            this.TotalStreamLength += part.Size;
                            this.Partitions.AddLast(part);
                        }
                        finally
                        { PartitionEditorLock.ExitWriteLock(); }

                        lock (Partitions)
                        {
                            var x = TCS_ReceivedNextPartition;
                            TCS_ReceivedNextPartition = new TaskCompletionSource <long>();
                            x.SetResult(part.Size);
                        }
                    }
                }

                SourceRead = true;
            }
            catch (TaskCanceledException tce)
            {
                lock (Partitions)
                {
                    TCS_ReceivedNextPartition.TrySetCanceled(tce.CancellationToken);
                    TCS_ReceivedLastPartition.TrySetCanceled(tce.CancellationToken);
                }
                throw;
            }
            finally
            {
                if (disposeWhenDone)
                {
                    source.Dispose();
                }

                lock (Partitions)
                {
                    if (!TCS_ReceivedNextPartition.Task.IsCanceled)
                    {
                        TCS_ReceivedNextPartition.SetResult(StreamLength);
                    }
                    if (!TCS_ReceivedLastPartition.Task.IsCanceled)
                    {
                        TCS_ReceivedLastPartition.SetResult(StreamLength);
                    }
                }
            }
        }
        public void From(Stream source, bool disposeWhenDone = false)
        {
            try
            {
                VerifyDisposure();

                IPartitionGenerator partitioner = null;

                lock (Partitions)
                {
                    if (source == null)
                    {
                        throw new ArgumentNullException(nameof(source));
                    }
                    if (HasSource)
                    {
                        throw new Exceptions.MultipleSourceException();
                    }
                    HasSource   = true;
                    partitioner = this.PartitionGenerator;
                }

                if (partitioner == null)
                {
                    partitioner = PartitionGeneratorFactory.Create();
                }

                foreach (var part in partitioner.Generate(source))
                {
                    if (part == null)
                    {
                        continue;
                    }
                    try
                    {
                        PartitionEditorLock.EnterWriteLock();
                        this.TotalStreamLength += part.Size;
                        this.Partitions.AddLast(part);
                    }
                    finally
                    { PartitionEditorLock.ExitWriteLock(); }

                    lock (Partitions)
                    {
                        var x = TCS_ReceivedNextPartition;
                        TCS_ReceivedNextPartition = new TaskCompletionSource <long>();
                        x.SetResult(part.Size);
                    }
                }

                lock (Partitions)
                {
                    SourceRead = true;
                    TCS_ReceivedNextPartition.SetResult(StreamLength);
                    TCS_ReceivedLastPartition.SetResult(StreamLength);
                }
            }
            finally
            {
                if (disposeWhenDone)
                {
                    source.Dispose();
                }
            }
        }