122736c2fSopenharmony_ci/* 222736c2fSopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 322736c2fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 422736c2fSopenharmony_ci * you may not use this file except in compliance with the License. 522736c2fSopenharmony_ci * You may obtain a copy of the License at 622736c2fSopenharmony_ci * 722736c2fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 822736c2fSopenharmony_ci * 922736c2fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1022736c2fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1122736c2fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1222736c2fSopenharmony_ci * See the License for the specific language governing permissions and 1322736c2fSopenharmony_ci * limitations under the License. 1422736c2fSopenharmony_ci */ 1522736c2fSopenharmony_ci 1622736c2fSopenharmony_ci#ifndef OHOS_INPUTMETHOD_IMF_FRAMEWORKS_COMMON_CONCURRENT_MAP_H 1722736c2fSopenharmony_ci#define OHOS_INPUTMETHOD_IMF_FRAMEWORKS_COMMON_CONCURRENT_MAP_H 1822736c2fSopenharmony_ci#include <functional> 1922736c2fSopenharmony_ci#include <map> 2022736c2fSopenharmony_ci#include <mutex> 2122736c2fSopenharmony_cinamespace OHOS { 2222736c2fSopenharmony_citemplate<typename _Key, typename _Tp> 2322736c2fSopenharmony_ciclass ConcurrentMap { 2422736c2fSopenharmony_ci template<typename _First, typename... _Rest> 2522736c2fSopenharmony_ci static _First First(); 2622736c2fSopenharmony_ci 2722736c2fSopenharmony_cipublic: 2822736c2fSopenharmony_ci using map_type = typename std::map<_Key, _Tp>; 2922736c2fSopenharmony_ci using filter_type = typename std::function<bool(map_type &)>; 3022736c2fSopenharmony_ci using key_type = typename std::map<_Key, _Tp>::key_type; 3122736c2fSopenharmony_ci using mapped_type = typename std::map<_Key, _Tp>::mapped_type; 3222736c2fSopenharmony_ci using value_type = typename std::map<_Key, _Tp>::value_type; 3322736c2fSopenharmony_ci using size_type = typename std::map<_Key, _Tp>::size_type; 3422736c2fSopenharmony_ci using reference = typename std::map<_Key, _Tp>::reference; 3522736c2fSopenharmony_ci using const_reference = typename std::map<_Key, _Tp>::const_reference; 3622736c2fSopenharmony_ci 3722736c2fSopenharmony_ci ConcurrentMap() = default; 3822736c2fSopenharmony_ci ~ConcurrentMap() 3922736c2fSopenharmony_ci { 4022736c2fSopenharmony_ci Clear(); 4122736c2fSopenharmony_ci } 4222736c2fSopenharmony_ci 4322736c2fSopenharmony_ci ConcurrentMap(const ConcurrentMap &other) 4422736c2fSopenharmony_ci { 4522736c2fSopenharmony_ci operator=(std::move(other)); 4622736c2fSopenharmony_ci } 4722736c2fSopenharmony_ci 4822736c2fSopenharmony_ci ConcurrentMap &operator=(const ConcurrentMap &other) noexcept 4922736c2fSopenharmony_ci { 5022736c2fSopenharmony_ci if (this == &other) { 5122736c2fSopenharmony_ci return *this; 5222736c2fSopenharmony_ci } 5322736c2fSopenharmony_ci auto tmp = other.Clone(); 5422736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 5522736c2fSopenharmony_ci entries_ = std::move(tmp); 5622736c2fSopenharmony_ci return *this; 5722736c2fSopenharmony_ci } 5822736c2fSopenharmony_ci 5922736c2fSopenharmony_ci ConcurrentMap(ConcurrentMap &&other) noexcept 6022736c2fSopenharmony_ci { 6122736c2fSopenharmony_ci operator=(std::move(other)); 6222736c2fSopenharmony_ci } 6322736c2fSopenharmony_ci 6422736c2fSopenharmony_ci ConcurrentMap &operator=(ConcurrentMap &&other) noexcept 6522736c2fSopenharmony_ci { 6622736c2fSopenharmony_ci if (this == &other) { 6722736c2fSopenharmony_ci return *this; 6822736c2fSopenharmony_ci } 6922736c2fSopenharmony_ci auto tmp = other.Steal(); 7022736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 7122736c2fSopenharmony_ci entries_ = std::move(tmp); 7222736c2fSopenharmony_ci return *this; 7322736c2fSopenharmony_ci } 7422736c2fSopenharmony_ci 7522736c2fSopenharmony_ci bool Emplace() noexcept 7622736c2fSopenharmony_ci { 7722736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 7822736c2fSopenharmony_ci auto it = entries_.emplace(); 7922736c2fSopenharmony_ci return it.second; 8022736c2fSopenharmony_ci } 8122736c2fSopenharmony_ci 8222736c2fSopenharmony_ci template<typename... _Args> 8322736c2fSopenharmony_ci typename std::enable_if<!std::is_convertible_v<decltype(First<_Args...>()), filter_type>, bool>::type Emplace( 8422736c2fSopenharmony_ci _Args &&...args) noexcept 8522736c2fSopenharmony_ci { 8622736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 8722736c2fSopenharmony_ci auto it = entries_.emplace(std::forward<_Args>(args)...); 8822736c2fSopenharmony_ci return it.second; 8922736c2fSopenharmony_ci } 9022736c2fSopenharmony_ci 9122736c2fSopenharmony_ci template<typename _Filter, typename... _Args> 9222736c2fSopenharmony_ci typename std::enable_if<std::is_convertible_v<_Filter, filter_type>, bool>::type Emplace(const _Filter &filter, 9322736c2fSopenharmony_ci _Args &&...args) noexcept 9422736c2fSopenharmony_ci { 9522736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 9622736c2fSopenharmony_ci if (!filter(entries_)) { 9722736c2fSopenharmony_ci return false; 9822736c2fSopenharmony_ci } 9922736c2fSopenharmony_ci auto it = entries_.emplace(std::forward<_Args>(args)...); 10022736c2fSopenharmony_ci return it.second; 10122736c2fSopenharmony_ci } 10222736c2fSopenharmony_ci 10322736c2fSopenharmony_ci std::pair<bool, mapped_type> Find(const key_type &key) const noexcept 10422736c2fSopenharmony_ci { 10522736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 10622736c2fSopenharmony_ci auto it = entries_.find(key); 10722736c2fSopenharmony_ci if (it == entries_.end()) { 10822736c2fSopenharmony_ci return std::pair{ false, mapped_type() }; 10922736c2fSopenharmony_ci } 11022736c2fSopenharmony_ci 11122736c2fSopenharmony_ci return std::pair{ true, it->second }; 11222736c2fSopenharmony_ci } 11322736c2fSopenharmony_ci 11422736c2fSopenharmony_ci bool Contains(const key_type &key) const noexcept 11522736c2fSopenharmony_ci { 11622736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 11722736c2fSopenharmony_ci return (entries_.find(key) != entries_.end()); 11822736c2fSopenharmony_ci } 11922736c2fSopenharmony_ci 12022736c2fSopenharmony_ci template<typename _Obj> 12122736c2fSopenharmony_ci bool InsertOrAssign(const key_type &key, _Obj &&obj) noexcept 12222736c2fSopenharmony_ci { 12322736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 12422736c2fSopenharmony_ci auto it = entries_.insert_or_assign(key, std::forward<_Obj>(obj)); 12522736c2fSopenharmony_ci return it.second; 12622736c2fSopenharmony_ci } 12722736c2fSopenharmony_ci 12822736c2fSopenharmony_ci bool Insert(const key_type &key, const mapped_type &value) noexcept 12922736c2fSopenharmony_ci { 13022736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 13122736c2fSopenharmony_ci auto it = entries_.insert(value_type{ key, value }); 13222736c2fSopenharmony_ci return it.second; 13322736c2fSopenharmony_ci } 13422736c2fSopenharmony_ci 13522736c2fSopenharmony_ci size_type Erase(const key_type &key) noexcept 13622736c2fSopenharmony_ci { 13722736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 13822736c2fSopenharmony_ci return entries_.erase(key); 13922736c2fSopenharmony_ci } 14022736c2fSopenharmony_ci 14122736c2fSopenharmony_ci void Clear() noexcept 14222736c2fSopenharmony_ci { 14322736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 14422736c2fSopenharmony_ci return entries_.clear(); 14522736c2fSopenharmony_ci } 14622736c2fSopenharmony_ci 14722736c2fSopenharmony_ci bool Empty() const noexcept 14822736c2fSopenharmony_ci { 14922736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 15022736c2fSopenharmony_ci return entries_.empty(); 15122736c2fSopenharmony_ci } 15222736c2fSopenharmony_ci 15322736c2fSopenharmony_ci size_type Size() const noexcept 15422736c2fSopenharmony_ci { 15522736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 15622736c2fSopenharmony_ci return entries_.size(); 15722736c2fSopenharmony_ci } 15822736c2fSopenharmony_ci 15922736c2fSopenharmony_ci // The action`s return true means meeting the erase condition 16022736c2fSopenharmony_ci // The action`s return false means not meeting the erase condition 16122736c2fSopenharmony_ci size_type EraseIf(const std::function<bool(const key_type &key, mapped_type &value)> &action) noexcept 16222736c2fSopenharmony_ci { 16322736c2fSopenharmony_ci if (action == nullptr) { 16422736c2fSopenharmony_ci return 0; 16522736c2fSopenharmony_ci } 16622736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 16722736c2fSopenharmony_ci#if __cplusplus > 201703L 16822736c2fSopenharmony_ci auto count = std::erase_if(entries_, 16922736c2fSopenharmony_ci [&action](value_type &value) -> bool { return action(value.first, value.second); }); 17022736c2fSopenharmony_ci#else 17122736c2fSopenharmony_ci auto count = entries_.size(); 17222736c2fSopenharmony_ci for (auto it = entries_.begin(); it != entries_.end();) { 17322736c2fSopenharmony_ci if (action((*it).first, (*it).second)) { 17422736c2fSopenharmony_ci it = entries_.erase(it); 17522736c2fSopenharmony_ci } else { 17622736c2fSopenharmony_ci ++it; 17722736c2fSopenharmony_ci } 17822736c2fSopenharmony_ci } 17922736c2fSopenharmony_ci count -= entries_.size(); 18022736c2fSopenharmony_ci#endif 18122736c2fSopenharmony_ci return count; 18222736c2fSopenharmony_ci } 18322736c2fSopenharmony_ci 18422736c2fSopenharmony_ci void ForEach(const std::function<bool(const key_type &, mapped_type &)> &action) 18522736c2fSopenharmony_ci { 18622736c2fSopenharmony_ci if (action == nullptr) { 18722736c2fSopenharmony_ci return; 18822736c2fSopenharmony_ci } 18922736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 19022736c2fSopenharmony_ci for (auto &[key, value] : entries_) { 19122736c2fSopenharmony_ci if (action(key, value)) { 19222736c2fSopenharmony_ci break; 19322736c2fSopenharmony_ci } 19422736c2fSopenharmony_ci } 19522736c2fSopenharmony_ci } 19622736c2fSopenharmony_ci 19722736c2fSopenharmony_ci void ForEachCopies(const std::function<bool(const key_type &, mapped_type &)> &action) 19822736c2fSopenharmony_ci { 19922736c2fSopenharmony_ci if (action == nullptr) { 20022736c2fSopenharmony_ci return; 20122736c2fSopenharmony_ci } 20222736c2fSopenharmony_ci auto entries = Clone(); 20322736c2fSopenharmony_ci for (auto &[key, value] : entries) { 20422736c2fSopenharmony_ci if (action(key, value)) { 20522736c2fSopenharmony_ci break; 20622736c2fSopenharmony_ci } 20722736c2fSopenharmony_ci } 20822736c2fSopenharmony_ci } 20922736c2fSopenharmony_ci 21022736c2fSopenharmony_ci // The action's return value means that the element is keep in map or not; true means keeping, false means removing. 21122736c2fSopenharmony_ci bool Compute(const key_type &key, const std::function<bool(const key_type &, mapped_type &)> &action) 21222736c2fSopenharmony_ci { 21322736c2fSopenharmony_ci if (action == nullptr) { 21422736c2fSopenharmony_ci return false; 21522736c2fSopenharmony_ci } 21622736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 21722736c2fSopenharmony_ci auto it = entries_.find(key); 21822736c2fSopenharmony_ci if (it == entries_.end()) { 21922736c2fSopenharmony_ci auto result = entries_.emplace(key, mapped_type()); 22022736c2fSopenharmony_ci it = result.second ? result.first : entries_.end(); 22122736c2fSopenharmony_ci } 22222736c2fSopenharmony_ci if (it == entries_.end()) { 22322736c2fSopenharmony_ci return false; 22422736c2fSopenharmony_ci } 22522736c2fSopenharmony_ci if (!action(it->first, it->second)) { 22622736c2fSopenharmony_ci entries_.erase(key); 22722736c2fSopenharmony_ci } 22822736c2fSopenharmony_ci return true; 22922736c2fSopenharmony_ci } 23022736c2fSopenharmony_ci 23122736c2fSopenharmony_ci // The action's return value means that the element is keep in map or not; true means keeping, false means removing. 23222736c2fSopenharmony_ci bool ComputeIfPresent(const key_type &key, const std::function<bool(const key_type &, mapped_type &)> &action) 23322736c2fSopenharmony_ci { 23422736c2fSopenharmony_ci if (action == nullptr) { 23522736c2fSopenharmony_ci return false; 23622736c2fSopenharmony_ci } 23722736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 23822736c2fSopenharmony_ci auto it = entries_.find(key); 23922736c2fSopenharmony_ci if (it == entries_.end()) { 24022736c2fSopenharmony_ci return false; 24122736c2fSopenharmony_ci } 24222736c2fSopenharmony_ci if (!action(key, it->second)) { 24322736c2fSopenharmony_ci entries_.erase(key); 24422736c2fSopenharmony_ci } 24522736c2fSopenharmony_ci return true; 24622736c2fSopenharmony_ci } 24722736c2fSopenharmony_ci 24822736c2fSopenharmony_ci bool ComputeIfAbsent(const key_type &key, const std::function<mapped_type(const key_type &)> &action) 24922736c2fSopenharmony_ci { 25022736c2fSopenharmony_ci if (action == nullptr) { 25122736c2fSopenharmony_ci return false; 25222736c2fSopenharmony_ci } 25322736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 25422736c2fSopenharmony_ci auto it = entries_.find(key); 25522736c2fSopenharmony_ci if (it != entries_.end()) { 25622736c2fSopenharmony_ci return false; 25722736c2fSopenharmony_ci } 25822736c2fSopenharmony_ci entries_.emplace(key, action(key)); 25922736c2fSopenharmony_ci return true; 26022736c2fSopenharmony_ci } 26122736c2fSopenharmony_ci 26222736c2fSopenharmony_ci bool ComputeIfAbsent(const key_type &key, const std::function<bool(const key_type &, mapped_type &)> &action) 26322736c2fSopenharmony_ci { 26422736c2fSopenharmony_ci if (action == nullptr) { 26522736c2fSopenharmony_ci return false; 26622736c2fSopenharmony_ci } 26722736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 26822736c2fSopenharmony_ci auto it = entries_.find(key); 26922736c2fSopenharmony_ci if (it != entries_.end()) { 27022736c2fSopenharmony_ci return false; 27122736c2fSopenharmony_ci } 27222736c2fSopenharmony_ci auto result = entries_.emplace(key, mapped_type()); 27322736c2fSopenharmony_ci it = result.second ? result.first : entries_.end(); 27422736c2fSopenharmony_ci if (it == entries_.end()) { 27522736c2fSopenharmony_ci return false; 27622736c2fSopenharmony_ci } 27722736c2fSopenharmony_ci if (!action(it->first, it->second)) { 27822736c2fSopenharmony_ci entries_.erase(key); 27922736c2fSopenharmony_ci return false; 28022736c2fSopenharmony_ci } 28122736c2fSopenharmony_ci return true; 28222736c2fSopenharmony_ci } 28322736c2fSopenharmony_ci 28422736c2fSopenharmony_ciprivate: 28522736c2fSopenharmony_ci std::map<_Key, _Tp> Steal() noexcept 28622736c2fSopenharmony_ci { 28722736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 28822736c2fSopenharmony_ci return std::move(entries_); 28922736c2fSopenharmony_ci } 29022736c2fSopenharmony_ci 29122736c2fSopenharmony_ci std::map<_Key, _Tp> Clone() const noexcept 29222736c2fSopenharmony_ci { 29322736c2fSopenharmony_ci std::lock_guard<decltype(mutex_)> lock(mutex_); 29422736c2fSopenharmony_ci return entries_; 29522736c2fSopenharmony_ci } 29622736c2fSopenharmony_ci 29722736c2fSopenharmony_ciprivate: 29822736c2fSopenharmony_ci mutable std::recursive_mutex mutex_; 29922736c2fSopenharmony_ci std::map<_Key, _Tp> entries_; 30022736c2fSopenharmony_ci}; 30122736c2fSopenharmony_ci} // namespace OHOS 30222736c2fSopenharmony_ci#endif // OHOS_INPUTMETHOD_IMF_FRAMEWORKS_COMMON_CONCURRENT_MAP_H 303