Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

execution::split: Conflict between shared_state<Child_Sndr> and shared_state<Out_Sndr> #290

Open
mochunshuang opened this issue Oct 4, 2024 · 1 comment

Comments

@mochunshuang
Copy link

split_t

struct split_t
{
    template <snd::sender Sndr>
        requires(snd::sender_in<Sndr, split_env>)
    auto operator()(Sndr &&sndr) const // noexcept
    {
        auto dom = snd::general::get_domain_early(std::as_const(sndr));
        return snd::transform_sender(
            dom, snd::make_sender(*this, {}, std::forward<Sndr>(sndr)));
    }

    template <snd::sender Sndr>
    auto transform_sender(Sndr &&sndr) noexcept // NOLINT
        requires(snd::sender_for<decltype((sndr)), split_t>)
    {
        // TODO(mcs):
        // Note: tag_change: split_t => split_impl_tag
        // Note: data_change: {} => shared_wrapper(shared_state{child},old_tag)
        // Note: sh_state: shared_state<child_sndr> conflict shared_state<Sndr>
        auto &&[old_tag, _, child] = sndr;
        auto *sh_state =
            new __split::shared_state{std::forward_like<decltype(sndr)>(child)};
        return snd::make_sender(split_impl_tag(),
                                __split::shared_wrapper{sh_state, old_tag});
    }
};
inline constexpr split_t split{}; // NOLINT

local_state

 template <class Sndr, class Rcvr>
    struct local_state : local_state_base
    {                          // exposition only
        using onstopcallback = // Note: Rcvr + get_stop_token_t => token_type
            stop_callback_of_t<queries::stop_token_of_t<queries::env_of_t<Rcvr>>,
                               snd::general::on_stop_request>;

        ~local_state() noexcept override;
        void notify() noexcept override;

        local_state(Sndr &&sndr, Rcvr &rcvr) noexcept;

        local_state(local_state &&) = delete;
        local_state(const local_state &) = delete;
        local_state &operator=(local_state &&) = delete;
        local_state &operator=(const local_state &) = delete;

        std::optional<onstopcallback> on_stop; // exposition only // NOLINT

        // using Childen = snd::__detail::mate_type::child_type<Sndr>;
        shared_state<Sndr> *sh_state; // exposition only // NOLINT
        Rcvr *rcvr;                   // exposition only // NOLINT
    };
template <> // for tag: adapt::split_impl_tag
struct snd::general::impls_for<adapt::split_impl_tag> : snd::__detail::default_impls
{
    // Note: create [basic_state->state] when connect. 
    static constexpr auto get_state = // NOLINT
        []<class Sndr>(Sndr &&sndr, auto &rcvr) noexcept {
            // Note: call: local_state(sndr,rcvr)
            return adapt::__split::local_state{std::forward_like<Sndr>(sndr), rcvr};
        };
   ....
}

p2300R10
local-state(Sndr&& sndr, Rcvr& rcvr) noexcept;
Effects: Equivalent to:

// when tag is split_impl_tag 
auto& [_, data, _] = sndr; //snd::make_sender(split_impl_tag(),__split::shared_wrapper{sh_state, old_tag}); //only can bind 2 but 3
this->sh_state = data.sh_state.get(); //shared_state<child_sndr> conflict shared_state<Sndr>
this->sh_state->inc-ref();
this->rcvr = addressof(rcvr);

info

 sender auto input = just(1);
 sender auto multi_shot = split(std::move(input));
 sender auto start =
        then(multi_shot, [](int i) { std::cout << i << " First continuation\n"; });
sync_wait(std::move(start));

`
e:\0_github_project\mcsexec\mcsexec\test\test_base\split.cpp:79:32: required from here
79 | mcs::this_thread::sync_wait(std::move(start));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
E:/0_github_project/mcsexec/mcsexec/include/__detail/adapt/__split.hpp:254:35: error: cannot convert 'mcs::execution::adapt::__split::shared_state<mcs::execution::snd::__detail::basic_sender<mcs::execution::factories::__just_tmcs::execution::recv::set_value_t, mcs::execution::snd::__detail::product_type > >' to 'mcs::execution::adapt::__split::shared_state<mcs::execution::snd::__detail::basic_sender<mcs::execution::adapt::split_impl_tag, mcs::execution::adapt::__split::shared_wrapper<mcs::execution::adapt::__split::shared_state<mcs::execution::snd::__detail::basic_sender<mcs::execution::factories::__just_tmcs::execution::recv::set_value_t, mcs::execution::snd::__detail::product_type > >, mcs::execution::adapt::split_t> > >' in assignment
254 | this->sh_state = data.sh_state; // TODO(mcs): ? ~~~~~^~~~~~~~
| |
| mcs::execution::adapt::__split::shared_state<mcs::execution::snd::__detail::basic_sender<mcs::execution::factories::__just_tmcs::execution::recv::set_value_t, mcs::execution::snd::__detail::product_type > >*

`

@jiixyj
Copy link

jiixyj commented Oct 7, 2024

Agreed, this seems to be a bug in the spec. local-state's sh_state type should not be shared-state<Sndr>* as specified, but something like shared_state_of_data<Sndr>* where shared_state_of_data is the decayed type of the (exposition only) sh_state member of the data member of the Sndr, i.e. the instance of shared-wrapper.

Also, I don't see where the get() in this->sh_state = data.sh_state.get(); (https://eel.is/c++draft/exec#split-6) comes from.

In any case, the split as defined in the working draft has some issues related to cancellation behavior, so I guess it is not unlikely to receive a respec or even getting removed from the draft altogether.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants