Я использую boost::context::execution_context
(версия 2), чтобы написать библиотеку C ++ 11, и я хочу распространить исключения из execution_context
на вызывающее выполнение.
Я бы хотел обработать исключения внутри лямбды, которые клиент передает моей библиотечной функции; Тем не менее, я столкнулся со странной проблемой, когда исключение неправильно обрабатывается boost :: context в некоторых случаях.
Это работает как ожидалось и очень похоже на некоторые из тестов boost и примеров :
TEST(execution_context, works) {
// Client callable
auto &&f = [](boost::context::execution_context<void> &&ctx) {
throw std::runtime_error("help!");
return std::move(ctx);
};
// Library code
std::exception_ptr exc{};
boost::context::execution_context<void> source(
[&exc, &f](boost::context::execution_context<void> &&ctx) {
try {
ctx = f(std::move(ctx));
} catch (boost::context::detail::forced_unwind const &) {
throw;
} catch (...) {
exc = std::current_exception();
}
return std::move(ctx);
});
try {
source = source();
if (exc) {
std::rethrow_exception(exc);
}
} catch (std::runtime_error const &) {
std::cout << "Runtime Error Caught" << std::endl;
}
}
Выход:
[ RUN ] execution_context.works
Runtime Error Caught
[ OK ] execution_context.works (0 ms)
Но следующее изменение не работает:
Мы добавляем класс, который переносит execution_context
:
class Core {
boost::context::execution_context<void> ctx_;
public:
explicit Core(boost::context::execution_context<void> &&ctx)
: ctx_{std::move(ctx)} {}
auto &&done() { return std::move(ctx_); }
};
Теперь мы делаем тот же тест, что и раньше, но используя определенный класс:
TEST(execution_context, fails) {
// Client callable
auto &&f = [](Core c) {
throw std::runtime_error("help!");
return c.done();
};
// Library code
std::exception_ptr exc{};
boost::context::execution_context<void> source(
[&exc, &f](boost::context::execution_context<void> &&ctx) {
try {
ctx = f(Core(std::move(ctx)));
} catch (boost::context::detail::forced_unwind const &) {
throw;
} catch (...) {
exc = std::current_exception();
}
return std::move(ctx);
});
try {
source = source();
if (exc) {
std::rethrow_exception(exc);
}
} catch (std::runtime_error const &) {
std::cout << "Runtime Error Caught" << std::endl;
}
}
Выход:
[ RUN ] execution_context.fails
unknown file: Failure
Unknown C++ exception thrown in the test body.
generators.t.tsk: /home/plewis/dpkg/refroot/amd64/opt/include/boost/context/detail/exception.hpp:37: boost::context::detail::forced_unwind::~forced_unwind(): Assertion `caught' failed.
zsh: abort (core dumped) ./test.t.tsk
Единственное отличие, которое я заметил, состоит в том, что execution_context
содержится в классе, и это приводит к неправильной обработке исключения. Это не имеет смысла.
Окружающая среда
Я использую GTest.
Компилятор
> g++ --version
g++ (GCC) 5.3.1 20160406 (Red Hat 5.3.1-6)
...
System
> uname -a
Linux myhostname 2.6.32-642.6.2.el6.x86_64 #1 SMP Mon Oct 24 10:22:33 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux
Повышение
boost version 1.69.0 compiled for amd64