[libcxx-commits] [PATCH] D107671: [libcxx][ranges] Add `ranges::join_view`.
Tim Song via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Aug 11 14:41:04 PDT 2021
tcanens added inline comments.
================
Comment at: libcxx/include/__ranges/join_view.h:109
+ *__outer_,
+ __parent_->__inner_.__emplace_deref(__outer_));
+ __inner_ = ranges::begin(__inner);
----------------
ldionne wrote:
> I don't understand why the spec allows modifying a member of the parent `join_view` from the iterator. That's very sneaky and can lead to e.g. race conditions if someone does:
>
> ```
> join_view v = ...;
> auto it1 = v.begin();
> auto it2 = v.begin();
>
> std::thread([=]{
> ++it1; // calls satisfy() under the hood, which modifies `v`
> });
>
> std::thread([=]{
> ++it2; // calls satisfy() under the hood, which modifies `v`
> });
>
> // sneaky race condition since you had a copy of different iterators in each thread
> ```
>
> Basically, I think it's quite vexing that incrementing an iterator modifies the underlying view in this case, and I don't fully understand why that is even required. What use case does that enable? Is the criteria `is_reference_v<range_reference_t<V>>` meant to mean something like "the outer range creates its inner ranges on-the-fly and they are temporary objects"? I'm having trouble following here.
>
> CC @tcanens in case you can share some insight here.
It's an input range for this case, so everything from the second `begin()` onwards is undefined.
Yes, this is the case where the inner ranges are created on the fly and we need to store the range //somewhere// while it is being iterated over, and the only reasonable place to store it is the view.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D107671/new/
https://reviews.llvm.org/D107671
More information about the libcxx-commits
mailing list