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 protected: 71 bool EnumerateThreadsImpl(const ThreadManager::Callback &cb, unsigned int incMask, 72 unsigned int xorMask) const override; 73 CoroutineContext *CreateCoroutineContext(bool coroHasEntrypoint) override; 74 void DeleteCoroutineContext(CoroutineContext *ctx) override; 75 76 size_t GetCoroutineCount() override; 77 size_t GetCoroutineCountLimit() override; 78 79 /// Sets number of coroutines that can execute simultaniously 80 void SetWorkersCount(uint32_t n); 81 /// Returns number of coroutines that can execute simultaniously 82 uint32_t GetWorkersCount() const; 83 84 private: 85 Coroutine *LaunchImpl(CompletionEvent *completionEvent, Method *entrypoint, PandaVector<Value> &&arguments, 86 bool startSuspended = true); 87 void ScheduleImpl(); 88 void UnblockWaitersImpl(CoroutineEvent *blocker) REQUIRES(coroSwitchLock_); 89 90 /* runnables queue management */ 91 void PushToRunnableQueue(Coroutine *co); 92 Coroutine *PopFromRunnableQueue(); 93 #ifndef NDEBUG 94 void PrintRunnableQueue(const PandaString &requester); 95 #endif 96 bool RunnableCoroutinesExist(); 97 98 /* coroutine registry management */ 99 void AddToRegistry(Coroutine *co); 100 void RemoveFromRegistry(Coroutine *co) REQUIRES(coroListLock_); 101 102 void DeleteCoroutineInstance(Coroutine *co); 103 bool RegisterWaiter(Coroutine *waiter, CoroutineEvent *awaitee) RELEASE(awaitee); 104 void ScheduleNextCoroutine(); 105 void MainCoroutineCompleted(); 106 107 os::memory::Mutex coroSwitchLock_; 108 os::memory::Mutex waitersLock_; 109 mutable os::memory::Mutex coroListLock_; 110 // all registered coros 111 PandaSet<Coroutine *> coroutines_ GUARDED_BY(coroListLock_); 112 // ready coros 113 PandaDeque<Coroutine *> runnablesQueue_; 114 // blocked coros: Coroutine AWAITS CoroutineEvent 115 PandaMultiMap<CoroutineEvent *, Coroutine *> waiters_; 116 117 os::memory::ConditionVariable cvAwaitAll_; 118 os::memory::Mutex cvAwaitAllMutex_; 119 120 uint32_t workersCount_ = 1; 121 // main is running from the very beginning 122 std::atomic_uint32_t runningCorosCount_ = 1; 123 std::atomic_uint32_t coroutineCount_ = 0; 124 }; 125 126 } // namespace ark 127 128 #endif /* PANDA_RUNTIME_COROUTINES_THREADED_COROUTINE_MANAGER_H */ 129