Reputation: 7357
Im searching for something similar to thread-local variables, but for boost::corotine (actually i use boost:asio::spawn). Consider following code:
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);
}
I want to set this the_magic_request_id
to some value when request is initialized, which will serve like "current request id".
Without this, i must pass the_magic_request_id
to every function and every module which do logging in project. some_function
is just an example, actually i have many classes, they do different work, but all of them require yield_context
and the_magic_request_id
in order to create an instance. I want to simplify interfaces for these classes.
Probably its possible to set "on_sleep" and "on_resume" hooks, which will set a global variable? Or boost::coroutine already have some ready-to-user mechanics for this? Did not found something usable in the docs.
Upvotes: 2
Views: 1305
Reputation: 400
Instead of using boost.coroutine (boost::asio::yield_context) you could use boost.fiber (user-land threads,boost::fibers::asio::yield_context). boost.fiber supports fiber_specific_ptr (eq. to boost.thread's thread_specific_ptr).
documentation: http://olk.github.io/libs/fiber/doc/html/index.html
Upvotes: 3
Reputation: 393769
You can use a bound function object to contain the state.
In fact that bound function object can be elegantly expressed as lambda with captures. Make sure that captures are by value (so you don't accidentally share the state with other instances) and if not, the objects they refer to live long enough.
E.g.
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";
}
}
Alternatively:
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);
}
}
Or transformed into lambda form:
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);
}
}
Upvotes: 0