#ifndef PREDICTABLE_PARALLEL_PATTERNS_APP_CONTEXT_SWITCH_FIBER_CALL_H_ #define PREDICTABLE_PARALLEL_PATTERNS_APP_CONTEXT_SWITCH_FIBER_CALL_H_ #include #include #include #include namespace pls { namespace internal { namespace base { using continuation_t = void *; using stack_pointer_t = char *; using callback_t = continuation_t (*)(continuation_t, void *); template struct lambda_capture { F lambda_; explicit lambda_capture(F &&lambda) : lambda_{std::forward(lambda)} {} continuation_t operator()(continuation_t continuation) { return lambda_(continuation); } }; template continuation_t execute_callable(continuation_t continuation, void *param) { T *callable = reinterpret_cast(param); continuation_t result = (*callable)(continuation); callable->~T(); return result; } extern "C" { continuation_t __fiber_call(stack_pointer_t stack_base, void *callback_arg, callback_t callback, stack_pointer_t stack_limit); continuation_t __fiber_continue(continuation_t continuation); } template static lambda_capture *place_lambda_capture(F &&lambda, char *memory) { return new(memory) lambda_capture(std::forward(lambda)); } template continuation_t fiber_call(stack_pointer_t stack_memory, size_t stack_size, F &&lambda) { stack_pointer_t lambda_memory = stack_memory + stack_size - sizeof(lambda_capture); auto *captured_lambda = place_lambda_capture(std::forward(lambda), lambda_memory); stack_pointer_t stack_base = lambda_memory; stack_pointer_t stack_limit = stack_memory; callback_t callback = execute_callable>; return __fiber_call(stack_base, captured_lambda, callback, stack_limit); } } } } #endif //PREDICTABLE_PARALLEL_PATTERNS_APP_CONTEXT_SWITCH_FIBER_CALL_H_