Я пытаюсь добавить некоторые асинхронные операции глубоко в существующую кодовую базу, которая вызывается внутри веб-сервера, реализованного с использованием pion (который сам использует boost :: asio).
Текущий код должен продолжать работать в контекстах, где нет доступного io_service, поэтому я сделал следующее, где Foo :: bar является главной точкой входа существующей кодовой базы, а handleRequest является обработчиком запросов pion:
class Foo
{
public:
void bar(std::string input, boost::asio::io_service* io = NULL)
{
ioService = io;
if ( io == NULL )
{
barCommon(input);
}
else
{
boost::asio::spawn(*io, boost::bind(&Foo::barAsync, this, input, _1));
}
}
void barAsync(std::string input, boost::asio::yield_context yc)
{
barCommon(input, &yc);
}
void barCommon(std::string input, boost::asio::yield_context* yieldContext = NULL)
{
// Existing code here, with some operations performed async
// using ioService and yieldContext if they are not NULL.
}
private:
boost::asio::io_service* ioService;
// Other member variables, which cause a crash when accessed
}
void handleRequest(pion::http::request_ptr request, pion::tcp::connection_ptr connection)
{
Foo* foo = acquireFooPointer();
foo->bar(std::string(request->get_content()), &connection->get_io_service());
}
Похоже, это работает, поскольку в результате запуска Foo :: barCommon внутри сопрограммы, но существующий код падает, как только он пытается получить доступ к переменным-членам Foo. Что мне здесь не хватает?
РЕДАКТИРОВАТЬ: Просто для ясности, указатель, полученный в handleRequest, относится к выделенному в куче объекту Foo, время жизни которого совпадает со временем серверного процесса.
Задача ещё не решена.
Других решений пока нет …