移动具有线程作为成员变量的类的操作 [英] Move operations for a class with a thread as member variable
问题描述
我想扩展一些人帮助我的地方调用函数里面的lambda传递给线程所以我的工人类可以支持移动构造函数和移动 operator =
,但我有问题,我的类通过复制(或引用)绑定到线程,因此它可以访问类值 this
。其中有几个 atomic
, condition_variable
和 mutex
。
I'm trying to expand with what some people helped me here Call function inside a lambda passed to a thread so my worker class can support a move constructor and a move operator=
, but I have the problem that my class is binding this
by copy (or reference) to the thread so it can access the class values. Which are several atomic<bool>
, a condition_variable
and a mutex
.
但是当我尝试移动它,因为线程绑定到其他条件变量, mutex
和 atomic
s,我做的任何东西都不工作。如何解决这个问题?
我需要使用一个更复杂的对象,并移动它而不是lambda,所以线程可以有一个referenece吗?或有另一种选择。
But when I try to move it since the thread is bound to the other condition variable, mutex
and atomic
s, anything I do on it is not working. How can I fix this?
Do I need to use a more complex object and move it around instead of a lambda so the thread can have a referenece to it? or is there another alternative.
As always help will be really appreciated :).
这是一个实现的代码片段(MWE)。
Here is a snippet (MWE) of the implementation.
class worker {
public:
template <class Fn, class... Args>
explicit worker(Fn func, Args... args) {
t = std::thread(
[&func, this](Args... cargs) -> void {
std::unique_lock<std::mutex> lock(mtx);
while (true) {
cond.wait(lock, [&]() -> bool { return ready; });
if (terminate)
break;
func(cargs...);
ready = false;
}
},
std::move(args)...);
}
worker(worker &&w) : t(std::move(w.t)) { /* here there is trouble */ }
worker &operator=(worker &&w) {
t = std::move(w.t);
terminate.store(wt.terminate);
ready.store(wt.ready);
return *this;
/* here too */
}
~worker() {
terminate = true;
if (t.joinable()) {
run_once();
t.join();
}
}
worker() {}
void run_once() {
std::unique_lock<std::mutex> lock(mtx);
ready = true;
cond.notify_one();
}
bool done() { return !ready; }
private:
std::thread t;
std::atomic<bool> ready, terminate; // What can I do with all these?
std::mutex mtx; //
std::condition_variable cond; //
};
int main() {
worker t;
t = worker([]() -> void { cout << "Woof" << endl; });
t.run_once();
while(!t.done()) ;
return 0;
}
很抱歉代码的大转储。
推荐答案
我可以通过工人
不可复制和不可移动来解决它,并留给用户 worker
将其存储为 unique_ptr
这没有什么错。
I would 'fix' it by just saying worker
is noncopyable and nonmoveable and leave it to the user of worker
to store it as a unique_ptr
if they want to move it around. There's nothing wrong with that at all. It's ordinary, actually.
如果你绝对希望这个类是可移动的,你可以使用Pimpl设计模式:make a Worker :: Impl
拥有
>和函数,转发到 unique_ptr
的嵌套类。 Impl
类将不可复制和不可移动,基本上是您当前的 worker
类。 lambda将有一个指向 Impl
类的指针,而不是 worker
类。 worker
类将不包含除 Impl
unique_ptr Impl
类的函数,并且默认的复制和移动ctors /操作符只会正常工作两个类(工人将可复制但不可移动, impl将是不可复制和不可移动的)。
If you absolutely want this class to be movable, you could use the Pimpl design pattern: make a Worker::Impl
nested class which worker
owns by unique_ptr
. The Impl
class would be noncopyable and nonmovable and basically be your current worker
class. The lambda would have a pointer to the Impl
class, not the worker
class. The worker
class would contain nothing except a unique_ptr
to the Impl
and functions that forward to the Impl
class' functions, and the defaulted copy and move ctors/operators will just work properly for both classes (worker will be copyable but not movable, impl will be noncopyable and nonmovable).
这篇关于移动具有线程作为成员变量的类的操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!