Coroutine-локальная переменная в boost

Я ищу что-то похожее на локальные переменные потока, но для 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 уже есть готовые механизмы для этого? Не нашел что-то полезное в документах.

1

Решение

Вместо использования 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

3

Другие решения

Вы можете использовать связанный объект функции для хранения состояния.

Фактически, объект связанной функции может быть элегантно выражен как лямбда с захватами. Убедитесь, что захваты по значению (чтобы вы случайно не делили состояние с другими экземплярами) и, если нет, объекты, на которые они ссылаются, живут достаточно долго.

Например.

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);
}
}
1

По вопросам рекламы [email protected]