1 /** 2 * Copyright (c) 2022-2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #ifndef PANDA_RUNTIME_COROUTINES_THREADED_COROUTINE_MANAGER_H 16 #define PANDA_RUNTIME_COROUTINES_THREADED_COROUTINE_MANAGER_H 17 18 #include "libpandabase/os/mutex.h" 19 #include "runtime/coroutines/coroutine_manager.h" 20 #include "runtime/coroutines/coroutine.h" 21 #include "runtime/include/value.h" 22 23 namespace ark { 24 25 /** 26 * @brief Thread-based coroutine manager implementation. 27 * 28 * In this implementation coroutines are OS threads. The invariants (only N coroutines are running simultaniously, etc.) 29 * are kept with the help of mutexes and condition variables. 30 * 31 * For interface function descriptions see CoroutineManager class declaration. 32 */ 33 class ThreadedCoroutineManager : public CoroutineManager { 34 public: 35 NO_COPY_SEMANTIC(ThreadedCoroutineManager); 36 NO_MOVE_SEMANTIC(ThreadedCoroutineManager); 37 ThreadedCoroutineManager(CoroutineFactory factory)38 explicit ThreadedCoroutineManager(CoroutineFactory factory) : CoroutineManager(factory) {} 39 ~ThreadedCoroutineManager() override = default; 40 41 /* CoroutineManager interfaces, see CoroutineManager class for the details */ 42 void Initialize(CoroutineManagerConfig config, Runtime *runtime, PandaVM *vm) override; 43 void Finalize() override; 44 void RegisterCoroutine(Coroutine *co) override; 45 bool TerminateCoroutine(Coroutine *co) override; 46 Coroutine *Launch(CompletionEvent *completionEvent, Method *entrypoint, PandaVector<Value> &&arguments, 47 CoroutineLaunchMode mode) override; 48 void Schedule() override; 49 void Await(CoroutineEvent *awaitee) RELEASE(awaitee) override; 50 void UnblockWaiters(CoroutineEvent *blocker) override; 51 52 /* ThreadManager interfaces, see ThreadManager class for the details */ 53 void WaitForDeregistration() override; 54 void SuspendAllThreads() override; 55 void ResumeAllThreads() override; 56 bool IsRunningThreadExist() override; 57 58 /* debugging tools */ 59 /** 60 * For ThreadedCoroutineManager implementation: no action performed if an attempt to switch coroutines on current 61 * worker is detected when coroutine switch is disabled. 62 */ DisableCoroutineSwitch()63 void DisableCoroutineSwitch() override {}; EnableCoroutineSwitch()64 void EnableCoroutineSwitch() override {}; IsCoroutineSwitchDisabled()65 bool IsCoroutineSwitchDisabled() override 66 { 67 return false; 68 }; 69 70 bool IsMainWorker(Coroutine *co) const override; 71 72 protected: 73 bool EnumerateThreadsImpl(const ThreadManager::Callback &cb, unsigned int incMask, 74 unsigned int xorMask) const override; 75 CoroutineContext *CreateCoroutineContext(bool coroHasEntrypoint) override; 76 void DeleteCoroutineContext(CoroutineContext *ctx) override; 77 78 size_t GetCoroutineCount() override; 79 size_t GetCoroutineCountLimit() override; 80 81 /// Sets number of coroutines that can execute simultaniously 82 void SetWorkersCount(uint32_t n); 83 /// Returns number of coroutines that can execute simultaniously 84 uint32_t GetWorkersCount() const; 85 86 private: 87 Coroutine *LaunchImpl(CompletionEvent *completionEvent, Method *entrypoint, PandaVector<Value> &&arguments, 88 bool startSuspended = true); 89 void ScheduleImpl(); 90 void UnblockWaitersImpl(CoroutineEvent *blocker) REQUIRES(coroSwitchLock_); 91 92 /* runnables queue management */ 93 void PushToRunnableQueue(Coroutine *co); 94 Coroutine *PopFromRunnableQueue(); 95 #ifndef NDEBUG 96 void PrintRunnableQueue(const PandaString &requester); 97 #endif 98 bool RunnableCoroutinesExist(); 99 100 /* coroutine registry management */ 101 void AddToRegistry(Coroutine *co); 102 void RemoveFromRegistry(Coroutine *co) REQUIRES(coroListLock_); 103 104 void DeleteCoroutineInstance(Coroutine *co); 105 bool RegisterWaiter(Coroutine *waiter, CoroutineEvent *awaitee) RELEASE(awaitee); 106 void ScheduleNextCoroutine(); 107 void MainCoroutineCompleted(); 108 109 os::memory::Mutex coroSwitchLock_; 110 os::memory::Mutex waitersLock_; 111 mutable os::memory::Mutex coroListLock_; 112 // all registered coros 113 PandaSet<Coroutine *> coroutines_ GUARDED_BY(coroListLock_); 114 // ready coros 115 PandaDeque<Coroutine *> runnablesQueue_; 116 // blocked coros: Coroutine AWAITS CoroutineEvent 117 PandaMultiMap<CoroutineEvent *, Coroutine *> waiters_; 118 119 os::memory::ConditionVariable cvAwaitAll_; 120 os::memory::Mutex cvAwaitAllMutex_; 121 122 uint32_t workersCount_ = 1; 123 // main is running from the very beginning 124 std::atomic_uint32_t runningCorosCount_ = 1; 125 std::atomic_uint32_t coroutineCount_ = 0; 126 }; 127 128 } // namespace ark 129 130 #endif /* PANDA_RUNTIME_COROUTINES_THREADED_COROUTINE_MANAGER_H */ 131