I'm working on implementing fibers using coroutines implemented in assembler. The coroutines work by cocall
to change stack.
I'd like to expose this in C++ using a higher level interface, as cocall
assembly can only handle a single void*
argument.
In order to handle template lambdas, I've experimented with converting them to a void*
and found that while it compiles and works, I was left wondering if it was safe to do so, assuming ownership semantics of the stack (which are preserved by fibers).
template <typename FunctionT>
struct Coentry
{
static void coentry(void * arg)
{
// Is this safe?
FunctionT * function = reinterpret_cast<FunctionT *>(arg);
(*function)();
}
static void invoke(FunctionT function)
{
coentry(reinterpret_cast<void *>(&function));
}
};
template <typename FunctionT>
void coentry(FunctionT function)
{
Coentry<FunctionT>::invoke(function);
}
int main(int argc, const char * argv[]) {
auto f = [&]{
std::cerr << "Hello World!" << std::endl;
};
coentry(f);
}
Is this safe and additionally, is it efficient? By converting to a void*
am I forcing the compiler to choose a less efficient representation?
Additionally, by invoking coentry(void*)
on a different stack, but the original invoke(FunctionT)
has returned, is there a chance that the stack might be invalid to resume? (would be similar to, say invoking within a std::thread
I guess).