13 #include <hilti/rt/any.h>
14 #include <hilti/rt/autogen/config.h>
15 #include <hilti/rt/configuration.h>
16 #include <hilti/rt/exception.h>
17 #include <hilti/rt/types/reference.h>
18 #include <hilti/rt/util.h>
23 extern "C" void __fiber_run_trampoline(
void* args);
26 extern "C" void __fiber_switch_trampoline(
void* args);
36 using Handle = detail::Fiber;
42 extern void trackStack();
50 std::unique_ptr<detail::Fiber>
main;
62 std::vector<std::unique_ptr<Fiber>>
cache;
115 const ::Fiber* _fiber;
116 void* _buffer =
nullptr;
117 size_t _buffer_size = 0;
121 inline std::ostream& operator<<(std::ostream& out,
const StackBuffer& s) {
122 out <<
fmt(
"%p-%p:%zu", s.activeRegion().first, s.activeRegion().second, s.activeSize());
131 : _f(std::move(f)), _invoke([](
const hilti::rt::any& f,
resumable::Handle* h) -> hilti::rt::any {
132 return hilti::rt::any_cast<F>(f)(h);
175 _exception =
nullptr;
176 _function = std::move(f);
190 bool isMain()
const {
return _type ==
Type::Main; }
195 case State::Yielded:
return false;
197 case State::Aborting:
198 case State::Finished:
208 auto&& result() {
return std::move(_result); }
209 std::exception_ptr exception()
const {
return _exception; }
220 std::string tag()
const;
222 static std::unique_ptr<Fiber> create();
223 static void destroy(std::unique_ptr<Fiber> f);
224 static void primeCache();
232 uint64_t max_stack_size;
233 uint64_t initialized;
239 friend void ::__fiber_run_trampoline(
void* argsp);
240 friend void ::__fiber_switch_trampoline(
void* argsp);
241 friend void detail::trackStack();
243 enum class State { Init, Running, Aborting, Yielded, Idle, Finished };
245 void _yield(
const char* tag);
246 void _activate(
const char* tag);
249 static void _startSwitchFiber(
const char* tag,
detail::Fiber* to);
252 static void _finishSwitchFiber(
const char* tag);
258 State _state{State::Init};
259 std::optional<Callback> _function;
260 std::optional<hilti::rt::any> _result;
261 std::exception_ptr _exception;
264 std::unique_ptr<::Fiber> _fiber;
267 Fiber* _caller =
nullptr;
270 StackBuffer _stack_buffer;
273 const char* _location =
nullptr;
275 #ifdef HILTI_HAVE_ASAN
278 const void* stack =
nullptr;
279 size_t stack_size = 0;
280 void* fake_stack =
nullptr;
286 inline static uint64_t _total_fibers;
287 inline static uint64_t _current_fibers;
288 inline static uint64_t _cached_fibers;
289 inline static uint64_t _max_fibers;
290 inline static uint64_t _max_stack_size;
291 inline static uint64_t _initialized;
294 std::ostream& operator<<(std::ostream& out,
const Fiber& fiber);
313 template<
typename Function>
315 requires(std::is_invocable_v<Function, resumable::Handle*>)
316 : _fiber(detail::Fiber::create()) {
317 _fiber->init(std::move(f));
329 detail::Fiber::destroy(std::move(_fiber));
351 bool hasResult()
const {
return _done && _result.has_value(); }
357 template<
typename Result>
359 assert(
static_cast<bool>(_result));
361 if constexpr ( std::is_same_v<Result, void> )
365 return hilti::rt::any_cast<const Result&>(*_result);
366 }
catch (
const hilti::rt::bad_any_cast& ) {
367 throw InvalidArgument(
"mismatch in result type");
373 explicit operator bool()
const {
return _done; }
378 void checkFiber(
const char* location)
const {
380 throw std::logic_error(std::string(
"fiber not set in ") + location);
383 std::unique_ptr<detail::Fiber> _fiber;
385 std::optional<hilti::rt::any> _result;
388 namespace resumable::detail {
394 static_assert(! std::is_reference_v<T>,
"copyArg() does not accept references other than ValueReference<T>.");
401 ValueReference<T> copyArg(
const ValueReference<T>& t) {
402 return ValueReference<T>(t.asSharedPtr());
408 ValueReference<T> copyArg(ValueReference<T>& t) {
409 return ValueReference<T>(t.asSharedPtr());
420 template<
typename Function>
421 auto execute(Function f) {
422 Resumable r(std::move(f));
Definition: function.h:18
void resume()
Definition: fiber.cc:631
resumable::Handle * handle()
Definition: fiber.h:345
void abort()
Definition: fiber.cc:642
const Result & get() const
Definition: fiber.h:358
Resumable(Function f) requires(std
Definition: fiber.h:314
void run()
Definition: fiber.cc:620
bool hasResult() const
Definition: fiber.h:351
void setLocation(const char *location=nullptr)
Definition: fiber.h:218
const auto & stackBuffer() const
Definition: fiber.h:183
Type
Definition: fiber.h:157
const char * location() const
Definition: fiber.h:212
auto type()
Definition: fiber.h:180
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:13
void cannot_be_reached() __attribute__((noreturn))
Definition: util.cc:45
std::unique_ptr< detail::Fiber > switch_trampoline
Definition: fiber.h:53
std::vector< std::unique_ptr< Fiber > > cache
Definition: fiber.h:62
std::unique_ptr< detail::Fiber > main
Definition: fiber.h:50
detail::Fiber * current
Definition: fiber.h:56
std::unique_ptr<::Fiber > shared_stack
Definition: fiber.h:59
std::pair< char *, char * > activeRegion() const
Definition: fiber.cc:289
size_t liveRemainingSize() const
Definition: fiber.cc:308
void save()
Definition: fiber.cc:332
void restore() const
Definition: fiber.cc:360
std::pair< char *, char * > allocatedRegion() const
Definition: fiber.cc:303
~StackBuffer()
Definition: fiber.cc:287
size_t activeSize() const
Definition: fiber.cc:330
StackBuffer(const ::Fiber *fiber)
Definition: fiber.h:74
size_t allocatedSize() const
Definition: fiber.h:100