我发现了很多关于转换为void *,将参数传递给pthread_create等的零碎信息,但没有任何内容将它们联系在一起 . 我只是想确保我've tied it all together and am not doing anything stupid. Let' s说我有以下线程类: Edit: 已修复错误匹配 static_cast
.
class ProducerThread {
pthread_t thread;
pthread_attr_t thread_attr;
ProducerThread(const ProducerThread& x);
ProducerThread& operator= (const ProducerThread& x);
virtual void *thread_routine(void *arg) {
ProtectedBuffer<int> *buffer = static_cast<ProtectedBuffer<int> *> arg;
int randomdata;
while(1) {
randomdata = RandomDataGen();
buffer->push_back(randomdata);
}
pthread_exit();
}
public:
ProtectedBuffer<int> buffer;
ProducerThread() {
int err_chk;
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED);
err_chk = pthread_create(&thread, &thread_attr, thread_routine, static_cast<void *> arg);
if (err_chk != 0) {
throw ThreadException(err_chk);
}
}
~ProducerThread() {
pthread_cancel(&thread);
pthread_attr_destroy(&thread_attr);
}
}
为了澄清, ProtectedBuffer
类中的数据只能使用 ProtectedBuffer::push_back(int arg)
等方法访问,这些方法使用互斥锁来保护实际数据 .
我的主要问题是:我正确使用 static_cast
吗?我的第二个问题是我需要_490108中的第一行,我将传递的void指针复制到指向 ProtectedBuffer
的指针?
另外,如果我做了其他可能导致问题的事情,我会很感激听到它 .
2 回答
如果你想走这条路,我相信你想要这样的东西:
Edit: 根据James Kanze的回答,在构造完成后添加一个单独的
activate
方法来启动线程 .然后,
ProducerThread
将派生自GenericThread
.Edit: 在C标准中搜索extern“C” . 没有要求函数指针必须指向C链接可以被C库例程调用的函数 . 由于指针正在传递,因此链接要求不适用,因为链接用于解析名称 . 根据C 2011草案(n3242),Sec . 指向静态方法的指针是一个函数指针 . 3.9.2p3:
Edit: Mea culpa . 假设C应用程序二进制接口,C库将调用回调函数 . 具有C链接的函数可以使用与C ABI不同的ABI . 这就是为什么在将回调函数传递给C库时需要使用具有
extern "C"
链接的函数 . 我真诚地向James Kanze表示怀疑,并对Loki Astari让我感到非常不满 .您的代码存在许多问题 . 对于初学者,我没有看到你所投射的
arg
在哪里,所以我不能说这个案例是否合适 .也许更重要的是,
thread_routine
是一个成员函数,因此无法将其转换为指向函数的指针 . 传递给pthread_create
的函数必须是extern "C"
,因此它不能是成员,句点;它必须是一个自由函数声明extern "C"
. 如果要调用成员函数,请将指向对象的指针作为最后一个参数传递,并在extern "C"
函数中取消引用它:并启动线程:
只是不要在构造函数中执行此操作 . 另一个线程可能在完全构造对象之前开始运行,具有灾难性影响 .
此外,请确保
startProducerThread
中的强制转换与传入pthread_create
的指针完全相同 . 如果你转换为startProducerThread
中的基类,那么非常非常肯定它是一个指向你传递给pthread_create
的基类的指针;必要时使用显式强制转换(对于startProducerThread
中的类型,而不是void*
) .最后,虽然与您的实际问题无关:如果
ProtectedBuffer
具有类似std::vector
的接口,并返回对内部数据的引用,则无法使其线程安全 . 保护需要在课堂外部 .