假设我有这个功能double someRandomFunction(int n)
它接受一个整数并返回双精度值,但它是随机的,因为它会尝试随机的东西来得出解决方案,因此即使您使用相同的参数运行该函数,有时也可能需要 10 秒才能完成,其他则需要 40 秒才能完成。
The double someRandomFunction(int n)
函数本身是黑盒函数的包装器。所以someRandomFunction
需要一段时间才能完成,但我无法控制黑盒的主循环,因此我无法真正检查线程内的标志变量,因为大量计算发生在黑盒函数中。
我想启动 10 个线程来调用该函数,并且我对首先完成的第一个线程的结果感兴趣。我不在乎是哪一个,我只需要这些线程的 1 个结果。
我找到了以下代码:
std::vector<boost::future<double>> futures;
for (...) {
auto fut = boost::async([i]() { return someRandomFunction(2) });
futures.push_back(std::move(fut));
}
for (...) {
auto res = boost::wait_for_any(futures.begin(), futures.end());
std::this_thread::yield();
std::cout << res->get() << std::endl;
}
这是最接近我正在寻找的内容,但我仍然看不到如何让我的程序在一个线程返回解决方案的情况下终止其他线程。
我想等待一个线程完成,然后继续使用该线程的结果来继续执行我的程序(即,我不想在获得单个结果后终止我的程序,但我想使用它用于剩余的程序执行。)。
再次,我想启动 10 个线程来调用someRandomFunction
然后等待一个线程先完成,获取该线程的结果并停止所有其他线程,即使它们没有完成工作。
如果提供给黑盒的数据结构具有一些明显的开始值和结束值,则使其提前完成的一种方法可能是在计算时更改最终值。如果您误解了黑匣子是如何工作的,那么它当然可能会导致各种麻烦must处理数据,但如果你相当确定,它是可行的。
main 生成 100 个外线程,每个外线程生成一个调用黑盒的内线程。内部线程接收黑盒结果并通知所有等待线程它已完成。外线程等待any内部线程完成,然后修改其自己的黑匣子的数据以欺骗其完成。
没有轮询(除了虚假的唤醒循环),也没有分离的线程。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <chrono>
// a work package for one black-box
struct data_for_back_box {
int start_here;
int end_here;
};
double blackbox(data_for_back_box* data) {
// time consuming work here:
for(auto v=data->start_here; v<data->end_here; ++v) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
// just a debug
if(data->end_here==0) std::cout << "I was tricked into exiting early\n";
return data->end_here;
}
// synchronizing stuff and result
std::condition_variable cv;
std::mutex mtx;
bool done=false;
double result;
// a wrapper around the real blackbox
void inner(data_for_back_box* data) {
double r = blackbox(data);
if(done) return; // someone has already finished, skip this result
// notify everyone that we're done
std::unique_lock<std::mutex> lock(mtx);
result = r;
done=true;
cv.notify_all();
}
// context setup and wait for any inner wrapper
// to signal "done"
void outer(int n) {
data_for_back_box data{0, 100+n*n};
std::thread work(inner, &data);
{
std::unique_lock<std::mutex> lock(mtx);
while( !done ) cv.wait(lock);
}
// corrupt data for blackbox:
data.end_here = 0;
// wait for this threads blackbox to finish
work.join();
}
int main() {
std::vector<std::thread> ths;
// spawn 100 worker threads
for(int i=0; i<100; ++i) {
ths.emplace_back(outer, i);
}
double saved_result;
{
std::unique_lock<std::mutex> lock(mtx);
while( !done ) cv.wait(lock);
saved_result = result;
} // release lock
// join all threads
std::cout << "got result, joining:\n";
for(auto& th : ths) {
th.join();
}
std::cout << "result: " << saved_result << "\n";
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)