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();
56 std::unique_ptr<detail::Fiber>
main;
68 std::vector<std::unique_ptr<Fiber>>
cache;
121 const ::Fiber* _fiber;
122 void* _buffer =
nullptr;
123 size_t _buffer_size = 0;
127 inline std::ostream& operator<<(std::ostream& out,
const StackBuffer& s) {
128 out <<
fmt(
"%p-%p:%zu", s.activeRegion().first, s.activeRegion().second, s.activeSize());
137 : _f(std::move(f)), _invoke([](
const hilti::rt::any& f,
resumable::Handle* h) -> hilti::rt::any {
138 return hilti::rt::any_cast<F>(f)(h);
181 _exception =
nullptr;
182 _function = std::move(f);
196 bool isMain()
const {
return _type ==
Type::Main; }
201 case State::Yielded:
return false;
203 case State::Aborting:
204 case State::Finished:
214 auto&& result() {
return std::move(_result); }
215 std::exception_ptr exception()
const {
return _exception; }
226 std::string tag()
const;
228 static std::unique_ptr<Fiber> create();
229 static void destroy(std::unique_ptr<Fiber> f);
230 static void primeCache();
238 uint64_t max_stack_size;
239 uint64_t initialized;
245 friend void ::__fiber_run_trampoline(
void* argsp);
246 friend void ::__fiber_switch_trampoline(
void* argsp);
247 friend void detail::trackStack();
249 enum class State { Init, Running, Aborting, Yielded, Idle, Finished };
251 void _yield(
const char* tag);
252 void _activate(
const char* tag);
255 static void _startSwitchFiber(
const char* tag,
detail::Fiber* to);
258 static void _finishSwitchFiber(
const char* tag);
264 State _state{State::Init};
265 std::optional<Callback> _function;
266 std::optional<hilti::rt::any> _result;
267 std::exception_ptr _exception;
270 std::unique_ptr<::Fiber> _fiber;
273 Fiber* _caller =
nullptr;
276 StackBuffer _stack_buffer;
279 const char* _location =
nullptr;
284 void* stack_base =
nullptr;
285 void* stack_limit =
nullptr;
286 void* deallocation_stack =
nullptr;
290 #ifdef HILTI_HAVE_ASAN
293 const void* stack =
nullptr;
294 size_t stack_size = 0;
295 void* fake_stack =
nullptr;
301 HILTI_JIT_IMPORT_OR_INLINE
static uint64_t _total_fibers;
302 HILTI_JIT_IMPORT_OR_INLINE
static uint64_t _current_fibers;
303 HILTI_JIT_IMPORT_OR_INLINE
static uint64_t _cached_fibers;
304 HILTI_JIT_IMPORT_OR_INLINE
static uint64_t _max_fibers;
305 HILTI_JIT_IMPORT_OR_INLINE
static uint64_t _max_stack_size;
306 HILTI_JIT_IMPORT_OR_INLINE
static uint64_t _initialized;
309 std::ostream& operator<<(std::ostream& out,
const Fiber& fiber);
328 template<
typename Function>
330 requires(std::is_invocable_v<Function, resumable::Handle*>)
331 : _fiber(detail::Fiber::create()) {
332 _fiber->init(std::move(f));
344 detail::Fiber::destroy(std::move(_fiber));
366 bool hasResult()
const {
return _done && _result.has_value(); }
372 template<
typename Result>
374 assert(
static_cast<bool>(_result));
376 if constexpr ( std::is_same_v<Result, void> )
380 return hilti::rt::any_cast<const Result&>(*_result);
381 }
catch (
const hilti::rt::bad_any_cast& ) {
382 throw InvalidArgument(
"mismatch in result type");
388 explicit operator bool()
const {
return _done; }
393 void checkFiber(
const char*
location)
const {
395 throw std::logic_error(std::string(
"fiber not set in ") +
location);
398 std::unique_ptr<detail::Fiber> _fiber;
400 std::optional<hilti::rt::any> _result;
403 namespace resumable::detail {
409 static_assert(! std::is_reference_v<T>,
"copyArg() does not accept references other than ValueReference<T>.");
416 ValueReference<T> copyArg(
const ValueReference<T>& t) {
417 return ValueReference<T>(t.asSharedPtr());
423 ValueReference<T> copyArg(ValueReference<T>& t) {
424 return ValueReference<T>(t.asSharedPtr());
435 template<
typename Function>
436 auto execute(Function f) {
437 Resumable r(std::move(f));
Definition: function.h:19
void resume()
Definition: fiber.cc:752
resumable::Handle * handle()
Definition: fiber.h:360
void abort()
Definition: fiber.cc:763
const Result & get() const
Definition: fiber.h:373
Resumable(Function f) requires(std
Definition: fiber.h:329
void run()
Definition: fiber.cc:741
bool hasResult() const
Definition: fiber.h:366
void setLocation(const char *location=nullptr)
Definition: fiber.h:224
const auto & stackBuffer() const
Definition: fiber.h:189
Type
Definition: fiber.h:163
const char * location() const
Definition: fiber.h:218
auto type()
Definition: fiber.h:186
void location(const char *x)
Definition: logging.h:126
std::string fmt(const char *fmt, const Args &... args)
Definition: fmt.h:17
void cannot_be_reached()
Definition: util.cc:53
std::unique_ptr< detail::Fiber > switch_trampoline
Definition: fiber.h:59
std::vector< std::unique_ptr< Fiber > > cache
Definition: fiber.h:68
std::unique_ptr< detail::Fiber > main
Definition: fiber.h:56
detail::Fiber * current
Definition: fiber.h:62
std::unique_ptr<::Fiber > shared_stack
Definition: fiber.h:65
std::pair< char *, char * > activeRegion() const
Definition: fiber.cc:379
size_t liveRemainingSize() const
Definition: fiber.cc:401
void save()
Definition: fiber.cc:428
void restore() const
Definition: fiber.cc:459
std::pair< char *, char * > allocatedRegion() const
Definition: fiber.cc:396
~StackBuffer()
Definition: fiber.cc:377
size_t activeSize() const
Definition: fiber.cc:426
StackBuffer(const ::Fiber *fiber)
Definition: fiber.h:80
size_t allocatedSize() const
Definition: fiber.h:106