访问可调用对象一个boost :: thread被构造

时间:2012-06-09 15:40:03

标签: c++ boost boost-thread

我正在使用Boost 1.49和MSVC10。

如果使用可调用对象 1 构造boost::thread,并且该对象具有我想要从{{1}的上下文之外的访问的成员函数或变量} ,我如何找到callabe对象?

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

Short, Self Contained, (Hopefully) Correct, Example

string

现在我想在#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(); } 中进行代码更改,其中包括:

  1. 获取main()
  2. 中的第一个thread
  3. 获取vector
  4. 中包含的Gizmo对象
  5. thread设置为“die”
  6. 如何在线程中获得state_

    Gizmo

    (1)此上下文中的可调用对象表示带有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}}。

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分: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_)传递给线程构造函数。

答案 2 :(得分:1)

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

不必在单独的列表中管理Gizmoboost::thread个对象,也不必创建新的类型以将两者配对,请考虑通过std::pair或{{1}将两者关联起来}。例如:

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对象副本的句柄可能相当容易。