Я работаю над реализацией волокон с использованием сопрограмм, реализованных на ассемблере. Сопрограммы работают cocall
для изменения стека.
Я хотел бы показать это на С++, используя интерфейс более высокого уровня, поскольку сборка cocall
может обрабатывать только один аргумент void*
.
Чтобы обрабатывать шаблонные лямбда-выражения, я экспериментировал с преобразованием их в void*
и обнаружил, что, хотя он компилируется и работает, мне остается только гадать, безопасно ли это делать, предполагая семантику владения стеком (которая сохраняется волокнами ).
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);
}
Это безопасно и, кроме того, эффективно? Преобразовывая в void*
, заставляю ли я компилятор выбирать менее эффективное представление?
Кроме того, при вызове coentry(void*)
в другом стеке, но исходный invoke(FunctionT)
вернулся, есть ли шанс, что стек может оказаться недопустимым для возобновления? (было бы похоже, скажем, на вызов внутри std::thread
, я думаю).
void *
для передачи вызываемого объекта? Почему бы не использовать тип шаблонаFunctionT
? Илиstd::function
? - person Some programmer dude   schedule 03.07.2017cocall
может обрабатывать только один аргументvoid *
для нового стека. - person ioquatix   schedule 03.07.2017static_assert(sizeof(void *) == sizeof(&function));
, потому что указатель на функцию может не иметь того же размера, что и указатель на void. - person user7860670   schedule 03.07.2017void*
, и я знаю, что это было аналогично в С++ - если это не изменилось недавно (о чем я не знаю), вы все равно делаете незаконные вещи... - person Aconcagua   schedule 03.07.2017FunctionT
будет выводиться как тип закрытия лямбды, объекта. - person StoryTeller - Unslander Monica   schedule 03.07.2017