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