1/*
2 * Copyright (c) 2021-2022 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#include "singleton_container.h"
17#include <mutex>
18#include "window_manager_hilog.h"
19
20namespace OHOS {
21namespace Rosen {
22namespace {
23constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "SingletonContainer"};
24} // namespace
25WM_IMPLEMENT_SINGLE_INSTANCE(SingletonContainer)
26
27SingletonContainer::~SingletonContainer()
28{
29    destroyed_ = true;
30    while (singletonMap.empty() == false) {
31        auto it = singletonMap.begin();
32        while (it != singletonMap.end()) {
33            if (it->second.refCount > 0) {
34                it++;
35                continue;
36            }
37
38            if (dependencySetMap.find(it->first) != dependencySetMap.end()) {
39                for (auto mid : dependencySetMap[it->first]) {
40                    singletonMap[mid].refCount--;
41                }
42                dependencySetMap.erase(it->first);
43            }
44
45            for (const auto &[k, v] : stringMap) {
46                if (v == it->first) {
47                    WLOGFD("remove %{public}s", k.c_str());
48                    break;
49                }
50            }
51            singletonMap.erase(it++);
52        }
53    }
54}
55
56void SingletonContainer::AddSingleton(const std::string& name, void* instance)
57{
58    if (stringMap.find(name) == stringMap.end()) {
59        static int32_t nextId = 0;
60        singletonMap[nextId].value = instance;
61        singletonMap[nextId].refCount = 0;
62        WLOGD("add %{public}s", name.c_str());
63        stringMap[name] = nextId++;
64    } else {
65        WLOGFE("add failed: %{public}s", name.c_str());
66    }
67}
68
69void SingletonContainer::SetSingleton(const std::string& name, void* instance)
70{
71    if (stringMap.find(name) == stringMap.end()) {
72        AddSingleton(name, instance);
73    } else {
74        WLOGI("set %{public}s", name.c_str());
75        singletonMap[stringMap[name]].value = instance;
76    }
77}
78
79void* SingletonContainer::GetSingleton(const std::string& name)
80{
81    if (stringMap.find(name) == stringMap.end()) {
82        WLOGFE("can not get %{public}s", name.c_str());
83        return nullptr;
84    }
85    if (singletonMap.find(stringMap[name]) == singletonMap.end()) {
86        WLOGFE("can not find singleton, name is %{public}s", name.c_str());
87        return nullptr;
88    }
89    return singletonMap[stringMap[name]].value;
90}
91
92void* SingletonContainer::DependOn(const std::string& instance, const std::string& name)
93{
94    auto& instanceDependencySet = dependencySetMap[stringMap[instance]];
95    if (instanceDependencySet.find(stringMap[name]) == instanceDependencySet.end()) {
96        WLOGFD("%{public}s DependOn %{public}s", instance.c_str(), name.c_str());
97        instanceDependencySet.insert(stringMap[name]);
98        singletonMap[stringMap[name]].refCount++;
99    }
100    return GetSingleton(name);
101}
102} // namespace Rosen
103} // namespace OHOS
104