On Mon, Sep 19, 2016 at 11:21 AM, Michael Steinberg
wrote:
Hello,
is there some way to temporarily run a function on the main stack? I
played around a bit, but failed ultimately since the first stub function to
be called is getting a "null" context which I assume to be only a valid
"return-context".
We're facing a problem where a dialog run modally inside a context runs
webkit, which triggers garbage collection, which fails miserably since it
assumes we're on the "native" stack. If it were possible to run something
"on-top" of the main stack, this could maybe be circumvented.
Thank you,
Michael
_______________________________________________
Boost-users mailing list
Boost-users@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users
I have a similar problem I solved by providing a mechanism for storing the
"root" context. Storing this is a bit tricky, since the context you're
jumping to is responsible for performing your action (assuming you're using
Context v2). My own fiber implementation provides the ability to jump to
yield, wait and jump to root. Hopefully this is helpful for you.
struct destination_action
{
enum class goal { root, ready, wait };
goal request;
void* addr = nullptr;
};
using context = boost::context::execution_context;
All context jumps go through a simple helper method (functions leading into
this are simply creating a destination_action instance with what the caller
wants to do).
void service::jump_to(context cxt, destination_action request) noexcept
{
std::tie(cxt, request) = cxt(request);
save_caller(std::move(cxt), request);
}
The save_caller function is pretty simple. You probably only care about
when request is goal::root, but I'll drop the whole thing for completeness.
void service::save_caller(context&& cxt, destination_action request)
noexcept
{
* // The stack terminated, so don't bother saving it. if
(!cxt) return;*
switch (request.request)
{
case destination_action::goal::ready:
_scheduler.ready(std::move(cxt));
break;
case destination_action::goal::wait:
_scheduler.wait(request.addr, std::move(cxt));
break;
* case destination_action::goal::root: ASSERT(!_root_context) <<
"Already have a root runner"; _root_context = std::move(cxt);
break;*
default:
ASSERT(false) << "Corruption? " << request.request;
}
}
Ultimately, I provide a run function which is meant to be called by the
root context.
void service::run()
{
if (_in_run)
throw invalid_state("This service is already running.");
_in_run = true;
SCOPE_EXIT { _in_run = false; };
while (_running)
{
if (auto next = pop_next_routine())
{
destination_action action;
action.request = destination_action::goal::root;
jump_to(std::move(next), action);
}
else
{
// No routine to run...must be a root request
auto fn = _root_requests.pop();
std::move(fn)();
}
}
}
Hope this helps!
--
Travis Göckel