• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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