如何在 Boehm GC 中使用 Boost.Coroutine?
How to use Boost.Coroutine with Boehm GC?
Boost.Coroutine 分配自己的调用堆栈。 Boehm GC 是否将这些堆栈上的指针视为根,如果不是,我如何才能做到这一点?在上下文切换到协程后,Boehm 终止程序。
大概 Boost.Coroutine 中的代码保存了一个指向它分配的调用堆栈的指针,并将其存储在 "usual" 存储指针的地方之一(例如,一些指针变量)。
如果是这样,那么是的,GC 将 "chase" 指针从存储它的变量到调用堆栈,并从那里(递归地)通过它包含的任何指针。
目前 boost 不提供挂钩到分段堆栈分配的方法,因此这是固定大小堆栈的解决方案。
#include <gc/gc.h>
#include <gc/gc_cpp.h>
#include <boost/coroutine2/coroutine.hpp>
#include <boost/coroutine2/protected_fixedsize_stack.hpp>
#include <boost/context/stack_context.hpp>
class BoehmGCStackAllocator {
boost::coroutines2::protected_fixedsize_stack stack;
// This is specific to boost::coroutines2::protected_fixedsize_stack.
// The stack protection page is included in sctx.size, so we have to
// subtract one page size from the stack size.
std::size_t pfss_usable_stack_size(boost::context::stack_context &sctx) {
return sctx.size - boost::context::stack_traits::page_size();
}
public:
boost::context::stack_context allocate() {
auto sctx = stack.allocate();
// Despite what the boost docs warn, the only *implemented* stack direction
// is "down". This is why we subtract the stack size.
GC_add_roots(static_cast<char *>(sctx.sp) - pfss_usable_stack_size(sctx), sctx.sp);
return sctx;
}
void deallocate(boost::context::stack_context sctx) {
GC_remove_roots(static_cast<char *>(sctx.sp) - pfss_usable_stack_size(sctx), sctx.sp);
stack.deallocate(sctx);
}
};
然后在创建协程时提供它。
auto coro = boost::coroutines2::coroutine<std::string>::pull_type(BoehmGCStackAllocator{}, [&](coro_t::push_type & yield) {
// ...
}
Boost.Coroutine 分配自己的调用堆栈。 Boehm GC 是否将这些堆栈上的指针视为根,如果不是,我如何才能做到这一点?在上下文切换到协程后,Boehm 终止程序。
大概 Boost.Coroutine 中的代码保存了一个指向它分配的调用堆栈的指针,并将其存储在 "usual" 存储指针的地方之一(例如,一些指针变量)。
如果是这样,那么是的,GC 将 "chase" 指针从存储它的变量到调用堆栈,并从那里(递归地)通过它包含的任何指针。
目前 boost 不提供挂钩到分段堆栈分配的方法,因此这是固定大小堆栈的解决方案。
#include <gc/gc.h>
#include <gc/gc_cpp.h>
#include <boost/coroutine2/coroutine.hpp>
#include <boost/coroutine2/protected_fixedsize_stack.hpp>
#include <boost/context/stack_context.hpp>
class BoehmGCStackAllocator {
boost::coroutines2::protected_fixedsize_stack stack;
// This is specific to boost::coroutines2::protected_fixedsize_stack.
// The stack protection page is included in sctx.size, so we have to
// subtract one page size from the stack size.
std::size_t pfss_usable_stack_size(boost::context::stack_context &sctx) {
return sctx.size - boost::context::stack_traits::page_size();
}
public:
boost::context::stack_context allocate() {
auto sctx = stack.allocate();
// Despite what the boost docs warn, the only *implemented* stack direction
// is "down". This is why we subtract the stack size.
GC_add_roots(static_cast<char *>(sctx.sp) - pfss_usable_stack_size(sctx), sctx.sp);
return sctx;
}
void deallocate(boost::context::stack_context sctx) {
GC_remove_roots(static_cast<char *>(sctx.sp) - pfss_usable_stack_size(sctx), sctx.sp);
stack.deallocate(sctx);
}
};
然后在创建协程时提供它。
auto coro = boost::coroutines2::coroutine<std::string>::pull_type(BoehmGCStackAllocator{}, [&](coro_t::push_type & yield) {
// ...
}