C++ 實現then,lambda鏈式調用

lambda 鏈式調用

C++11支持lambda和function,在一些延遲計算的場景下,這個鏈式調用的需求更加強烈。鏈式調用的目的是,將多個函數按照前一個的輸出作爲下一個的輸入串起來,然後推遲到某個時刻再計算。C++中鏈式調用比較少見,因爲實現比較複雜。

template<typename T>
class Task;
template<typename R,typename...Args>
class Task<R(Args...)>{
    public:
    Task(std::function<R(Args...)> && f) : m_fn(std::move(f)){std::cout <<
    	"move construct func name : "<<__func__<< std::endl;}
    Task(std::function<R(Args...)> & f) : m_fn(f){std::cout <<"construct func name : "<<
    	__func__<< std::endl;}
    R run(Args&& ... args){
        std::cout <<"exec function,func name : "<<__func__<< std::endl;
        return m_fn(std::forward<Args>(args)...); //perfect
    }
    // continue exec
    template<typename F>
    auto then(F && f)->Task<typename std::result_of<F(R)>::type(Args...)>{
        std::cout <<"then -> "<<i<< std::endl;i++;
        using return_type = typename std::result_of<F(R)>::type; //get F return type
        auto func = std::move(m_fn);
        return Task<return_type(Args...)>([func,f](Args&& ...args){
            return f(func(std::forward<Args>(args)...));
        });
    }
    private:
    std::function<R(Args...)> m_fn;
};

void TestTask(){
    Task<int(int)> task([](int i){std::cout <<"init :"<<i<< std::endl;return i;});
    std::string str = "join in lambda then : ";
    auto res = task.then([&str](int i){str += "then 1\t";std::cout <<"first:"<<i<< 
    	std::endl;return i + 1;})
    .then([&str](int i){str += "then 2\t";std::cout <<"second:"<<i<<std::endl;return i + 2;})
    .then([&str](int n){str += "then 3\t";std::cout <<"third:"<<n<< 
    	std::endl;return std::make_tuple(n + 3,"n + 3");})
    .then([&str](auto n){str += "then 4\t";std::cout <<"fouth:"<< 
    	std::get<0>(n)<<"tuple string : "<<std::get<1>(n)<< std::endl;
    	return std::make_tuple(std::get<0>(n) + 4,"then exec ecnd");
    	}).run(1);
    std::cout <<"result tuple value : "<<std::get<0>(res)<<"   result tuple string : "<<
    	std::get<1>(res)<< "   result string : "<<str<<std::endl;
}

auto fu(int i){
    auto f = std::async([](int i){
        std::cout <<"sleep two "<<i<<" seconds..."<< std::endl;
       // std::chrono::milliseconds dre(i * 1000);
       // std::this_thread::sleep_for(dre);
        return i * i;
    },i);
    return std::forward<decltype(f)>(f);
}

void testFuture(){
    std::cout <<"at testFuture func thread : "<<std::this_thread::get_id()<< std::endl;
    typedef std::future<int> A;
    typedef std::result_of<decltype(fu)*(int)>::type B;
    static_assert(std::is_same<A,B>::value,"not equal");
    Task<std::result_of<decltype(fu)&(int)>::type(int)> task(fu);
    auto t = task.then([](auto o){
        std::cout <<"wait value ..."<< std::endl;
        std::cout <<"at first then func thread : "<<std::this_thread::get_id()<< std::endl;
        auto ii = o.get() + 100;
        auto f = std::async([](int i){
            std::cout <<"new value :"<<i<<" .."<< std::endl;
            std::cout <<"]async in thread : "<<std::this_thread::get_id()<< std::endl;
            //std::chrono::milliseconds dre(i * 1000);
            //std::this_thread::sleep_for(dre);
            return i * i;
        },ii);
        return std::forward<decltype(f)>(f);}) 
    .then([](auto o){
        std::cout <<wait value ...\n";
        std::cout <<"]at second then func thread : "<<std::this_thread::get_id<< std::endl; 
        //std::chrono::milliseconds dre(2000); //sleep 2 seconds
        //std::this_thread::sleep_for(dre);
        std::cout <<"wait last value...,,,,,,,,,,,,,,,,,,,,,,,,,,"<< std::endl;
        return o.get() + 10000;})
    .then([](auto o){
        std::cout <<"fouth then"<< std::endl;
        auto ff = std::async([](auto i){
            std::cout <<"wait value ...\n";
            std::cout <<"at third then func thread : "<<std::this_thread::get_id<< std::endl; 
            int all = 2134;
            for(auto ii = 0; ii < i; ++ii){
                //std::cout<<ii;
                all += (ii % 3 == 0 && ii > all * 1.5) ? 1 : 2;
            }
            std::cout<<""<<all<<"\n";
            return all;
        },o);
        return std::forward<decltype(ff)>(ff);})
    .run(2); // 2 seconds
    std::cout<<"future get : "<<t.get()<<"\n";
}

int main(){
    TestTask();  // lambda exec func
    testFuture(); //lambda exec thread
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章