fiber.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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. #if !defined(_WIN32) && !defined(WIN32)
  8. namespace boost::context::detail {
  9. struct transfer_t;
  10. }
  11. #endif
  12. namespace Common {
  13. /**
  14. * Fiber class
  15. * a fiber is a userspace thread with it's own context. They can be used to
  16. * implement coroutines, emulated threading systems and certain asynchronous
  17. * patterns.
  18. *
  19. * This class implements fibers at a low level, thus allowing greater freedom
  20. * to implement such patterns. This fiber class is 'threadsafe' only one fiber
  21. * can be running at a time and threads will be locked while trying to yield to
  22. * a running fiber until it yields. WARNING exchanging two running fibers between
  23. * threads will cause a deadlock. In order to prevent a deadlock, each thread should
  24. * have an intermediary fiber, you switch to the intermediary fiber of the current
  25. * thread and then from it switch to the expected fiber. This way you can exchange
  26. * 2 fibers within 2 different threads.
  27. */
  28. class Fiber {
  29. public:
  30. Fiber(std::function<void(void*)>&& entry_point_func, void* start_parameter);
  31. ~Fiber();
  32. Fiber(const Fiber&) = delete;
  33. Fiber& operator=(const Fiber&) = delete;
  34. Fiber(Fiber&&) = default;
  35. Fiber& operator=(Fiber&&) = default;
  36. /// Yields control from Fiber 'from' to Fiber 'to'
  37. /// Fiber 'from' must be the currently running fiber.
  38. static void YieldTo(std::shared_ptr<Fiber> from, std::shared_ptr<Fiber> to);
  39. [[nodiscard]] static std::shared_ptr<Fiber> ThreadToFiber();
  40. void SetRewindPoint(std::function<void(void*)>&& rewind_func, void* rewind_param);
  41. void Rewind();
  42. /// Only call from main thread's fiber
  43. void Exit();
  44. /// Changes the start parameter of the fiber. Has no effect if the fiber already started
  45. void SetStartParameter(void* new_parameter);
  46. private:
  47. Fiber();
  48. #if defined(_WIN32) || defined(WIN32)
  49. void OnRewind();
  50. void Start();
  51. static void FiberStartFunc(void* fiber_parameter);
  52. static void RewindStartFunc(void* fiber_parameter);
  53. #else
  54. void OnRewind(boost::context::detail::transfer_t& transfer);
  55. void Start(boost::context::detail::transfer_t& transfer);
  56. static void FiberStartFunc(boost::context::detail::transfer_t transfer);
  57. static void RewindStartFunc(boost::context::detail::transfer_t transfer);
  58. #endif
  59. struct FiberImpl;
  60. std::unique_ptr<FiberImpl> impl;
  61. };
  62. } // namespace Common