1 /** 2 * Copyright (c) 2024-2025 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_TYPES_ETS_FINALIZABLE_WEAK_REF_LIST_H 16 #define PANDA_PLUGINS_ETS_RUNTIME_TYPES_ETS_FINALIZABLE_WEAK_REF_LIST_H 17 18 #include "plugins/ets/runtime/types/ets_object.h" 19 #include "plugins/ets/runtime/types/ets_finalizable_weak_ref.h" 20 21 namespace ark::ets { 22 23 class EtsFinalizableWeakRefList : protected EtsFinalizableWeakRef { 24 public: 25 using Node = EtsFinalizableWeakRef; 26 using List = EtsFinalizableWeakRefList; 27 Push(EtsCoroutine * coro,Node * weakRef)28 void Push(EtsCoroutine *coro, Node *weakRef) 29 { 30 ASSERT(weakRef != nullptr); 31 auto *head = GetHead(); 32 if (head == nullptr) { 33 SetHead(coro, weakRef); 34 return; 35 } 36 head->SetPrev(coro, weakRef); 37 weakRef->SetNext(coro, head); 38 SetHead(coro, weakRef); 39 } 40 Unlink(EtsCoroutine * coro,Node * weakRef)41 void Unlink(EtsCoroutine *coro, Node *weakRef) 42 { 43 ASSERT(weakRef != nullptr); 44 auto *prev = weakRef->GetPrev(); 45 auto *next = weakRef->GetNext(); 46 if (prev != nullptr) { 47 prev->SetNext(coro, next); 48 } 49 if (next != nullptr) { 50 next->SetPrev(coro, prev); 51 } 52 if (weakRef == GetHead()) { 53 SetHead(coro, next); 54 } 55 weakRef->SetPrev(coro, nullptr); 56 weakRef->SetNext(coro, nullptr); 57 } 58 UnlinkClearedReferences(EtsCoroutine * coro)59 void UnlinkClearedReferences(EtsCoroutine *coro) 60 { 61 auto *weakRef = GetHead(); 62 while (weakRef != nullptr) { 63 if (weakRef->GetReferent() == nullptr) { 64 // Finalizer of the cleared reference must be enqueued 65 ASSERT(weakRef->ReleaseFinalizer().IsEmpty()); 66 Unlink(coro, weakRef); 67 } 68 weakRef = weakRef->GetNext(); 69 } 70 } 71 FromCoreType(ObjectHeader * intrusiveList)72 static List *FromCoreType(ObjectHeader *intrusiveList) 73 { 74 return reinterpret_cast<List *>(intrusiveList); 75 } 76 GetCoreType()77 ObjectHeader *GetCoreType() 78 { 79 return reinterpret_cast<ObjectHeader *>(const_cast<EtsObject *>(AsObject())); 80 } 81 GetCoreType()82 const ObjectHeader *GetCoreType() const 83 { 84 return reinterpret_cast<const ObjectHeader *>(AsObject()); 85 } 86 AsObject()87 EtsObject *AsObject() 88 { 89 return this; 90 } 91 AsObject()92 const EtsObject *AsObject() const 93 { 94 return this; 95 } 96 FromEtsObject(EtsObject * intrusiveList)97 static List *FromEtsObject(EtsObject *intrusiveList) 98 { 99 return reinterpret_cast<List *>(intrusiveList); 100 } 101 TraverseAndFinalize()102 void TraverseAndFinalize() 103 { 104 auto *weakRef = GetHead(); 105 while (weakRef != nullptr) { 106 auto finalizer = weakRef->ReleaseFinalizer(); 107 if (!finalizer.IsEmpty()) { 108 finalizer.Run(); 109 } 110 weakRef = weakRef->GetNext(); 111 } 112 } 113 114 private: GetHead()115 Node *GetHead() const 116 { 117 ASSERT(GetPrev() == nullptr); 118 ASSERT(GetReferent() == nullptr); 119 return GetNext(); 120 } 121 SetHead(EtsCoroutine * coro,Node * weakRef)122 void SetHead(EtsCoroutine *coro, Node *weakRef) 123 { 124 ASSERT(GetPrev() == nullptr); 125 ASSERT(GetReferent() == nullptr); 126 return SetNext(coro, weakRef); 127 } 128 }; 129 130 static_assert(sizeof(EtsFinalizableWeakRefList) == sizeof(EtsFinalizableWeakRef)); 131 132 } // namespace ark::ets 133 134 #endif // PANDA_PLUGINS_ETS_RUNTIME_TYPES_ETS_FINALIZABLE_WEAK_REF_LIST_H 135