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