在运行之前获取 std::thread 的 thread:id?
Get std::thread's thread:id before it runs?
我正在尝试在 C++ 11 的 std::thread
之上构建一个线程安全层,其中每个对象都分配给一个拥有的线程,并且某些调用在用于错误的线程。拥有线程是唯一可以将对象传输到另一个线程的线程。
我已经全部正常工作了,除了,我找不到在线程实际 运行ning 之前获取线程的 thread::id
的方法。我需要在传递之前将新线程的 ID 附加到对象。
如果我用
std::thread newThread( [theObject]()
{
// use theObject here.
} );
我最早能得到线程的ID是在线程对象定义之后,此时线程已经运行ning.
我看到 std::thread
有一个默认的构造函数,但我看不出有什么方法可以在之后的线程上为 运行 提供一个函数。
有没有办法在线程上执行两步构建,或者在创建时控制线程的ID?
不——一创建线程,它就开始运行。如果你想在它做(大部分)任何事情之前获得它的 ID,你可能想要创建一个小包装器,你可以在其中传递线程(例如)一个 CV 和一个队列,它存放它的输出。
然后当线程启动时,它会检索自己的ID,将其存放在输出队列中,然后等待CV。当 parent 检索到 ID,并准备好让 child 开始做某事时,它会向 CV 发出信号,然后它就开始了。
与其在线程启动前获取线程 ID 运行,不如考虑让线程执行的函数在启动前进行一些初始设置。例如,您可以这样做:
bool isReady = false;
bool wasReceived = false;
std::mutex mutex;
std::condition_variable condition;
std::thread newThread([theObject, &isReady, &mutex, &condition] {
/* Wait until we've been cleared to go. */
std::unique_lock<std::mutex> lock(isReady);
condition.wait(lock, [&isReady] { return isReady; });
/* Signal that we're done. */
wasReceived = true;
lock.unlock();
condition.notify_one();
/* Put code here to do whatever it is that the thread should do. */
});
/* Read the thread's ID. It's currently waiting for us. */
auto id = newThread.get_id();
/* Tell the thread that we're ready for it. */
std::unique_lock<std::mutex> lock(mutex);
isReady = true;
condition.notify_one();
/* Wait until the thread has confirmed that it's ready. */
condition.wait(lock, [&] { return wasReceived; });
这将创建线程并让它等待创建者有机会读取其 ID。一旦发生这种情况,创建者就会等待线程确认它已准备就绪,然后您可以根据需要使用线程 ID。
当心上述代码中的错误 - 它完全未经测试。 :-)
通过传递唯一的 std::promise 参数启动每个非活动线程,首先获取线程 ID(线程 ID 用作传递引用参数)然后让它等待设置承诺由线程管理器。这也将消除使用条件变量的麻烦。
已编辑 片段
class smart_thread {
public:
smart_thread(std::function<void(void)> task)
{
thread_ = std::thread([=]() {
id_ = std::this_thread::get_id();
// wait here till activated
future_.get();
if(active_) task();
});
}
void activate() {
promise_.set_value();
active_ = true;
}
~smart_thread() {
if(!active_) promise_.set_value();
thread_.join();
}
private:
std::thread::id id_;
std::atomic<bool> active_ = false;
std::thread thread_;
std::promise<void> promise_;
std::future<void> future_ = promise_.get_future();
};
void main()
{
auto task = []() { std::cout << "Hello World\n"; };
smart_thread thread(task); // start thread inactive mode
thread.activate(); // activate thread
}
是否可以创建一个模板 class 以 std::function<void(T *object)>
的形式接受线程例程。如果需要传入额外的参数,这可以通过匿名闭包轻松完成。
template <class T>
class ThreadWrapper
{
public:
ThreadWrapper(std::function<void(T *object)> function, T *object) :
{
m_thread = std::thread(WrapFunction, function, object);
//optionally
m_thread.detach();
}
static void WrapFunction(ThreadWrapper *wrapper, std::function<void()> function, T *object)
{
// Get the thread id and save in the object
object->SetThreadId(get_id());
// Now actually invoke the thread routine, with the id already installed.
function(object);
}
}
// Cleanup is left as an exercise for the reader.
当心上述代码中的错误 - 它完全未经测试。 :-) :-)
我正在尝试在 C++ 11 的 std::thread
之上构建一个线程安全层,其中每个对象都分配给一个拥有的线程,并且某些调用在用于错误的线程。拥有线程是唯一可以将对象传输到另一个线程的线程。
我已经全部正常工作了,除了,我找不到在线程实际 运行ning 之前获取线程的 thread::id
的方法。我需要在传递之前将新线程的 ID 附加到对象。
如果我用
std::thread newThread( [theObject]()
{
// use theObject here.
} );
我最早能得到线程的ID是在线程对象定义之后,此时线程已经运行ning.
我看到 std::thread
有一个默认的构造函数,但我看不出有什么方法可以在之后的线程上为 运行 提供一个函数。
有没有办法在线程上执行两步构建,或者在创建时控制线程的ID?
不——一创建线程,它就开始运行。如果你想在它做(大部分)任何事情之前获得它的 ID,你可能想要创建一个小包装器,你可以在其中传递线程(例如)一个 CV 和一个队列,它存放它的输出。
然后当线程启动时,它会检索自己的ID,将其存放在输出队列中,然后等待CV。当 parent 检索到 ID,并准备好让 child 开始做某事时,它会向 CV 发出信号,然后它就开始了。
与其在线程启动前获取线程 ID 运行,不如考虑让线程执行的函数在启动前进行一些初始设置。例如,您可以这样做:
bool isReady = false;
bool wasReceived = false;
std::mutex mutex;
std::condition_variable condition;
std::thread newThread([theObject, &isReady, &mutex, &condition] {
/* Wait until we've been cleared to go. */
std::unique_lock<std::mutex> lock(isReady);
condition.wait(lock, [&isReady] { return isReady; });
/* Signal that we're done. */
wasReceived = true;
lock.unlock();
condition.notify_one();
/* Put code here to do whatever it is that the thread should do. */
});
/* Read the thread's ID. It's currently waiting for us. */
auto id = newThread.get_id();
/* Tell the thread that we're ready for it. */
std::unique_lock<std::mutex> lock(mutex);
isReady = true;
condition.notify_one();
/* Wait until the thread has confirmed that it's ready. */
condition.wait(lock, [&] { return wasReceived; });
这将创建线程并让它等待创建者有机会读取其 ID。一旦发生这种情况,创建者就会等待线程确认它已准备就绪,然后您可以根据需要使用线程 ID。
当心上述代码中的错误 - 它完全未经测试。 :-)
通过传递唯一的 std::promise 参数启动每个非活动线程,首先获取线程 ID(线程 ID 用作传递引用参数)然后让它等待设置承诺由线程管理器。这也将消除使用条件变量的麻烦。
已编辑 片段
class smart_thread {
public:
smart_thread(std::function<void(void)> task)
{
thread_ = std::thread([=]() {
id_ = std::this_thread::get_id();
// wait here till activated
future_.get();
if(active_) task();
});
}
void activate() {
promise_.set_value();
active_ = true;
}
~smart_thread() {
if(!active_) promise_.set_value();
thread_.join();
}
private:
std::thread::id id_;
std::atomic<bool> active_ = false;
std::thread thread_;
std::promise<void> promise_;
std::future<void> future_ = promise_.get_future();
};
void main()
{
auto task = []() { std::cout << "Hello World\n"; };
smart_thread thread(task); // start thread inactive mode
thread.activate(); // activate thread
}
是否可以创建一个模板 class 以 std::function<void(T *object)>
的形式接受线程例程。如果需要传入额外的参数,这可以通过匿名闭包轻松完成。
template <class T>
class ThreadWrapper
{
public:
ThreadWrapper(std::function<void(T *object)> function, T *object) :
{
m_thread = std::thread(WrapFunction, function, object);
//optionally
m_thread.detach();
}
static void WrapFunction(ThreadWrapper *wrapper, std::function<void()> function, T *object)
{
// Get the thread id and save in the object
object->SetThreadId(get_id());
// Now actually invoke the thread routine, with the id already installed.
function(object);
}
}
// Cleanup is left as an exercise for the reader.
当心上述代码中的错误 - 它完全未经测试。 :-) :-)