• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2023-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_COROUTINE_EVENTS_H
16 #define PANDA_RUNTIME_COROUTINES_COROUTINE_EVENTS_H
17 
18 #include "runtime/include/runtime.h"
19 #include "runtime/mem/refstorage/reference.h"
20 
21 namespace ark {
22 
23 class CoroutineManager;
24 
25 /**
26  * @brief The base class for coroutine events. Cannot be instantiated directly.
27  *
28  * These events are used to implement blocking and unblocking the coroutines that are waiting for something.
29  * The lifetime of an event is intended to be managed manually or be bound to its owner lifetime (e.g. coroutine).
30  */
31 class CAPABILITY("mutex") CoroutineEvent {
32 public:
33     NO_COPY_SEMANTIC(CoroutineEvent);
34     NO_MOVE_SEMANTIC(CoroutineEvent);
35 
36     enum class Type { NONE, GENERIC, COMPLETION, CHANNEL, IO };
37 
~CoroutineEvent()38     virtual ~CoroutineEvent()
39     {
40         if (IsLocked()) {
41             Unlock();
42         }
43         Runtime::GetCurrent()->GetInternalAllocator()->Delete(mutex_);
44     };
45 
GetType()46     Type GetType()
47     {
48         return type_;
49     }
50 
Happened()51     bool Happened() REQUIRES(this)
52     {
53         return happened_;
54     }
55 
56     /// Set event happened and unblock waiters
57     void Happen();
58 
SetNotHappened()59     void SetNotHappened()
60     {
61         Lock();
62         happened_ = false;
63         Unlock();
64     }
65 
Lock()66     void Lock() ACQUIRE()
67     {
68         mutex_->Lock();
69         locked_ = true;
70     }
71 
Unlock()72     void Unlock() RELEASE()
73     {
74         locked_ = false;
75         mutex_->Unlock();
76     }
77 
78 protected:
CoroutineEvent(Type t,CoroutineManager * coroManager)79     explicit CoroutineEvent(Type t, CoroutineManager *coroManager) : type_(t), coroManager_(coroManager)
80     {
81         mutex_ = Runtime::GetCurrent()->GetInternalAllocator()->New<os::memory::Mutex>();
82     }
83 
IsLocked()84     bool IsLocked()
85     {
86         return locked_;
87     }
88 
SetHappened()89     void SetHappened()
90     {
91         Lock();
92         happened_ = true;
93         Unlock();
94     }
95 
96 private:
97     Type type_ = Type::NONE;
98     bool happened_ GUARDED_BY(this) = false;
99     bool locked_ = false;
100     CoroutineManager *coroManager_ = nullptr;
101 
102     os::memory::Mutex *mutex_;
103 };
104 
105 /**
106  * @brief The generic event: just some  event that can be awaited.
107  *
108  * The only thing that it can do: it can happen.
109  */
110 class GenericEvent : public CoroutineEvent {
111 public:
112     NO_COPY_SEMANTIC(GenericEvent);
113     NO_MOVE_SEMANTIC(GenericEvent);
114 
GenericEvent(CoroutineManager * coroManager)115     explicit GenericEvent(CoroutineManager *coroManager) : CoroutineEvent(Type::GENERIC, coroManager) {}
116     ~GenericEvent() override = default;
117 
118 private:
119 };
120 
121 /// @brief The coroutine completion event: happens when coroutine is done executing its bytecode.
122 class CompletionEvent : public CoroutineEvent {
123 public:
124     NO_COPY_SEMANTIC(CompletionEvent);
125     NO_MOVE_SEMANTIC(CompletionEvent);
126 
127     /**
128      * @param promise A weak reference (from global storage) to the language-dependent promise object that will hold
129      * the coroutine return value.
130      */
CompletionEvent(mem::Reference * promise,CoroutineManager * coroManager)131     explicit CompletionEvent(mem::Reference *promise, CoroutineManager *coroManager)
132         : CoroutineEvent(Type::COMPLETION, coroManager), promise_(promise)
133     {
134     }
135     ~CompletionEvent() override = default;
136 
ReleasePromise()137     mem::Reference *ReleasePromise()
138     {
139         return std::exchange(promise_, nullptr);
140     }
141 
SetPromise(mem::Reference * promise)142     void SetPromise(mem::Reference *promise)
143     {
144         ASSERT(promise_ == nullptr);
145         promise_ = promise;
146     }
147 
148 private:
149     mem::Reference *promise_ = nullptr;
150 };
151 
152 }  // namespace ark
153 
154 #endif /* PANDA_RUNTIME_COROUTINES_COROUTINE_EVENTS_H */