将来尝试引用已删除的函数
Attempting to Reference a Deleted Function in Future
我正在编写一个程序,它将异步查找大量质数。我通过使用 TaskQueue
来实现,它本质上是一个 queue ,由所有异步执行的期货组成。涉及三个线程:将这些任务分配给 TaskQueue
的厨师线程,检查期货是否有答案并决定是否存储数据的客户线程,以及启动的主线程并检查其他两个的状态。我在第 593 行收到错误:Error 2 error C2280: 'std::future<return_type>::future(const std::future<return_type> &)' : attempting to reference a deleted function e:\visualstudio\vc\include\xmemory0 593 1 MultiThreadTaskQueue
引用文件 xmemory0,它似乎是我 #include
d 的另一个 headers 引用的文件。我的问题似乎是未来 object 的复制构造函数的问题,可能是在复制之前被删除的复制构造函数,但我不确定在我的程序中会发生什么。这是我的代码的副本:
#include <iostream>
#include <queue>
#include <future>
#include <thread>
#include <vector>
#include <mutex>
using namespace std;
using longInt = long long unsigned int;
template <typename return_type>
class TaskQueue {
private:
queue<future<return_type>> tasks;
mutex mtx;
public:
//return a copy of the queue
queue<future<return_type>> copy() const {
return tasks;
}
//default constructor
//does nothing, waits for input
TaskQueue() {
//do nothing
}
//call constructors
//adds task to queue
template <typename ... Args, typename ... Ts>
TaskQueue(return_type(*func)(Ts...), Args&& ... args) {
tasks.push(std::async(func, args...));
}
//copy constructor
//copies another queue to this one
TaskQueue(const TaskQueue<longInt> & in) {
tasks = in.copy();
}
//setter and getter functions
//inserts a new task into the queue
template <typename ... Args, typename ... Ts>
void add(return_type(*func)(Ts...), Args&& ... args) {
tasks.push(std::async(func, args...));
}
//returns true if the task at the top of the queue is ready
bool valid() {
return tasks.front().valid();
}
//gets the value, if the value is not ready, waits for it to be ready
//pops the top task after getting it
return_type get() {
//mtx.lock();
return_type temp = tasks.front().get();
tasks.pop();
//mtx.unlock();
return temp;
}
//waits for the value of the top of the queue to become ready
void wait() {
tasks.front().wait();
}
//returns the number of tasks in the queue
int size() const {
return tasks.size();
}
};
bool HALT_ALL = false;
int MAX_TASKS_AT_ONCE = 10;
//prototypes
longInt isPrime(longInt);
void cook(TaskQueue<longInt>&);
void consumer(TaskQueue<longInt>&, vector<longInt> &);
int main() {
//declare task queue and vector to store prime numbers
TaskQueue<longInt> checkPrimes;
vector<longInt> primes;
primes.push_back(2);
int maxPrimes;
cout << "Enter max primes: ";
cin >> maxPrimes;
cout << endl;
//launch the chef thread and the customer thread
thread chef(&cook, checkPrimes);
thread customer(&consumer, checkPrimes, primes);
int previousSize = 0;
//use main to keep track of the progress of the other threads
while (primes.size() < maxPrimes) {
if (previousSize != primes.size()) {
cout << "Primes found: " << primes.size() << endl;
previousSize = primes.size();
}
else {
checkPrimes.wait();
}
}
//halt all other asynchronous operations
HALT_ALL = true;
//join other threads
chef.join();
customer.join();
//print final prime found for verification of data
cout << "Final Prime found: " << primes[primes.size() - 1] << endl;
system("PAUSE");
return 0;
}
//returns the number if it is prime or 0 if it is not
longInt isPrime(longInt n) {
if (n <= 3) {
if (n > 1) {
return n;
}
return 0;
}
if (n % 2 == 0 || n % 3 == 0) {
return 0;
}
for (unsigned short i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return 0;
}
}
return n;
}
void cook(TaskQueue<longInt>& tasks) {
longInt currentPrime = 3;
while (!HALT_ALL) {
if (tasks.size() < MAX_TASKS_AT_ONCE) {
tasks.add(isPrime, currentPrime);
currentPrime += 2;
}
}
}
void consumer(TaskQueue<longInt>& tasks, vector<longInt> & primes) {
while (!HALT_ALL) {
if (tasks.size() > 0) {
longInt temp = tasks.get();
if (temp > 0) {
primes.push_back(temp);
}
}
}
}
您正试图在此处复制 std::future
:
queue<future<return_type>> copy() const {
return tasks;
}
但是 std::future
是 non-copyable,它的复制构造函数被删除(参见示例 here),所以您会收到编译器错误消息。
删除 copy()
函数和 TaskQueue
复制构造函数。
其实你的错误就在这里:
thread chef(&cook, checkPrimes);
thread customer(&consumer, checkPrimes, primes);
如果参数是右值,std::thread
构造函数移动它的参数,否则复制它们。所以只需传递 reference_wrapper
s 即可:
thread chef(&cook, std::ref(checkPrimes));
thread customer(&consumer, std::ref(checkPrimes), std::ref(primes));
它不仅可以编译您的代码,还可以使代码在语义上更正确,因为您可能不希望每个线程都有自己的任务队列和素数向量。
请注意,您必须进行适当的同步以避免数据竞争。
我正在编写一个程序,它将异步查找大量质数。我通过使用 TaskQueue
来实现,它本质上是一个 queue ,由所有异步执行的期货组成。涉及三个线程:将这些任务分配给 TaskQueue
的厨师线程,检查期货是否有答案并决定是否存储数据的客户线程,以及启动的主线程并检查其他两个的状态。我在第 593 行收到错误:Error 2 error C2280: 'std::future<return_type>::future(const std::future<return_type> &)' : attempting to reference a deleted function e:\visualstudio\vc\include\xmemory0 593 1 MultiThreadTaskQueue
引用文件 xmemory0,它似乎是我 #include
d 的另一个 headers 引用的文件。我的问题似乎是未来 object 的复制构造函数的问题,可能是在复制之前被删除的复制构造函数,但我不确定在我的程序中会发生什么。这是我的代码的副本:
#include <iostream>
#include <queue>
#include <future>
#include <thread>
#include <vector>
#include <mutex>
using namespace std;
using longInt = long long unsigned int;
template <typename return_type>
class TaskQueue {
private:
queue<future<return_type>> tasks;
mutex mtx;
public:
//return a copy of the queue
queue<future<return_type>> copy() const {
return tasks;
}
//default constructor
//does nothing, waits for input
TaskQueue() {
//do nothing
}
//call constructors
//adds task to queue
template <typename ... Args, typename ... Ts>
TaskQueue(return_type(*func)(Ts...), Args&& ... args) {
tasks.push(std::async(func, args...));
}
//copy constructor
//copies another queue to this one
TaskQueue(const TaskQueue<longInt> & in) {
tasks = in.copy();
}
//setter and getter functions
//inserts a new task into the queue
template <typename ... Args, typename ... Ts>
void add(return_type(*func)(Ts...), Args&& ... args) {
tasks.push(std::async(func, args...));
}
//returns true if the task at the top of the queue is ready
bool valid() {
return tasks.front().valid();
}
//gets the value, if the value is not ready, waits for it to be ready
//pops the top task after getting it
return_type get() {
//mtx.lock();
return_type temp = tasks.front().get();
tasks.pop();
//mtx.unlock();
return temp;
}
//waits for the value of the top of the queue to become ready
void wait() {
tasks.front().wait();
}
//returns the number of tasks in the queue
int size() const {
return tasks.size();
}
};
bool HALT_ALL = false;
int MAX_TASKS_AT_ONCE = 10;
//prototypes
longInt isPrime(longInt);
void cook(TaskQueue<longInt>&);
void consumer(TaskQueue<longInt>&, vector<longInt> &);
int main() {
//declare task queue and vector to store prime numbers
TaskQueue<longInt> checkPrimes;
vector<longInt> primes;
primes.push_back(2);
int maxPrimes;
cout << "Enter max primes: ";
cin >> maxPrimes;
cout << endl;
//launch the chef thread and the customer thread
thread chef(&cook, checkPrimes);
thread customer(&consumer, checkPrimes, primes);
int previousSize = 0;
//use main to keep track of the progress of the other threads
while (primes.size() < maxPrimes) {
if (previousSize != primes.size()) {
cout << "Primes found: " << primes.size() << endl;
previousSize = primes.size();
}
else {
checkPrimes.wait();
}
}
//halt all other asynchronous operations
HALT_ALL = true;
//join other threads
chef.join();
customer.join();
//print final prime found for verification of data
cout << "Final Prime found: " << primes[primes.size() - 1] << endl;
system("PAUSE");
return 0;
}
//returns the number if it is prime or 0 if it is not
longInt isPrime(longInt n) {
if (n <= 3) {
if (n > 1) {
return n;
}
return 0;
}
if (n % 2 == 0 || n % 3 == 0) {
return 0;
}
for (unsigned short i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return 0;
}
}
return n;
}
void cook(TaskQueue<longInt>& tasks) {
longInt currentPrime = 3;
while (!HALT_ALL) {
if (tasks.size() < MAX_TASKS_AT_ONCE) {
tasks.add(isPrime, currentPrime);
currentPrime += 2;
}
}
}
void consumer(TaskQueue<longInt>& tasks, vector<longInt> & primes) {
while (!HALT_ALL) {
if (tasks.size() > 0) {
longInt temp = tasks.get();
if (temp > 0) {
primes.push_back(temp);
}
}
}
}
您正试图在此处复制 std::future
:
queue<future<return_type>> copy() const {
return tasks;
}
但是 std::future
是 non-copyable,它的复制构造函数被删除(参见示例 here),所以您会收到编译器错误消息。
删除 copy()
函数和 TaskQueue
复制构造函数。
其实你的错误就在这里:
thread chef(&cook, checkPrimes);
thread customer(&consumer, checkPrimes, primes);
如果参数是右值,std::thread
构造函数移动它的参数,否则复制它们。所以只需传递 reference_wrapper
s 即可:
thread chef(&cook, std::ref(checkPrimes));
thread customer(&consumer, std::ref(checkPrimes), std::ref(primes));
它不仅可以编译您的代码,还可以使代码在语义上更正确,因为您可能不希望每个线程都有自己的任务队列和素数向量。
请注意,您必须进行适当的同步以避免数据竞争。