0

Boost1.49とMSVC10を使用しています。

aboost::threadが呼び出し可能なオブジェクト1で構成されていて、そのオブジェクトに、コンテキストの外部threadからアクセスしたいメンバー関数または変数がある場合、callabeオブジェクトにアクセスするにはどうすればよいですか?

たとえば、vector<boost::thread*>ローカルに保存された5つのワーカースレッドを生成する単純なアプリケーションを実装しましたmain()。これらの各スレッドは、コンストラクターでGizmo1つのcharパラメーターを受け取る呼び出し可能なオブジェクトでインスタンス化されます。これは、クラスのメンバー変数charとして保存されます。各スレッドは保存され、250ミリ秒間スリープします。どういうわけかsavesの値が「die」になるまで、このループで永遠に続きます。std::stringGizmocoutstringstring

短く、自己完結型、(うまくいけば)正しい、例

#include <cstdlib>
#include <string>
#include <memory>
#include <vector>
using namespace std;

#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

boost::mutex cout_mtx;

class Gizmo
{
public:
    Gizmo(const string& state) : state_(state) {};
    Gizmo(Gizmo&& rhs) : state_(std::move(rhs.state_)) {};
    virtual ~Gizmo()
    {
        bool b = true;
    }
    void operator()();

    string state_;
};

void Gizmo::operator()()
{
    while( state_ != "die" )
    {
        {
            boost::mutex::scoped_lock scoped_lock(cout_mtx);
            cout << state_ << flush;
        }
        boost::this_thread::sleep(boost::posix_time::milliseconds(250));
    }
}

boost::thread* start_thread(char c)
{
    Gizmo g(string(1,c));
    return new boost::thread(g);
}

int main()
{
    vector<boost::thread*> threads;

    string d=".*x%$";
    for( string::const_iterator it = d.begin(); it != d.end(); ++it )
    {
        threads.push_back(start_thread(*it));
    }

    for( auto th = threads.begin(); th != threads.end(); ++th )
        (*th)->join();
}

ここで、コードを変更したいと思いますmain()

  1. で最初のものを入手threadしてくださいvector
  2. Gizmoその中に含まれるオブジェクトを取得しますthread
  3. state_「死ぬ」に設定する

Gizmoスレッド内を取得するにはどうすればよいですか?

for( auto th = threads.begin(); th != threads.end(); ++th )
{
    boost::this_thread::sleep(boost::posix_time::seconds(1));
    Gizmo& that_gizmo = (*th)-> ??? ;  // WHAT DO I DO?
    that_gizmo.state_ = "die";
}

(1)このコンテキストでの呼び出し可能オブジェクトclassとは、。を伴うaを意味しoperator()ます。

4

3 に答える 3

2

start_thread() メソッドは、スレッドに渡される一時的なスタック オブジェクトを作成しています。代わりに、main() でギズモ オブジェクトのベクターを作成し、そのベクターの各メンバー (ギズモ) をブーストのスレッド コンストラクターに渡す必要があります。メイン関数のベクトルにスレッドの呼び出し可能オブジェクトへの参照を格納できる場合に、スレッドの呼び出し可能なオブジェクトを具体的に取得する必要がある理由はわかりません。

メインスレッドとそれをチェックするブーストスレッドの間で状態の設定を同期することを忘れないでください。

于 2012-06-09T17:03:44.567 に答える
1

にはboost::thread、呼び出し可能なオブジェクトを取得する機能はありません。 boost::threadデフォルトのコンストラクターがあるため、スレッドのエントリ ポイントとして機能する呼び出し可能な型または関数はわかりません。また、boost::thread型消去を実行しないと、同じコレクションまたはスレッド プール内の異なるエントリ ポイントを持つスレッドを管理できなくなります。たとえば、スレッドstd::vector< boost::thread< Gizmo > >のみを管理でき、スレッドと非スレッドを管理できます。Gizmostd::vector< boost::thread >GizmoGizmo

Gizmoboost::threadオブジェクトを別々のリストで管理したり、新しいタイプを作成して 2 つをペアにしたりする代わりに、std::pairまたはを介し​​て 2 つを関連付けることを検討してboost::tupleください。例えば:

std::vector< boost::tuple< boost::thread*, Gizmo > > threads;

また、スレッドがエントリ ポイントに複数のタイプを使用することになり、各タイプに独自の形式のシャットダウンが必要な場合は、 を介してタイプの消去を実行することを検討してboost::functionください。例えば:

void shutdown_gizmo( Gizmo& );

boost::function< void() > fn = boost::bind( shutdown_gizmo, boost::ref( gizmo ) );

// The tuple now contains a function object, decoupling it from Gizmo objects,
// and allowing other shutdown methods to be paired with threads.
typedef boost::tuple< boost::thread*, boost::function< void() > > tuple_t;
std::vector< tuple_t > threads;

どのソリューションでも、オブジェクトのスコープを維持することと、正しいオブジェクトGizmoへのハンドルを維持することに注意してください。Gizmo実際のGizmoオブジェクトのコピーへのハンドルを意図せずに取得するのはかなり簡単です。

于 2012-06-09T23:06:22.850 に答える