1 #include <MTScheduler.h> 2 3 namespace MT 4 { 5 FiberContext::FiberContext() 6 : threadContext(nullptr) 7 , taskStatus(FiberTaskStatus::UNKNOWN) 8 , currentGroup(TaskGroup::GROUP_UNDEFINED) 9 , childrenFibersCount(0) 10 , parentFiber(nullptr) 11 { 12 } 13 14 void FiberContext::SetStatus(FiberTaskStatus::Type _taskStatus) 15 { 16 ASSERT(threadContext, "Sanity check failed"); 17 ASSERT(threadContext->thread.IsCurrentThread(), "You can change task status only from owner thread"); 18 taskStatus = _taskStatus; 19 } 20 21 FiberTaskStatus::Type FiberContext::GetStatus() const 22 { 23 return taskStatus; 24 } 25 26 void FiberContext::SetThreadContext(internal::ThreadContext * _threadContext) 27 { 28 if (_threadContext) 29 { 30 _threadContext->lastActiveFiberContext = this; 31 } 32 33 threadContext = _threadContext; 34 } 35 36 internal::ThreadContext* FiberContext::GetThreadContext() 37 { 38 return threadContext; 39 } 40 41 void FiberContext::Reset() 42 { 43 ASSERT(childrenFibersCount.Get() == 0, "Can't release fiber with active children fibers"); 44 45 currentGroup = TaskGroup::GROUP_UNDEFINED; 46 currentTask = internal::TaskDesc(); 47 parentFiber = nullptr; 48 threadContext = nullptr; 49 } 50 51 void FiberContext::WaitGroupAndYield(TaskGroup::Type group) 52 { 53 ASSERT(threadContext, "Sanity check failed!"); 54 ASSERT(threadContext->taskScheduler->IsWorkerThread(), "Can't use WaitGroupAndYield outside Task. Use TaskScheduler.WaitGroup() instead."); 55 ASSERT(threadContext->thread.IsCurrentThread(), "Thread context sanity check failed"); 56 57 VERIFY(group != currentGroup, "Can't wait the same group. Deadlock detected!", return); 58 VERIFY(group < TaskGroup::COUNT, "Invalid group!", return); 59 60 ConcurrentQueueLIFO<FiberContext*> & groupQueue = threadContext->taskScheduler->waitTaskQueues[group]; 61 62 // Change status 63 taskStatus = FiberTaskStatus::AWAITING_GROUP; 64 65 // Add current fiber to awaiting queue 66 groupQueue.Push(this); 67 68 Fiber & schedulerFiber = threadContext->schedulerFiber; 69 70 // Yielding, so reset thread context 71 threadContext = nullptr; 72 73 //switch to scheduler 74 Fiber::SwitchTo(fiber, schedulerFiber); 75 } 76 77 void FiberContext::RunSubtasksAndYieldImpl(fixed_array<internal::TaskBucket>& buckets) 78 { 79 ASSERT(threadContext, "Sanity check failed!"); 80 ASSERT(threadContext->taskScheduler->IsWorkerThread(), "Can't use RunSubtasksAndYield outside Task. Use TaskScheduler.WaitGroup() instead."); 81 ASSERT(threadContext->thread.IsCurrentThread(), "Thread context sanity check failed"); 82 83 // add to scheduler 84 threadContext->taskScheduler->RunTasksImpl(buckets, this, false); 85 86 // 87 ASSERT(threadContext->thread.IsCurrentThread(), "Thread context sanity check failed"); 88 89 // Change status 90 taskStatus = FiberTaskStatus::AWAITING_CHILD; 91 92 Fiber & schedulerFiber = threadContext->schedulerFiber; 93 94 // Yielding, so reset thread context 95 threadContext = nullptr; 96 97 //switch to scheduler 98 Fiber::SwitchTo(fiber, schedulerFiber); 99 } 100 101 102 } 103