我有一个简单的任务调度程序:调用执行方法,packaged_task
返回指向我Task
的指针。当一个任务完成后我就会#1;喜欢显示调试数据(涉及到GUI,所以我需要在主线程中执行此操作)。我希望像boost::wait_for_any
一样使用j->get()
,但boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::promise_already_satisfied> >
有时会抛出异常get
。这留下了两个想法。要么是因为复制而是异常类所指出的,但是我不知道这发生了什么,或者由于wait_for_any
已经被调用,这是不可能发生的,因为期货只能在这个方法块我已经将它们转换为shared_futrues所以它应该可以工作。
那么在Task
部分中,我如何找回指向已完成的future
实例的指针?
使用shared_future
而不是execute
编辑。
事实证明,我的一个任务的get
函数抛出了异常,而期货会将这些异常带到std::vector<boost::future<Task*>> futures;
std::vector<Task*> tasks = get_tasks();
for (Task* t : tasks) {
typedef boost::packaged_task<Task*()> task_t;
task_t task([t]() -> Task* {
t->execute();
return t;
});
auto fut = task.get_future();
futures.push_back(std::move(fut));
impl->io_service.post(boost::bind(&task_t::operator(), boost::make_shared<task_t>(std::move(task))));
}
for (Task* t : tasks) {
auto j = boost::wait_for_any(futures.begin(), futures.end());
Task* task = j->get();
task->display_debug();
futures.erase(j);
}
调用。代码本身很好(除了缺少的异常处理程序)。但是,使用Boost信号(见下面的答案)可能是更好的方法。
{{1}}
答案 0 :(得分:2)
嗯。我实际上在这里失去了一点。看起来你做的事情比要求的要复杂得多(为什么你不使用Boost Signals2而不是&#34;轮询&#34;对于特定的&#34;事件&#34;通过期货?看来你是无论如何不要以任何特定的顺序期待它们?)。
对于它的价值,这里有一个适用于我的固定版本。如果我以后有更多时间,我可以比较一下注释,看看解释差异的原因。
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/make_shared.hpp>
#include <boost/thread/future.hpp>
#include <iostream>
#include <string>
#include <set>
struct Task
{
virtual ~Task() = default;
virtual void execute() {}
virtual void display_debug() { std::cout << __FUNCTION__ << static_cast<void*>(this) << "\n"; }
};
std::set<Task*> get_tasks()
{
static std::set<Task*> data{ new Task, new Task };
return data;
}
int main() {
struct { boost::asio::io_service io_service; } impl_instance;
auto impl = &impl_instance;
std::vector<boost::shared_future<Task*>> futures;
std::set<Task*> tasks = get_tasks();
for (Task* t : tasks) {
typedef boost::packaged_task<Task*> task_t;
task_t wrap([t]() -> Task* {
t->execute();
return t;
});
auto fut = wrap.get_future();
futures.push_back(std::move(fut));
impl->io_service.post(boost::bind(&task_t::operator(), boost::make_shared<task_t>(std::move(wrap))));
}
boost::thread th([&]{ impl->io_service.run(); });
while (!futures.empty()) {
auto j = boost::wait_for_any(futures.begin(), futures.end());
auto fut = *j;
futures.erase(j);
Task* task = fut.get();
task->display_debug();
// optionally:
// tasks.erase(task);
}
th.join();
}