4

タスクスケジューラと一緒に使用するために、std::packaged_taskを別のクラス内にラップしようとしています。

現時点では、std::futureサポートを除いてすべて機能しています。std :: futureのサポートを取得するには、提供するget_future()関数にstd::packaged_taskを使用する必要があることがわかりました。

私はこれを機能させるために一日中さまざまな方法を試してきましたが、std::bindからの戻り値を使用してpackaged_taskを適切に宣言して初期化することができないようです。std :: async、std :: future、std :: threadなど、関連するすべてのlibstdc ++関数の実装を解読しようとしましたが、うまくいきませんでした。

次のコードは、機能していないバージョンと機能しているバージョンの両方の実装です。それを機能させるには、2つの/ * --- WORKS * /のコメントを外し、他の関連する行にコメントを付けます。

#include <vector>
#include <deque>
#include <memory>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <iostream>
#include <chrono>
#include <functional>

#include <windows.h>

class task
{
private:
    struct task_implementation_base
    {
        virtual void execute() = 0;
    };

    template <class callable>
    struct task_implementation : public task_implementation_base
    {
        task_implementation(callable&& f) : /*m_task(std::forward<callable>(f)) WORKS*/m_task(f) { }
        void execute() { m_task(); }

        //callable m_task; // WORKS
        std::packaged_task<typename result_of<callable>::type> m_task;
    };

    template <class callable>
    std::shared_ptr<task_implementation<callable>> make_routine(callable&& f)
    {
        return std::make_shared<task_implementation<callable>>(std::forward<callable>(f));
    }

public:
    template <class callable, class... arguments>
    task(callable&& f, arguments&&... args) : m_function(make_routine(std::bind(std::forward<callable>(f), std::forward<arguments>(args)...))) {}

    void operator()() { run(); }

    void run() { m_function->execute(); }

private:
    std::shared_ptr<task_implementation_base> m_function;

};

int testint(int i)
{
    std::cout << "test6" << " :: ran from thread " << std::this_thread::get_id() << "\n";
    fflush(stdout);
    return i+100;
}

void test(const char* text)
{
    std::cout << text << " :: ran from thread " << std::this_thread::get_id() << "\n";
    fflush(stdout);
}

class testclass
{
public:
    void print1() { test("test3"); }
    void print2() { test("test4"); }
    void print3(const char* text) { test(text); }

};

int main()
{
    testclass testclass1;
    testclass* testclass2 = new testclass;

    task test1(test, "test1");
    task test2([]() { test("test2"); });
    task test3(&testclass::print1, &testclass1);
    task test4(&testclass::print2, &*testclass2);
    task test5(&testclass::print3, &*testclass2, "test5");
    task test6(&testint, 1);

    test1();
    test2();
    test3();
    test4();
    test5();
    test6();

    Sleep(2000);

    return 0;
}

問題はだと思いtypename result_of<callable>::typeます。関数の戻り型に正しく評価されないと思いcallableます。

で使用c++ (Built by MinGW-builds project) 4.8.0 20121225 (experimental)していWindows 8 64bitます。私は単にこの仕事を間違った方法で行おうとしているだけだと思う​​ので、エラーは無関係だと思いますが、とにかくエラーのペーストビンがあります:エラー

4

2 に答える 2

3

std::packaged_task呼び出された関数の結果タイプをテンプレート引数として受け取るだけでなく、呼び出される関数に渡す引数のタイプも受け取ります。

それらは次のように定義できます。

// somewhere
int foo(bool, int);

// somewhere else
std::packaged_task<int(bool, int)> p(foo);

コードを修正するには、2つの空の括弧ペアを追加する必要があります。上で説明したことは、にも当てはまりますstd::result_of

std::packaged_task<typename std::result_of<callable()>::type()> m_task;
于 2013-01-15T20:37:06.050 に答える
0

メイントピックの質問への回答のみです。「実装方法」

短い実装例:

template <typename Signature> /// <---- 1
class Task;

template <typename Res, typename... ArgTypes>
class Task<Res(ArgTypes...)>  /// <---- 2
{
public:
    template <typename Function>
    explicit Task(Function&& callback)
        : _task{std::forward<Function>(callback)}
    { }

    void execute(ArgTypes... args) noexcept(false)
    {
        //...
        _task(std::forward<ArgTypes>(args)...);
    }

private:
    std::packaged_task<Res(ArgTypes...)> _task;
};

ステップ1と2が必要な理由はわかりませんが、libの実装と同じようにしました。多分誰かがこの応答を拡張することができます。

于 2020-11-24T14:15:13.293 に答える