• 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_H
16 #define PANDA_RUNTIME_COROUTINES_THREADED_COROUTINE_H
17 
18 #include "runtime/coroutines/coroutine_context.h"
19 
20 namespace ark {
21 
22 /**
23  * @brief Native context of a coroutine. std::thread-based implementation.
24  *
25  * This implementation utilizes std::thread with condition variables and mutexes
26  * to emulate context switch on suspension.
27  *
28  */
29 class ThreadedCoroutineContext : public CoroutineContext {
30 public:
31     NO_COPY_SEMANTIC(ThreadedCoroutineContext);
32     NO_MOVE_SEMANTIC(ThreadedCoroutineContext);
33 
34     explicit ThreadedCoroutineContext() = default;
35     ~ThreadedCoroutineContext() override = default;
36 
37     /**
38      * Prepares the context (including the std::thread object creation) for execution, links it to the managed context
39      * part (Coroutine instance) and registers the created coroutine in the CoroutineManager (in the RUNNABLE status)
40      */
41     void AttachToCoroutine(Coroutine *co) override;
42     /**
43      * Manually destroys the context. Should be called by the Coroutine instance as a part of main coroutine
44      * destruction. All other coroutines and their contexts are destroyed by the CoroutineManager once the coroutine
45      * entrypoint execution finishes
46      */
47     void Destroy() override;
48 
CleanUp()49     void CleanUp() override {}
50 
51     bool RetrieveStackInfo(void *&stackAddr, size_t &stackSize, size_t &guardSize) override;
52 
53     /**
54      * Intended to be called from the context of a running thread that is going to be suspended.
55      * Changes status to Status::RUNNABLE or Status::BLOCKED, depending on the suspend
56      * reason. The next step for the caller thread is to call WaitUntilResumed() and block on it.
57      */
58     void RequestSuspend(bool getsBlocked) override;
59     /**
60      * Resume the suspended coroutine by setting status to Status::RUNNING.
61      * Wakes up the thread that is blocked on WaitUntilResumed()
62      */
63     void RequestResume() override;
64     /// Unblock the coroutine and set its status to Status::RUNNABLE
65     void RequestUnblock() override;
66 
67     /**
68      * Intended to be called from the context of a running coroutine that is going to
69      * launch a new one. Blocks until the created coroutine passes the init sequence.
70      */
71     void WaitUntilInitialized();
72     /// Blocks until the coroutine becomes running
73     void WaitUntilResumed();
74     /// Moves the main coroutine to Status::TERMINATING
75     void MainThreadFinished();
76     /// Moves the main coroutine to Status::AWAIT_LOOP
77     void EnterAwaitLoop();
78 
79     Coroutine::Status GetStatus() const override;
80 
81 protected:
82     void SetStatus(Coroutine::Status newStatus) override;
83     os::thread::NativeHandleType GetCoroutineNativeHandle();
84     void SetCoroutineNativeHandle(os::thread::NativeHandleType h);
85 
86 private:
87     /// std::thread's body
88     static void ThreadProc(ThreadedCoroutineContext *ctx);
89     /**
90      * Notify the waiters that the coroutine has finished its initialization sequence.
91      * Unblocks the thread waiting on the WaitUntilInitialized()
92      */
93     void InitializationDone();
94 
95     os::memory::ConditionVariable cv_;
96     os::memory::Mutex cvMutex_;
97     os::thread::NativeHandleType nativeHandle_ {};
98 
99     std::atomic<Coroutine::Status> status_ {Coroutine::Status::CREATED};
100 };
101 
102 }  // namespace ark
103 
104 #endif  // PANDA_RUNTIME_COROUTINES_THREADED_COROUTINE_H
105