fiber.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. // Copyright 2020 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <functional>
  6. #include <memory>
  7. namespace boost::context::detail {
  8. struct transfer_t;
  9. }
  10. namespace Common {
  11. /**
  12. * Fiber class
  13. * a fiber is a userspace thread with it's own context. They can be used to
  14. * implement coroutines, emulated threading systems and certain asynchronous
  15. * patterns.
  16. *
  17. * This class implements fibers at a low level, thus allowing greater freedom
  18. * to implement such patterns. This fiber class is 'threadsafe' only one fiber
  19. * can be running at a time and threads will be locked while trying to yield to
  20. * a running fiber until it yields. WARNING exchanging two running fibers between
  21. * threads will cause a deadlock. In order to prevent a deadlock, each thread should
  22. * have an intermediary fiber, you switch to the intermediary fiber of the current
  23. * thread and then from it switch to the expected fiber. This way you can exchange
  24. * 2 fibers within 2 different threads.
  25. */
  26. class Fiber {
  27. public:
  28. Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter);
  29. ~Fiber();
  30. Fiber(const Fiber&) = delete;
  31. Fiber& operator=(const Fiber&) = delete;
  32. Fiber(Fiber&&) = default;
  33. Fiber& operator=(Fiber&&) = default;
  34. /// Yields control from Fiber 'from' to Fiber 'to'
  35. /// Fiber 'from' must be the currently running fiber.
  36. static void YieldTo(std::weak_ptr<Fiber> weak_from, Fiber& to);
  37. [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
  38. void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param);
  39. void Rewind();
  40. /// Only call from main thread's fiber
  41. void Exit();
  42. /// Changes the start parameter of the fiber. Has no effect if the fiber already started
  43. void SetStartParameter(void* new_parameter);
  44. private:
  45. Fiber();
  46. void OnRewind(boost::context::detail::transfer_t& transfer);
  47. void Start(boost::context::detail::transfer_t& transfer);
  48. static void FiberStartFunc(boost::context::detail::transfer_t transfer);
  49. static void RewindStartFunc(boost::context::detail::transfer_t transfer);
  50. struct FiberImpl;
  51. std::unique_ptr<FiberImpl> impl;
  52. };
  53. } // namespace Common