質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.07%

boost::fiber でスタックサイズを指定したい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 228

cugel

score 219

boost::fiber で packaged_task を作成する際に、fixedsize_stack アロケータを指定したい

Boost 1.72 を使っています。
コンパイラは FreeBSD stable/12 上の clang version 8.0.1 です。
boost::fiber を使ったコードを書いていて、packaged_task を作成する際に、スタックサイズを指定したいのですが、スタックアロケータを指定するとコンパイルエラーが出てコンパイルできません。
なんとかする方法はありますでしょうか。

発生している問題・エラーメッセージ

In file included from test_stackallocator.cpp:1:
In file included from /usr/include/c++/v1/iostream:38:
In file included from /usr/include/c++/v1/ios:216:
In file included from /usr/include/c++/v1/__locale:15:
In file included from /usr/include/c++/v1/string:505:
In file included from /usr/include/c++/v1/string_view:176:
In file included from /usr/include/c++/v1/__string:57:
In file included from /usr/include/c++/v1/algorithm:644:
/usr/include/c++/v1/memory:1515:38: error: no type named 'value_type' in 'boost::context::basic_fixedsize_stack<boost::context::stack_traits>'
    typedef typename allocator_type::value_type value_type;
            ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
/usr/local/include/boost/fiber/future/detail/task_object.hpp:115:22: note: in instantiation of template class 'std::__1::allocator_traits<boost::context::basic_fixedsize_stack<boost::context::stack_traits> >' requested here
    typedef typename allocator_traits::template rebind_alloc<
                     ^
/usr/local/include/boost/fiber/future/packaged_task.hpp:57:22: note: in instantiation of template class 'boost::fibers::detail::task_object<boost::_bi::bind_t<void, void (*)(std::__1::basic_string<char>, boost::function<void ()>), boost::_bi::list2<boost::_bi::value<std::__1::basic_string<char> >, boost::_bi::value<boost::function<void ()> > > >, boost::context::basic_fixedsize_stack<boost::context::stack_traits>, void>' requested here
            typename object_type::allocator_type
                     ^
test_stackallocator.cpp:47:12: note: in instantiation of function template speci
alization 'boost::fibers::packaged_task<void ()>::packaged_task<boost::_bi::bind
_t<void, void (*)(std::__1::basic_string<char>, boost::function<void ()>), boost
::_bi::list2<boost::_bi::value<std::__1::basic_string<char> >, boost::_bi::value<boost::function<void ()> > > >, boost::context::basic_fixedsize_stack<boost::context::stack_traits> >' requested here
    pack_t pt(std::allocator_arg, fs_t(stacksize),
           ^
In file included from test_stackallocator.cpp:10:
In file included from /usr/local/include/boost/fiber/future/packaged_task.hpp:20:
/usr/local/include/boost/fiber/future/detail/task_object.hpp:115:49: error: no member named 'rebind_alloc' in 'std::__1::allocator_traits<boost::context::basic_fixedsize_stack<boost::context::stack_traits> >'
    typedef typename allocator_traits::template rebind_alloc<
                     ~~~~~~~~~~~~~~~~~~         ^
/usr/local/include/boost/fiber/future/packaged_task.hpp:57:22: note: in instantiation of template class 'boost::fibers::detail::task_object<boost::_bi::bind_t<void, void (*)(std::__1::basic_string<char>, boost::function<void ()>), boost::_bi::list2<boost::_bi::value<std::__1::basic_string<char> >, boost::_bi::value<boost::function<void ()> > > >, boost::context::basic_fixedsize_stack<boost::context::stack_traits>, void>' requested here
            typename object_type::allocator_type
                     ^
test_stackallocator.cpp:47:12: note: in instantiation of function template specialization 'boost::fibers::packaged_task<void ()>::packaged_task<boost::_bi::bind_t<void, void (*)(std::__1::basic_string<char>, boost::function<void ()>), boost::_bi::list2<boost::_bi::value<std::__1::basic_string<char> >, boost::_bi::value<boost::function<void ()> > > >, boost::context::basic_fixedsize_stack<boost::context::stack_traits> >' requested here
    pack_t pt(std::allocator_arg, fs_t(stacksize),
           ^
In file included from test_stackallocator.cpp:10:
/usr/local/include/boost/fiber/future/packaged_task.hpp:61:46: error: no viable conversion from 'const boost::context::basic_fixedsize_stack<boost::context::stack_traits>' to 'typename object_type::allocator_type' (aka 'int')
        typename object_type::allocator_type a{ alloc };
                                             ^~~~~~~~~~
test_stackallocator.cpp:47:12: note: in instantiation of function template specialization 'boost::fibers::packaged_task<void ()>::packaged_task<boost::_bi::bind_t<void, void (*)(std::__1::basic_string<char>, boost::function<void ()>), boost::_bi::list2<boost::_bi::value<std::__1::basic_string<char> >, boost::_bi::value<boost::function<void ()> > > >, boost::context::basic_fixedsize_stack<boost::context::stack_traits> >' requested here
    pack_t pt(std::allocator_arg, fs_t(stacksize),
           ^
3 errors generated.
(END)

該当のソースコード

もとのコードを簡単にしようとしたら何やら無駄な感じの多いコードになってしまいましたが…。

#include <iostream>
#include <memory>
#include <string>

// boost 1.72
#include <boost/bind.hpp>
#include <boost/fiber/fiber.hpp>
#include <boost/fiber/fixedsize_stack.hpp>
#include <boost/fiber/future/future.hpp>
#include <boost/fiber/future/packaged_task.hpp>
#include <boost/function.hpp>

typedef boost::fibers::packaged_task<void()> pack_t;
typedef boost::fibers::shared_future<void> shared_future_t;
using fiber = boost::fibers::fiber;
typedef boost::fibers::fixedsize_stack fs_t;
typedef boost::function<void()> callable_t;

class Container;
class Data;

class Container {
private:
    Data* mdata;
public:
    Container() : mdata(0) {}
    ~Container();
    static void toplevel(const std::string name, callable_t callable);
    void launch(const std::string name, callable_t callable);
};

class Data {
public:
    std::string mname;
    fiber mfib;
    shared_future_t mfuture;

    Data(const std::string& name, callable_t callable, size_t stacksize);
    ~Data() {}
    const std::string Name() { return mname; }
};

Data::Data(const std::string& name, callable_t callable, size_t stacksize) :
    mname(name), mfib(), mfuture()
{
    pack_t pt(std::allocator_arg, fs_t(stacksize),
              boost::bind(Container::toplevel, name, callable));
    mfuture = pt.get_future();
    fiber(std::move(pt)).detach();
    std::cout << "Data waits." << std::endl;
}

void callback()
{
    for(int i=0; i<5; ++i)
    {
        std::cout << "callback counts: " << i << std::endl;
    }
}

Container::~Container()
{
    delete(mdata);
}

void Container::toplevel(const std::string name, callable_t callable)
{
    std::cout << "toplevel: " << name << std::endl;
    callable();
}

void Container::launch(const std::string name, callable_t callable)
{
    if(mdata)
        return;
    std::cout << "launch: " << name << std::endl;
    mdata = new Data(name, callable, 1024);
    mdata->mfuture.wait();
}

int main()
{
    Container c;
    c.launch(std::string("from main"), callback);
}

試したこと

以下のようにスタックアロケータを指定しないコードにしたら通ります。

pack_t pt(boost::bind(Container::toplevel, name, callable));


/usr/local/include/boost/fiber/future/detail/task_object.hpp の 37行目に

typedef std::allocator_traits< Allocator >  allocator_traits;

とあるのが問題になっているようだというところまではなんとかわかりましたが、その先どうすればよいのかわかりません。

補足

Boost の fiber の issue #106 と似た問題のようなんですが、こちらは3年も前に解決済みとされています。とすると私の書き方になにか間違いがあるのだと思いますが。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

やりたいことは、次のようなコードでしょうか?https://wandbox.org/permlink/ZO1WiF3yNi1bwghl
(補足:スタックサイズ1024ではSEGVするため適当に10倍しています。)

Data::Data(const std::string& name, callable_t callable, size_t stacksize) :
    mname(name), mfib(), mfuture()
{
    pack_t pt(/*std::allocator_arg, fs_t(stacksize),*/
              boost::bind(Container::toplevel, name, callable));
    mfuture = pt.get_future();
    fiber(std::allocator_arg, fs_t(stacksize),  // ←HERE
          std::move(pt)).detach();
    std::cout << "Data waits." << std::endl;
}

fibers::packaged_task標準アロケータを要求します。一方、fibers::fixedsize_stackfibers::fiber専用Stack-Allocator要件を満たすものです。名前は似ていますが、目的が異なる全くの別物です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/05/07 10:51

    ありがとうございます。そういうことだったんですね。助かりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.07%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る