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_PLUGINS_ETS_RUNTIME_ETS_COROUTINE_H 16 #define PANDA_PLUGINS_ETS_RUNTIME_ETS_COROUTINE_H 17 18 #include "runtime/coroutines/coroutine_context.h" 19 #include "plugins/ets/runtime/ets_napi_env.h" 20 #include "runtime/coroutines/coroutine.h" 21 #include "runtime/coroutines/coroutine_manager.h" 22 #include "runtime/coroutines/coro_callback_queue.h" 23 24 namespace ark::ets { 25 class PandaEtsVM; 26 27 /// @brief The eTS coroutine. It is aware of the native interface and reference storage existance. 28 class EtsCoroutine : public Coroutine { 29 public: 30 NO_COPY_SEMANTIC(EtsCoroutine); 31 NO_MOVE_SEMANTIC(EtsCoroutine); 32 33 /** 34 * @brief EtsCoroutine factory: the preferrable way to create a coroutine. See CoroutineManager::CoroutineFactory 35 * for details. 36 * 37 * Since C++ requires function type to exactly match the formal parameter type, we have to make this factory a 38 * template. The sole purpose for this is to be able to return both Coroutine* and EtsCoroutine* 39 */ 40 template <class T> 41 static T *Create(Runtime *runtime, PandaVM *vm, PandaString name, CoroutineContext *context, 42 std::optional<EntrypointInfo> &&epInfo = std::nullopt) 43 { 44 mem::InternalAllocatorPtr allocator = runtime->GetInternalAllocator(); 45 auto *callbackQueue = allocator->New<CoroCallbackQueue>(); 46 auto co = allocator->New<EtsCoroutine>(os::thread::GetCurrentThreadId(), allocator, vm, std::move(name), 47 context, callbackQueue, std::move(epInfo)); 48 co->Initialize(); 49 return co; 50 } 51 ~EtsCoroutine() override = default; 52 CastFromThread(Thread * thread)53 static EtsCoroutine *CastFromThread(Thread *thread) 54 { 55 ASSERT(thread != nullptr); 56 return static_cast<EtsCoroutine *>(thread); 57 } 58 GetCurrent()59 static EtsCoroutine *GetCurrent() 60 { 61 Coroutine *co = Coroutine::GetCurrent(); 62 if ((co != nullptr) && co->GetThreadLang() == ark::panda_file::SourceLang::ETS) { 63 return CastFromThread(co); 64 } 65 return nullptr; 66 } 67 SetPromiseClass(void * promiseClass)68 void SetPromiseClass(void *promiseClass) 69 { 70 promiseClassPtr_ = promiseClass; 71 } 72 GetTlsPromiseClassPointerOffset()73 static constexpr uint32_t GetTlsPromiseClassPointerOffset() 74 { 75 return MEMBER_OFFSET(EtsCoroutine, promiseClassPtr_); 76 } 77 GetUndefinedObject()78 ALWAYS_INLINE ObjectHeader *GetUndefinedObject() const 79 { 80 return undefinedObj_; 81 } 82 83 // For mainthread initializer SetUndefinedObject(ObjectHeader * obj)84 void SetUndefinedObject(ObjectHeader *obj) 85 { 86 undefinedObj_ = obj; 87 } 88 GetTlsUndefinedObjectOffset()89 static constexpr uint32_t GetTlsUndefinedObjectOffset() 90 { 91 return MEMBER_OFFSET(EtsCoroutine, undefinedObj_); 92 } 93 94 PANDA_PUBLIC_API PandaEtsVM *GetPandaVM() const; 95 PANDA_PUBLIC_API CoroutineManager *GetCoroutineManager() const; 96 GetEtsNapiEnv()97 PandaEtsNapiEnv *GetEtsNapiEnv() const 98 { 99 return etsNapiEnv_.get(); 100 } 101 102 void Initialize() override; 103 void RequestCompletion(Value returnValue) override; 104 void FreeInternalMemory() override; 105 106 protected: 107 // we would like everyone to use the factory to create a EtsCoroutine 108 explicit EtsCoroutine(ThreadId id, mem::InternalAllocatorPtr allocator, PandaVM *vm, PandaString name, 109 CoroutineContext *context, CallbackQueue *queue, std::optional<EntrypointInfo> &&epInfo); 110 111 private: 112 panda_file::Type GetReturnType(); 113 EtsObject *GetReturnValueAsObject(panda_file::Type returnType, Value returnValue); 114 EtsObject *GetValueFromPromiseSync(EtsPromise *promise); 115 116 std::unique_ptr<PandaEtsNapiEnv> etsNapiEnv_; 117 void *promiseClassPtr_ {nullptr}; 118 119 ObjectHeader *undefinedObj_ {}; 120 121 // Allocator calls our protected ctor 122 friend class mem::Allocator; 123 }; 124 } // namespace ark::ets 125 126 #endif // PANDA_PLUGINS_ETS_RUNTIME_ETS_COROUTINE_H 127