Suppose you have the following:
假设您拥有以下内容:
Test.h
Test.h
class Test {
public:
Test();
// Other member variables
void createThread();
}
Test.cpp
Test.cpp
void* threadRunnable(void* arg) {
// Uses Test class member variables
}
Test::Test(){
//
}
void Test::createThread() {
pthread_create(..,threadRunnable,..);
}
How would the function threadRunnable
passed into pthread_create
be able to access member variables without instantiating an object? Or is this not possible.
传递给pthreadcreate的函数threadRunnable如何能够在不实例化对象的情况下访问成员变量?或者这是不可能的。
Things I've tried:
我试过的东西:
- Singleton with a reference to the class (don't think this works as you still need an object first)
- Making the function
threadRunnable
a member or friend
function
Not sure what else can be done
不知道还能做些什么
更多回答
Unrelated: Why use the platform specific C library pthread
instead of the standard C++ std::thread
or std::jthread
?
无关:为什么要使用特定于平台的C库pTHREAD而不是标准的C++STD::THREAD或STD::JTHREAD?
What Ted said, and use lambda expressions to pass parameters to your thread functions. For C++20 use std::jthread for older versions use std::thread. And if you have a lambda expression you can pass it in as constructor argument of your thread. If you want a thread to calculate something and return the answer later use std::async and you can use a lambda expression with a return value
Ted说的,并使用lambda表达式将参数传递给线程函数。对于C++20使用std::jthread对于旧版本使用std::thread。如果你有一个lambda表达式,你可以把它作为线程的构造函数参数传递。如果你想让一个线程计算一些东西并在稍后返回答案,可以使用std::xmlc,你可以使用一个带返回值的lambda表达式
优秀答案推荐
You'd need to supply the pointer to threadRunnable
to pthread_create
and also a pointer to this
. Then cast arg
to a Test*
. I'm using NULL
and a C style cast from void*
to Test*
instead of nullptr
and a static_cast
which will work in pre C++11:
您需要提供指向pthREAD_CREATE的threadRunnable的指针,以及指向这个的指针。然后让Arg接受一次测试*。我使用的是从void*到Test*的NULL和C样式强制转换,而不是nullptr和STATIC_CAST,它可以在C++11之前使用:
#include <pthread.h>
#include <iostream>
class Test {
public:
~Test() {
pthread_join(th, NULL);
}
void createThread();
private:
friend void* threadRunnable(void*);
pthread_t th;
int x;
};
void* threadRunnable(void* arg) { // <-----------+
Test& tst = *((Test*)(arg)); // *this |
// Uses Test class member variables // |
tst.x = 10; // |
std::cout << tst.x << '\n'; // |
return NULL; // |
} // |
// |
void Test::createThread() { // |
pthread_create(&th, NULL, &threadRunnable, this);
}
int main() {
Test tst;
tst.createThread();
}
A somewhat cleaner way that was often used before C++11 was to make threadRunnable
a member function and to use a static
proxy function with phtread_create
:
在C++11之前经常使用的一种比较简洁的方法是使threadRunnable成为成员函数,并使用带有phtread_create的静态代理函数:
#include <pthread.h>
#include <iostream>
class Test {
public:
~Test() {
pthread_join(th, NULL);
}
void createThread();
private:
static void* runnableProxy(void*);
void threadRunnable();
pthread_t th;
int x;
};
void* Test::runnableProxy(void* instance) {
((Test*)instance)->threadRunnable();
return NULL;
}
void Test::threadRunnable() {
// Uses Test class member variables
x = 10;
std::cout << x << '\n';
}
void Test::createThread() {
pthread_create(&th, NULL, &Test::runnableProxy, this);
}
int main() {
Test tst;
tst.createThread();
}
In modern C++ you'd use std::thread
or std::jthread
instead and then there's no need for a proxy function:
在现代C++中,您可以改用std::Thress或std::JThline,这样就不需要代理函数了:
Example:
示例:
#include <iostream>
#include <thread>
class Test {
public:
void createThread();
private:
void threadRunnable();
std::jthread th;
int x;
};
void Test::threadRunnable() {
// Uses Test class member variables
x = 10;
std::cout << x << '\n';
}
void Test::createThread() {
th = std::jthread(&Test::threadRunnable, this);
}
int main() {
Test tst;
tst.createThread();
}
更多回答
Would you be able to explain how the solution with pthread may work?
你能解释一下pthread的解决方案是如何工作的吗?
@jeff I have two pthread
based solutions in the answer. The first one looks very similar to your code. Did you manage to get it working? If you did, but don't understand why, please ask about the part you want me to clarify further.
@Jeff我在答案中有两个基于pline的解决方案。第一个看起来与您的代码非常相似。你设法让它工作了吗?如果你有,但不明白为什么,请询问你想让我进一步澄清的部分。
我是一名优秀的程序员,十分优秀!