Advertisement
Guest User

Untitled

a guest
Apr 1st, 2020
183
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.48 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. Fiber* caller = GetCurrentFiber();
  68. ++count_of_sleeping_;
  69. WaitableTimer timer(io_context_, duration);
  70. auto handler = [this, caller](const asio::error_code& error) {
  71. --count_of_sleeping_;
  72. caller->WakeUp();
  73. Reschedule(caller);
  74. };
  75. caller->Sleep();
  76. timer.async_wait(handler);
  77. SwitchToScheduler();
  78. }
  79.  
  80. void Scheduler::Terminate() {
  81. Fiber* caller = GetCurrentFiber();
  82. caller->SetState(FiberState::Terminated);
  83. SwitchToScheduler();
  84. }
  85.  
  86. // Scheduling
  87.  
  88. void Scheduler::Run(FiberRoutine init) {
  89. SchedulerScope scope(this);
  90. Spawn(init);
  91. RunLoop();
  92. }
  93.  
  94. void Scheduler::RunLoop() {
  95. asio::executor_work_guard<asio::io_context::executor_type> work =
  96. asio::make_work_guard(io_context_);
  97. while (!run_queue_.IsEmpty() || count_of_sleeping_ > 0) {
  98. if (run_queue_.IsEmpty()) {
  99. io_context_.run_one();
  100. } else {
  101. Fiber* next = run_queue_.PopFront();
  102. SwitchTo(next);
  103. if (!next->IsSleepingNow()) {
  104. Reschedule(next);
  105. }
  106. io_context_.poll();
  107. }
  108. }
  109. work.reset();
  110. }
  111.  
  112. void Scheduler::SwitchTo(Fiber* fiber) {
  113. SetCurrentFiber(fiber);
  114. fiber->SetState(FiberState::Running);
  115. // Scheduler loop_context_ -> fiber->context_
  116. loop_context_.SwitchTo(fiber->Context());
  117. }
  118.  
  119. void Scheduler::Reschedule(Fiber* fiber) {
  120. switch (fiber->State()) {
  121. case FiberState::Runnable: // From Yield
  122. Schedule(fiber);
  123. break;
  124. case FiberState::Terminated: // From Terminate
  125. Destroy(fiber);
  126. break;
  127. default:
  128. TINY_PANIC("Unexpected fiber state");
  129. break;
  130. }
  131. }
  132.  
  133. void Scheduler::Schedule(Fiber* fiber) {
  134. run_queue_.PushBack(fiber);
  135. }
  136.  
  137. Fiber* Scheduler::CreateFiber(FiberRoutine routine) {
  138. return Fiber::Create(routine);
  139. }
  140.  
  141. void Scheduler::Destroy(Fiber* fiber) {
  142. delete fiber;
  143. }
  144.  
  145. //////////////////////////////////////////////////////////////////////
  146.  
  147. Fiber* GetCurrentFiber() {
  148. return GetCurrentScheduler()->GetCurrentFiber();
  149. }
  150.  
  151. } // namespace tinyfiber
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement