Advertisement
Guest User

Untitled

a guest
Apr 1st, 2020
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.98 KB | None | 0 0
  1. #include "scheduler.hpp"
  2.  
  3. namespace tinyfiber {
  4.  
  5. //////////////////////////////////////////////////////////////////////
  6.  
  7. static thread_local Scheduler* current_scheduler;
  8.  
  9. Scheduler* GetCurrentScheduler() {
  10. TINY_VERIFY(current_scheduler, "not in fiber context");
  11. return current_scheduler;
  12. }
  13.  
  14. struct SchedulerScope {
  15. SchedulerScope(Scheduler* scheduler) {
  16. TINY_VERIFY(!current_scheduler,
  17. "cannot run scheduler from another scheduler");
  18. current_scheduler = scheduler;
  19. }
  20.  
  21. ~SchedulerScope() {
  22. current_scheduler = nullptr;
  23. }
  24. };
  25.  
  26. //////////////////////////////////////////////////////////////////////
  27.  
  28. Scheduler::Scheduler() {
  29. }
  30.  
  31. Fiber* Scheduler::GetCurrentFiber() {
  32. TINY_VERIFY(running_ != nullptr, "Not in fiber context");
  33. return running_;
  34. }
  35.  
  36. Fiber* Scheduler::GetAndResetCurrentFiber() {
  37. Fiber* current = running_;
  38. running_ = nullptr;
  39. return current;
  40. }
  41.  
  42. void Scheduler::SetCurrentFiber(Fiber* fiber) {
  43. running_ = fiber;
  44. }
  45.  
  46. // Operations invoked by running fibers
  47.  
  48. void Scheduler::SwitchToScheduler() {
  49. Fiber* caller = GetAndResetCurrentFiber();
  50. caller->Context().SwitchTo(loop_context_);
  51. }
  52.  
  53. // System calls
  54.  
  55. void Scheduler::Spawn(FiberRoutine routine) {
  56. auto* created = CreateFiber(routine);
  57. Schedule(created);
  58. }
  59.  
  60. void Scheduler::Yield() {
  61. Fiber* caller = GetCurrentFiber();
  62. caller->SetState(FiberState::Runnable);
  63. SwitchToScheduler();
  64. }
  65.  
  66. void Scheduler::SleepFor(Duration duration) {
  67. // Intentionally ineffective implementation
  68.  
  69. StopWatch stop_watch;
  70. do {
  71. Yield();
  72. } while (stop_watch.Elapsed() < duration);
  73. }
  74.  
  75. void Scheduler::Terminate() {
  76. Fiber* caller = GetCurrentFiber();
  77. caller->SetState(FiberState::Terminated);
  78. SwitchToScheduler();
  79. }
  80.  
  81. // Scheduling
  82.  
  83. void Scheduler::Run(FiberRoutine init) {
  84. SchedulerScope scope(this);
  85. Spawn(init);
  86. RunLoop();
  87. }
  88.  
  89. void Scheduler::RunLoop() {
  90. while (!run_queue_.IsEmpty()) {
  91. Fiber* next = run_queue_.PopFront();
  92. SwitchTo(next);
  93. Reschedule(next);
  94. }
  95. }
  96.  
  97. void Scheduler::SwitchTo(Fiber* fiber) {
  98. SetCurrentFiber(fiber);
  99. fiber->SetState(FiberState::Running);
  100. // Scheduler loop_context_ -> fiber->context_
  101. loop_context_.SwitchTo(fiber->Context());
  102. }
  103.  
  104. void Scheduler::Reschedule(Fiber* fiber) {
  105. switch (fiber->State()) {
  106. case FiberState::Runnable: // From Yield
  107. Schedule(fiber);
  108. break;
  109. case FiberState::Terminated: // From Terminate
  110. Destroy(fiber);
  111. break;
  112. default:
  113. TINY_PANIC("Unexpected fiber state");
  114. break;
  115. }
  116. }
  117.  
  118. void Scheduler::Schedule(Fiber* fiber) {
  119. run_queue_.PushBack(fiber);
  120. }
  121.  
  122. Fiber* Scheduler::CreateFiber(FiberRoutine routine) {
  123. return Fiber::Create(routine);
  124. }
  125.  
  126. void Scheduler::Destroy(Fiber* fiber) {
  127. delete fiber;
  128. }
  129.  
  130. //////////////////////////////////////////////////////////////////////
  131.  
  132. Fiber* GetCurrentFiber() {
  133. return GetCurrentScheduler()->GetCurrentFiber();
  134. }
  135.  
  136. } // namespace tinyfiber
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement