• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 
16 #ifndef ECMASCRIPT_MODULE_MANAGER_MAP_H
17 #define ECMASCRIPT_MODULE_MANAGER_MAP_H
18 
19 #include <optional>
20 #include "ecmascript/mem/gc_root.h"
21 #include "ecmascript/mem/c_containers.h"
22 
23 namespace panda::ecmascript {
24 /**
25  * A concurrent-safe hash map for use as a GC root container.
26  * All stored values are wrapped in GCRoot with CMCGC.
27  *
28  * Safe for concurrent access between GC threads and mutator threads
29  *
30  * IMPORTANT: Do not attempt to cache iterators or references outside
31  * of the provided interface - they can become invalid after the lock is released.
32  */
33 template <class Key, class Hash = std::hash<Key>, class KeyEqual = std::equal_to<Key>>
34 class ModuleManagerMap {
35     using UnderlyingMap = CUnorderedMap<Key, GCRoot, Hash, KeyEqual>;
36     mutable std::mutex lock_;
37     // Underlying storage with GCRoot values
38     UnderlyingMap map_;
39 
40 public:
41     /**
42      * Inserts or updates a key-value pair.
43      * If the key already exists, replaces the existing value.
44      */
Insert(const Key & key,JSTaggedValue value)45     void Insert(const Key &key, JSTaggedValue value)
46     {
47         std::lock_guard<std::mutex> lock(lock_);
48         map_[key] = GCRoot(value);
49     }
50 
51     /**
52      * Inserts a key-value pair only if the key doesn't exist.
53      * If the key already exists, the operation is a no-op.
54      * The try_emplace ensure a GCRoot constructor is only trigger
55      * if the insertion actually happen
56      *
57      * Note: Returns bool instead of <iterator,bool> for thread safety.
58      * Exposing iterators would be unsafe as they become invalid
59      * once the lock is released.
60      */
61     template <typename K>
Emplace(const K & key,JSTaggedValue value)62     bool Emplace(const K &key, JSTaggedValue value)
63     {
64         std::lock_guard<std::mutex> lock(lock_);
65         return map_.try_emplace(key, value).second;
66     }
67 
68     /**
69      * Safely retrieves a value by key with readbarrier.
70      *
71      * The returned value is obtained via GCRoot::Read(), ensuring proper
72      * read barriers are applied for concurrent GC safety. The value is
73      * returned by copy to avoid dangling references after lock release.
74      */
75     template <typename K>
Find(const K & key)76     std::optional<JSTaggedValue> Find(const K &key)
77     {
78         std::lock_guard<std::mutex> lock(lock_);
79         auto it = map_.find(key);
80         return it == map_.end() ? std::nullopt : std::make_optional(it->second.Read());
81     }
82 
83     /**
84      * Applies a function to each key-value pair while holding the lock.
85      */
86     template <typename Func>
ForEach(Func && fn)87     void ForEach(Func &&fn)
88     {
89         std::lock_guard<std::mutex> lock(lock_);
90         for (auto it = map_.begin(); it != map_.end(); ++it) {
91             fn(it);
92         }
93     }
94 
Erase(const Key & key)95     void Erase(const Key &key)
96     {
97         std::lock_guard<std::mutex> lock(lock_);
98         map_.erase(key);
99     }
100 
Size()101     size_t Size() const
102     {
103         std::lock_guard<std::mutex> lock(lock_);
104         return map_.size();
105     }
106 
Clear()107     void Clear()
108     {
109         std::lock_guard<std::mutex> lock(lock_);
110         map_.clear();
111     }
112 };
113 
114 }  // namespace panda::ecmascript
115 #endif
116