std.collection - changing the collection while iterating
Morbid.Obesity via Digitalmars-d
digitalmars-d at puremagic.com
Tue Jun 23 15:22:08 PDT 2015
On Sunday, 21 June 2015 at 23:02:38 UTC, Andrei Alexandrescu
wrote:
> While I work on making std.allocator better, here's some food
> for thought regarding std.collection.
>
> Consider a traditional container with reference semantics,
> Java-style. Regarding changing the collection (e.g.
> adding/removing elements) while iterating, we have the
> following possibilities:
>
> 1. Leave it undefined, like the STL does. Probably this is too
> extreme.
>
> 2. Throw an exception if a remove is attempted while ranges
> exist. This works but it's conservative - e.g. it throws even
> if those ranges are never to be used again etc.
>
> 3. Allow the removal but throw from the ranges if there's any
> attempt to use a range following a remove.
>
> 4. Make it work such that ranges continue to be valid post
> removal. Perhaps this is on the inefficient side.
>
>
> Andrei
First,
There is an alternative: Lazy Removal. This allows one to remove
from the container while iterating over it by not removing
immediately but after the iteration has actually happened. Lazy
Removal can easily be implemented efficiently by using a bit
sequence to represent the removed state of each item. This is to
provide the appropriate null reference when retrieving an item
that has been removed. Of course, one could lead it up to the
user to avoid accessing removed elements. (if they removed them,
it should be easy to know or keep track manually)
Second,
Case 1, unfortunately. There is no valid solution as T. S. has
mentioned EXCEPT to prevent any immediate removal. (since T.S.
showed that removal while iterating is bad, we can't have it)
Hence to simulate this see :First:.
To make immediate changes when they are ok. The programmer can
have access to a "Flush" which will immediately remove all
"cached removals".
In fact, to make like easier all removals should be cached while
iterating. Once iterating is done, the removals are flushed. This
is a clearly defined and easily implementable solution that
provides the best of both worlds.
e.g.,
Remove(x) - Removes the item x from the container
immediately if the container is not being iterated over, else it
waits until the container is no longer being iterated over. This
is safe since no real action on the container is taken while the
container is "in use".
Flush() - Removes all cached items from Remove(x) from the
container. Unsafe while iterating over.
RemoveNow(x) - Immediately removes the item x from the
container regardless of iteration. Usafe while iterating over.
More information about the Digitalmars-d
mailing list