Skip to content

Add private method ToDisposableLinkedList to replace DisposableGroup and Acquire #724

Open
@Orace

Description

@Orace

Transpose, Interleave and SortedMerge are three methods that have to deals with enumeration of a collection of IEnumerable.

In this three methods, implementation have to ensure that all enumerators from the input enumerables are disposed when:

  1. The enumeration of the input collection of IEnumerable fail.
  2. The result sequence enumerator is disposed.

1. is assured by Acquire in the three methods.
2. is assured by DisposableGroup in SortedMerge and by some try {} finaly {} blocks in Transpose and Interleave (and those make Acquire useless as discussed here #696 ).

Acquire return an array, DisposableGroup is based on an list.
For the three methods we can build cases where enumerators are heavily removed from the array/list (or, for Transpose, tested as null).
Since remove for array/list (or repeatedly skip null elements) is O(N) in time, that lead to O(N²) time complexity.
This can be easily fixed with the use of a LinkedList (and by removing null elements from it).

I propose a ToDisposableLinkedList() method that 1. have the functionality of Acquire (on error, dispose already acquired elements) and provide a DisposableLinkedList that 2. have the functionality of DisposableGroup<T> (being disposable and dispose its content when disposed).

It will be used like that:

using var enumerators = source.Select(e => e.GetEnumerator()).ToDisposableLinkedList();

The using here allow to remove the try {} finally {} from here:

finally
{
foreach (var e in enumerators)
e?.Dispose();
}

and here:
finally
{
Debug.Assert(iteratorList != null || iterators != null);
foreach (var iter in (iteratorList ?? (IList<IEnumerator<T>>) iterators))
iter.Dispose();
}

and improve the DisposableGroup/Acquire combo from here:

using var disposables = new DisposableGroup<TSource>(sequences.Select(e => e.GetEnumerator()).Acquire());

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions