1

最近入手した C++11 の本から、123 ページ (packaged_task 5.3.5.2) の例をビルドしようとしています。これを XCode で機能させるためにいくつかの作業を行った後、いくつか質問があります。

まず、packaged_task ctor に関数ポインターを渡す必要があるようです。テキストにアンパサンドが表示されていないため、タイプミスか、標準の変更が遅れている可能性がありますか?

次に、さらに重要なことに、get を呼び出して sigabrt の取得を回避できるように thread.join(s) を追加する必要があり、プロセスは何も出力せずに終了します。スレッドが値を返すまで get future の呼び出しがブロックされるという印象を受けましたが、そうではないようです。結合を追加すると、コードの非同期 (非ブロッキング) の性質に逆らうようにも見えます。必要に応じて、将来に参加できないのはなぜですか? ドキュメントから読み取ると、get は暗黙的に待機を呼び出し、コードに待機を追加しても、sigabrt が発生することが示されています。これは非常に不可解です。

私は c 言語方言 c11、-std=gnu++11 および libc++ (c++11 サポート付き) を使用しています。運がない他のオプションを試しました(gnuc ++を使用している場合、見つかりません)。これは、コードを作成するために使用できる唯一の組み合わせのようです。XCode は、c++11 をコンパイルするために必要なものについて非常にうるさいです。

事前にご協力いただきありがとうございます。

これは、コードを実行するための私の「修正」を含む本のテストケースです。

    #include <iostream>
    #include <numeric>
    #include <vector>
    #include <thread>
    #include <future>

    using namespace std;

    double accum(double *beg, double *end, double init)
    {
        return accumulate(beg, end, init);
    }

    double comp2(vector<double>& v)
    {

        using Task_type = double(double*,double*,double);

        packaged_task<Task_type> pt0 {&accum}; //use '&' to compile
        packaged_task<Task_type> pt1 {&accum}; //use '&' to compile

        future<double> f0 {pt0.get_future()};
        future<double> f1 {pt1.get_future()};

        double* first=&v[0];
        thread t1 {move(pt0), first, first+v.size()/2, 0};
        thread t2 {move(pt1), first+v.size()/2, first+v.size(), 0};

        // need this to run
        t1.join(); 
        t2.join();

        // using this instead of the join doesn't work
//      f0.wait(); 
//      f1.wait();

        return f0.get() + f1.get();
    }

    int main()
    {
        vector<double> v {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        cout<<comp2(v)<<endl;
        return 0;
    }
4

3 に答える 3

0

現在の回答は質問に直接答えていないと思います。タスクを実行するためにスレッドを明示的に作成する必要はありません。例えば:

#include <future>
#include <stdexcept>
#include <iostream>
#include <thread>
#include <utility>
#include <functional>

using namespace std;

int ff(int i)
{
  return i;
}

int main(int argc, char *argv[])
{

  packaged_task<int(int)> pt1 (ff);
  auto v1 = pt1.get_future();
  thread t1(move(pt1), 1);
  t1.join();

  packaged_task<int(int)> pt2(ff);
  auto v2 = pt2.get_future();
  pt2(1);
  cout << v2.get() << endl;

  return 0;
}

上記の例をコンパイルすると、標準出力として 1 が表示されます。

しかし、私を混乱させたのは、最初のpackaged_taskをコメントアウトするstd::system_errorと、完全なコードが表示されるということです:

#include <future>
#include <stdexcept>
#include <iostream>
#include <thread>
#include <utility>
#include <functional>

using namespace std;

int ff(int i)
{
  return i;
}

int main(int argc, char *argv[])
{

  // packaged_task<int(int)> pt1 (ff);
  // auto v1 = pt1.get_future();
  // thread t1(move(pt1), 1);
  // t1.join();

  packaged_task<int(int)> pt2(ff);
  auto v2 = pt2.get_future();
  pt2(1);
  cout << v2.get() << endl;

  return 0;
}

どうやら 2 つの packaged_tasks は独立しているようですが、最初のタスクを削除すると、2 つ目のタスクがsystem_error.

これは質問への回答ではなく、質問を明確にするための試みです。

于 2017-12-06T20:39:31.837 に答える