0

我正在使用 Boost 1.49 和 MSVC10。

如果 aboost::thread是用可调用对象1构造的,并且该对象具有我想从的上下文外部thread访问的成员函数或变量,我如何访问 callabe 对象?

例如,我实现了一个简单的应用程序,它产生 5 个工作线程,保存到vector<boost::thread*>本地到main(). 这些线程中的每一个都使用一个可调用对象进行实例化,该对象在其构造函数中Gizmo采用一个char参数。这char被保存为类std::string中的成员变量Gizmo。每个线程将cout被保存string,然后休眠 250 毫秒。它永远在这个循环中继续,直到不知何故 savesstring的价值变成“死”。

简短,独立,(希望)正确,示例

#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)在这种情况下,可调用对象意味着 aclassoperator()

4

3 回答 3

2

您的 start_thread() 方法正在创建一个临时的堆栈对象,然后将其传递给线程。相反,您应该在 main() 中创建一个 Gizmo 对象向量,然后将该向量的每个成员(一个 Gizmo)传递给 boost 的线程构造函数。当您可以在主函数的向量中存储对线程的可调用对象时,我看不出有什么理由应该专门获取线程的可调用对象。

请记住在主线程和检查它的 boost 线程之间同步状态设置。

于 2012-06-09T17:03:44.567 回答
1

你不能实现一个start_thread类,让你访问仿函数,而不是一个函数,并保留一个指向这些指针的向量吗?类似的东西(细节有待解决,这些都没有经过测试):

class start_thread {
 public:
  explicit start_thread(char c) : gizmo_(std::string(c,1)), t_(gizmo_) {}
  void join() { t_.join();}
  const Gizmo& callable() const { return gizmo_;}
  Gizmo& callable() { return gizmo_;}
 private:
  Gizmo gizmo_;
  boost::thread t_;
}

您需要将 传递gizmo_给线程构造函数作为boost::ref(gizmo_).

于 2012-06-09T16:32:14.517 回答
1

boost::thread不提供获取可调用对象的能力 。boost::thread有一个默认构造函数,所以它不知道将作为线程入口点的可调用类型或函数。此外,如果boost::thread不执行类型擦除,则将无法再管理同一集合或线程池中具有不同入口点的线程。例如,std::vector< boost::thread< Gizmo > >只能管理Gizmo线程,而std::vector< boost::thread >可以管理Gizmo线程和非Gizmo线程。

不必在单独的列表中管理Gizmoboost::thread对象,或者创建一个新类型来将两者配对在一起,而是考虑通过std::pair或将两者关联起来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 回答