libunifex icon indicating copy to clipboard operation
libunifex copied to clipboard

question of on

Open franktea opened this issue 3 years ago • 3 comments

I wrote a very simple test due to the doc, call on(scheduler1) and then on(scheduler2), but I found all code run on scheduler1. What's wrong, please?

#include <unifex/single_thread_context.hpp>
#include <unifex/just.hpp>
#include <unifex/on.hpp>
#include <unifex/transform.hpp>
#include <unifex/sync_wait.hpp>
#include <unifex/inline_scheduler.hpp>
#include <unifex/via.hpp>
#include <iostream>
#include <cassert>

#include <unifex/executor_concepts.hpp>
#include <unifex/scheduler_concepts.hpp>

using namespace unifex;

int main() {
    single_thread_context ctx;
    auto scheduler1 = ctx.get_scheduler();
    single_thread_context ctx2;
    auto scheduler2 = ctx2.get_scheduler();

    execute(schedule(scheduler1), [](){ std::cout<<"sch1 thread: "<<std::this_thread::get_id()<<"\n"; });
    execute(schedule(scheduler2), [](){ std::cout<<"sch2 thread: "<<std::this_thread::get_id()<<"\n"; });

    auto s = just(3)
        | on(scheduler1) // this line works
        | transform([](int a){
            std::cout<<"transform1 thread: "<<std::this_thread::get_id()<<"\n";
            return a+1;})
        | on(scheduler2) // it seems that this line is ignored
        | transform([](int a){
            std::cout<<"transform2 thread: "<<std::this_thread::get_id()<<"\n";
            return a*2;});
    int r = sync_wait(s).value(); 

    std::cout<<"r="<<r<<"\n";
}

output: sch1 thread: 0x70000946f000 sch2 thread: 0x7000094f2000 transform1 thread: 0x70000946f000 transform2 thread: 0x70000946f000 r=8

transform1 and transform2 both ran in scheduler1, not as I exepected.

franktea avatar Apr 11 '21 14:04 franktea

The on() algorithm actually applies to the operations that come before it in pipeline syntax (as those are the child operations of on())

So in your example, the first on(scheduler1) controls the scheduler that the just(3) operation will be started on (and thus the context that it immediately completes on).

The second on(scheduler2) controls the scheduler that the transform() is started on, which in turn just forwards through to call start() on the on(just(3), scheduler1)` scheduler. But the first thing that will do is transition from scheduler2 to scheduler1 to start the just() operation.

At the moment the on() algorithm does not have any transition back to the original context when the child operation completes (it should probably be named start_on() to be clearer about that). We have discussed changing the behaviour so that it transitions back to the parent scheduler when it completes but have not yet implemented this.

lewissbaker avatar Apr 12 '21 00:04 lewissbaker

We have discussed changing the behaviour so that it transitions back to the parent scheduler when it completes but have not yet implemented this.

This feels to me like a different algorithm.

ericniebler avatar Jul 01 '21 17:07 ericniebler

@franktea looks like the original question was answered. Shall we close?

janondrusek avatar Jul 29 '22 21:07 janondrusek

@janondrusek yes, please close. Thank you guys.

franktea avatar Sep 30 '22 10:09 franktea