Я ищу что-то похожее на локальные переменные потока, но для boost :: corotine (на самом деле я использую boost: asio :: spawn). Рассмотрим следующий код:
void coroutine_work(boost::asio::yield_context yield) {
async_foo( yield );
some_function();
}
void some_function() {
fprintf(log_fd, "%s Some function called", the_magic_request_id);
}
Я хочу установить это the_magic_request_id
к некоторому значению при инициализации запроса, который будет служить как «текущий идентификатор запроса».
Без этого я должен пройти the_magic_request_id
для каждой функции и каждого модуля, которые делают вход в проект. some_function
это просто пример, на самом деле у меня много классов, они выполняют разную работу, но все они требуют yield_context
а также the_magic_request_id
для того, чтобы создать экземпляр. Я хочу упростить интерфейсы для этих классов.
Возможно, возможно установить хуки on_sleep и on_resume, которые установят глобальную переменную? Или у Boost :: Coroutine уже есть готовые механизмы для этого? Не нашел что-то полезное в документах.
Вместо использования boost.coroutine (boost :: asio :: yield_context) вы можете использовать boost.fiber (пользовательские потоки, boost :: fiber :: asio :: yield_context). boost.fiber поддерживает fiber_specific_ptr (например, для boost.thread’s thread_specific_ptr).
документация: http://olk.github.io/libs/fiber/doc/html/index.html
Вы можете использовать связанный объект функции для хранения состояния.
Фактически, объект связанной функции может быть элегантно выражен как лямбда с захватами. Убедитесь, что захваты по значению (чтобы вы случайно не делили состояние с другими экземплярами) и, если нет, объекты, на которые они ссылаются, живут достаточно долго.
Например.
extern std::ostream& log_stream; // for exposition only
struct coroutine_work {
boost::uuids::uuid the_magic_request_id = boost::uuids::random_generator{}();
void operator()(boost::asio::yield_context yield) {
async_foo(yield);
some_function();
}
void some_function() const {
log_stream << the_magic_request_id << " Some function called\n";
}
}
В качестве альтернативы:
static void some_function(boost::uuids::uuid const& reqid) const {
log_stream << reqid << " Some function called\n";
}
struct coroutine_work {
boost::uuids::uuid the_magic_request_id = boost::uuids::random_generator{}();
void operator()(boost::asio::yield_context yield) {
async_foo(yield);
some_function(the_magic_request_id);
}
}
Или превращается в лямбда-форму:
static void some_function(boost::uuids::uuid const& reqid) const {
log_stream << reqid << " Some function called\n";
}
// somewhere else:
{
boost::uuids::uuid the_magic_request_id = boost::uuids::random_generator{}();
auto coroutine_work = [the_magic_request_id](boost::asio::yield_context yield) {
async_foo(yield);
some_function(the_magic_request_id);
}
}