【发布时间】:2013-11-04 18:48:06
【问题描述】:
我正在尝试使用 boost::thread 在 C++ 上的线程上实现 Actor 计算模型。 但是程序在执行过程中抛出了奇怪的异常。异常不稳定,有时程序以正确的方式运行。
那里有我的代码:
actor.hpp
class Actor {
public:
typedef boost::function<int()> Job;
private:
std::queue<Job> d_jobQueue;
boost::mutex d_jobQueueMutex;
boost::condition_variable d_hasJob;
boost::atomic<bool> d_keepWorkerRunning;
boost::thread d_worker;
void workerThread();
public:
Actor();
virtual ~Actor();
void execJobAsync(const Job& job);
int execJobSync(const Job& job);
};
actor.cpp
namespace {
int executeJobSync(std::string *error,
boost::promise<int> *promise,
const Actor::Job *job)
{
int rc = (*job)();
promise->set_value(rc);
return 0;
}
}
void Actor::workerThread()
{
while (d_keepWorkerRunning) try {
Job job;
{
boost::unique_lock<boost::mutex> g(d_jobQueueMutex);
while (d_jobQueue.empty()) {
d_hasJob.wait(g);
}
job = d_jobQueue.front();
d_jobQueue.pop();
}
job();
}
catch (...) {
// Log error
}
}
void Actor::execJobAsync(const Job& job)
{
boost::mutex::scoped_lock g(d_jobQueueMutex);
d_jobQueue.push(job);
d_hasJob.notify_one();
}
int Actor::execJobSync(const Job& job)
{
std::string error;
boost::promise<int> promise;
boost::unique_future<int> future = promise.get_future();
{
boost::mutex::scoped_lock g(d_jobQueueMutex);
d_jobQueue.push(boost::bind(executeJobSync, &error, &promise, &job));
d_hasJob.notify_one();
}
int rc = future.get();
if (rc) {
ErrorUtil::setLastError(rc, error.c_str());
}
return rc;
}
Actor::Actor()
: d_keepWorkerRunning(true)
, d_worker(&Actor::workerThread, this)
{
}
Actor::~Actor()
{
d_keepWorkerRunning = false;
{
boost::mutex::scoped_lock g(d_jobQueueMutex);
d_hasJob.notify_one();
}
d_worker.join();
}
实际上抛出的异常是 int rc = future.get(); 行中的 boost::thread_interrupted。但是形成 boost 文档我不能解释这个例外。文档说
抛出: - boost::thread_interrupted 如果与 *this 相关的结果在调用时尚未准备好,并且当前线程被中断。
但是我的工作线程不能处于中断状态。
当我使用 gdb 并设置“catch throw”时,我看到回溯看起来像
抛出线程中断
boost::detail::interruption_checker::check_for_interruption
boost::detail::interruption_checker::interruption_checker
boost::condition_variable::wait
boost::detail::future_object_base::wait_internal
boost::detail::future_object_base::wait
boost::detail::future_object::get
boost::unique_future::get
我查看了 boost 源,但不明白为什么 interrupt_checker 决定工作线程被中断。
所以有人 C++ 大师,请帮助我。我需要做什么才能获得正确的代码? 我正在使用:
提升 1_53
Linux 版本 2.6.18-194.32.1.el5 Red Hat 4.1.2-48
gcc 4.7
编辑
修好了!感谢 Evgeny Panasyuk 和 Lazin。问题出在 TLS 中 管理。 boost::thread 和 boost::thread_specific_ptr 正在使用 相同的 TLS 存储用于其目的。就我而言,当 他们都试图在创建时更改此存储(不幸的是,我 不明白为什么会发生这种情况)。所以 TLS 被破坏了。
我将代码中的 boost::thread_specific_ptr 替换为 __thread 指定变量。
Offtop:在调试过程中,我发现外部库中的内存损坏 并修复它=)
.
编辑 2 我得到了确切的问题......这是GCC中的一个错误=) _GLIBCXX_DEBUG 编译标志会破坏 ABI。 你可以看到关于 boost bugtracker 的讨论: https://svn.boost.org/trac/boost/ticket/7666
【问题讨论】:
-
"在我的情况下,当他们都试图在创建时更改此存储时出现问题" - 很高兴看到一些代码显示了这一点。可能是 Boost 中的错误 - 所以我们应该报告它。
-
“我将代码中的 boost::thread_specific_ptr 替换为 __thread 指定变量。” - 那么,另一个 TLS 插槽会损坏吗? =)
标签: c++ multithreading boost actor