覆盖向量的第一个元素会更改向量最后一个元素的内容
Overwriting first element of a vector changes contents of last element of vector
在编写我的代码时,我注意到 运行 代码 returns 不正确的结果,事实证明我的代码中的某些东西正在改变我的协同程序的句柄向量并将其缩小到一个我用新元素覆盖句柄向量的现有元素的代码行。
这样做还会更改向量最后一个元素的内容(更具体地说,是来自 myTask header 的布尔值),但不会更改其间的元素。
有谁知道这是什么原因造成的?任何帮助表示赞赏。
完整的实现代码:
#include <concepts>
#include <coroutine>
#include <exception>
#include <iostream>
#include <myTask.h>
#include <vector>
myTask<int> getVectorInt(std::vector<int>& array, int key, bool interleave)
{
std::cout << "started lookup of key: " << key << std::endl;
int result = array.at(key);
if (interleave == true)
{
std::cout << "about to suspend task with key: " << key << std::endl;
co_await std::suspend_always{};
std::cout << "resumed task with key: " << key << std::endl;
}
co_return result;
}
void interleavedExecution(std::vector<int>& lookup, std::vector<int>& keys, std::vector<int>& results)
{
// group size = number of concurrent instruction streams
int groupsize = 3;
// initialization of handle vector
std::vector<std::coroutine_handle<myTask<int>::promise_type>> handles;
// initialization of promise vector
std::vector<myTask<int>::promise_type> promises;
// creating/initializing first handles
for (int i = 0; i < groupsize; ++i)
{
handles.push_back(getVectorInt(lookup, keys.at(i), true));
}
int notDone = groupsize;
int i = groupsize;
// interleaved execution starts here
while (notDone > 0)
{
for (int handleIndex = 0; handleIndex < handles.size(); ++handleIndex)
{
if (!handles.at(handleIndex).promise().isDone())
{
handles.at(handleIndex).resume();
handles.at(handleIndex).promise().boolIsDone = true;
}
else
{
// pushing value back directly into results
results.push_back(handles.at(handleIndex).promise().value_);
if (i < keys.size())
{
// bug here, changes the last boolIsDone also to false (or messes with the last vector element)
handles.at(handleIndex) = getVectorInt(lookup, keys.at(i), true);
handles.at(handleIndex).promise().boolIsDone = false;
++i;
}
else { --notDone; }
}
}
}
}
template <typename T>
void outputVector(std::vector<T> toOutput)
{
std::cout << "Results: ";
for (int i = 0; i < toOutput.size(); ++i)
{
std::cout << toOutput.at(i) << ' ';
}
}
int main()
{
std::vector<int> lookup = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
std::vector<int> keys = {4, 2, 0, 6, 9, 0};
std::vector<int> results;
// correct output: 50, 30, 10, 70, 100, 10
// given output: 50, 30, 70, 10, 100, 10
interleavedExecution(lookup, keys, results);
outputVector(results);
}
myTask header 携带一个布尔值:
#include <concepts>
#include <coroutine>
#include <exception>
#include <iostream>
template <typename T>
struct myTask {
struct promise_type {
unsigned value_;
~promise_type() {
//std::cout << "promise_type destroyed" << std::endl;
}
myTask<T> get_return_object() {
return myTask<T> {
.h_ = std::coroutine_handle<promise_type>::from_promise(*this)
};
}
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() { return {}; }
void unhandled_exception() { std::terminate(); }
std::suspend_always return_value(unsigned value) {
value_ = value;
return {};
}
bool boolIsDone = false;
auto isDone() { return boolIsDone; }
};
std::coroutine_handle<promise_type> h_;
operator std::coroutine_handle<promise_type>() const {
//std::cout << "called handle" << std::endl;
return h_; }
};
事实证明,将 final_suspend()
的 return 类型从 std::suspend_never
更改为 std::suspend_always
可以解决问题。
在编写我的代码时,我注意到 运行 代码 returns 不正确的结果,事实证明我的代码中的某些东西正在改变我的协同程序的句柄向量并将其缩小到一个我用新元素覆盖句柄向量的现有元素的代码行。
这样做还会更改向量最后一个元素的内容(更具体地说,是来自 myTask header 的布尔值),但不会更改其间的元素。
有谁知道这是什么原因造成的?任何帮助表示赞赏。
完整的实现代码:
#include <concepts>
#include <coroutine>
#include <exception>
#include <iostream>
#include <myTask.h>
#include <vector>
myTask<int> getVectorInt(std::vector<int>& array, int key, bool interleave)
{
std::cout << "started lookup of key: " << key << std::endl;
int result = array.at(key);
if (interleave == true)
{
std::cout << "about to suspend task with key: " << key << std::endl;
co_await std::suspend_always{};
std::cout << "resumed task with key: " << key << std::endl;
}
co_return result;
}
void interleavedExecution(std::vector<int>& lookup, std::vector<int>& keys, std::vector<int>& results)
{
// group size = number of concurrent instruction streams
int groupsize = 3;
// initialization of handle vector
std::vector<std::coroutine_handle<myTask<int>::promise_type>> handles;
// initialization of promise vector
std::vector<myTask<int>::promise_type> promises;
// creating/initializing first handles
for (int i = 0; i < groupsize; ++i)
{
handles.push_back(getVectorInt(lookup, keys.at(i), true));
}
int notDone = groupsize;
int i = groupsize;
// interleaved execution starts here
while (notDone > 0)
{
for (int handleIndex = 0; handleIndex < handles.size(); ++handleIndex)
{
if (!handles.at(handleIndex).promise().isDone())
{
handles.at(handleIndex).resume();
handles.at(handleIndex).promise().boolIsDone = true;
}
else
{
// pushing value back directly into results
results.push_back(handles.at(handleIndex).promise().value_);
if (i < keys.size())
{
// bug here, changes the last boolIsDone also to false (or messes with the last vector element)
handles.at(handleIndex) = getVectorInt(lookup, keys.at(i), true);
handles.at(handleIndex).promise().boolIsDone = false;
++i;
}
else { --notDone; }
}
}
}
}
template <typename T>
void outputVector(std::vector<T> toOutput)
{
std::cout << "Results: ";
for (int i = 0; i < toOutput.size(); ++i)
{
std::cout << toOutput.at(i) << ' ';
}
}
int main()
{
std::vector<int> lookup = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
std::vector<int> keys = {4, 2, 0, 6, 9, 0};
std::vector<int> results;
// correct output: 50, 30, 10, 70, 100, 10
// given output: 50, 30, 70, 10, 100, 10
interleavedExecution(lookup, keys, results);
outputVector(results);
}
myTask header 携带一个布尔值:
#include <concepts>
#include <coroutine>
#include <exception>
#include <iostream>
template <typename T>
struct myTask {
struct promise_type {
unsigned value_;
~promise_type() {
//std::cout << "promise_type destroyed" << std::endl;
}
myTask<T> get_return_object() {
return myTask<T> {
.h_ = std::coroutine_handle<promise_type>::from_promise(*this)
};
}
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() { return {}; }
void unhandled_exception() { std::terminate(); }
std::suspend_always return_value(unsigned value) {
value_ = value;
return {};
}
bool boolIsDone = false;
auto isDone() { return boolIsDone; }
};
std::coroutine_handle<promise_type> h_;
operator std::coroutine_handle<promise_type>() const {
//std::cout << "called handle" << std::endl;
return h_; }
};
事实证明,将 final_suspend()
的 return 类型从 std::suspend_never
更改为 std::suspend_always
可以解决问题。