gpt4 book ai didi

c++ - 如何让 std::thread 对传递给它的函数的参数进行一般构造?

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:19:47 24 4
gpt4 key购买 nike

std::thread 的构造函数和类似的接口(interface),如 std::async 将它们的参数复制到线程可访问的存储中,就像通过函数一样

template <class T>
typename decay<T>::type decay_copy(T&& v) {
return std::forward<T>(v);
}

此函数可以处理移动和复制构造函数,但我想知道是否可以概括这些参数的构造方式,类似于 .emplace() 概括 .insert()< 的方式 在标准容器接口(interface)中。

例如,我可能有一个只能从 int 构造的可移动类型:

struct foo
{
foo(int arg){}
foo(foo&& other){}

foo() = delete;
foo(const foo&) = delete;
};

是否可以为这样的类型创建一个helper,通过decay_copy 复制构造会产生构造其他类型的效果?

我知道如何创建一个将 foo 的参数复制到线程可访问存储中的解决方案,但我想避免这种情况(假设这些参数在一般情况下和线程可访问存储中是巨大的稀缺)。

这是我最初的尝试:

#include <thread>
#include <utility>

struct foo
{
foo(int arg){}
foo(foo&& other){}

foo() = delete;
foo(const foo&) = delete;
};


template<class T, class Arg>
struct helper
{
operator T () const
{
return T{arg_};
}

Arg arg_;
};


template<class T, class Arg>
helper<T,Arg> help(Arg&& arg)
{
return helper<T,Arg>{std::forward<Arg>(arg)};
}


int main()
{
auto lambda = [](const foo& f){};

std::thread t{lambda, help<foo>(13)};
t.join();

return 0;
}

我在这个解决方案中遇到的问题是,所有 foo 的构造函数参数都通过 helper 对象复制到线程可访问的存储中。我只想在 foo 对象上花费存储空间。

假设我不能修改 lambda,也不能修改 std::thread,是否有一些技巧会导致 decay_copy 函数返回一个新构造的 foo 当给定一个 helper 作为参数时?

最佳答案

我不确定您所说的“线程可访问存储”是什么意思,因为一个进程中的所有线程通常共享它们的所有内存。

也许你引用了堆栈,但你可能会传递 foo对象完全构建(在主线程中)。 foo对象将存在于线程堆栈中:

foo f{13};
std::thread t{lambda, f};

一个奇特的选择是使用 std::future :

#include <future>
template<class T>
struct helper
{
operator T ()
{
return future.get();
}
std::future<T> future;
};
template<class T>
helper<T> help(std::future<T> &&p)
{
return helper<T>{std::forward<std::future<T>>(p)};
}

然后它可以与 std::promise 一起使用:

std::promise<foo> p;
//you can set the value before or after the thread
std::thread t{lambda, help(p.get_future())};
//either way, std::future::get() is a synchronization point
p.set_value(13);
t.join();

或使用 std::packaged_task和创建 foo 的 labmda .但在这种特殊情况下,lambda 将在线程中执行,因此我猜这与您的原始代码之间没有实际区别。

更新:根据您的评论,我认为您可以通过简单的 std::promise<void> 使用您的助手类。用于同步:

template<class T>
struct helper
{
operator T ()
{
foo f{x};
promise.set_value(); // x is no longer needed
return f;
}

std::promise<void> promise;
int &x;
};


template<class T>
helper<T> help(std::promise<void> &&p, int &x)
{
return helper<T>{std::forward<std::promise<void>>(p), x};
}

int main()
{
auto lambda = [](const foo &&f){ };

std::promise<void> prom_done;
std::future<void> done = prom_done.get_future();

int x = 42;
std::thread t{lambda, help<foo>(std::move(prom_done), x)};

future.get(); //wait until the `foo` is fully created.

t.join();
}

关于c++ - 如何让 std::thread 对传递给它的函数的参数进行一般构造?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28119126/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com