我正在使用Boost 1.49和MSVC10。
如果使用可调用对象 1 构造boost::thread
,并且该对象具有我想要从{{1}的上下文之外的访问的成员函数或变量} ,我如何找到callabe对象?
例如,我实现了一个简单的应用程序,它生成5个工作线程,保存到thread
本地vector<boost::thread*>
。这些线程中的每一个都使用可调用对象main()
进行实例化,该对象在其构造函数中采用一个Gizmo
参数。此char
在char
类中保存为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();
}
中进行代码更改,其中包括:
main()
thread
vector
Gizmo
对象
thread
设置为“die”如何在线程中获得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}}。
答案 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
个线程。
不必在单独的列表中管理Gizmo
和boost::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
对象副本的句柄可能相当容易。