1 /*
2 * Copyright (c) 2021-2023 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 "core/common/container_scope.h"
17 #include "core/common/container_consts.h"
18
19 namespace OHOS::Ace {
20 namespace {
21 // preview not support multi-instance, always using default instance id 0.
22 #if defined(PREVIEW)
23 constexpr int32_t DEFAULT_ID = 0;
24 #else
25 constexpr int32_t DEFAULT_ID = INSTANCE_ID_UNDEFINED;
26 #endif
27
28 std::shared_mutex mutex_;
29 std::set<int32_t> containerSet_;
30 thread_local int32_t currentLocalId_(DEFAULT_ID);
31 thread_local int32_t currentId_(DEFAULT_ID);
32 std::atomic<int32_t> recentActiveId_(DEFAULT_ID);
33 std::atomic<int32_t> recentForegroundId_(DEFAULT_ID);
34 }
35
CurrentId()36 int32_t ContainerScope::CurrentId()
37 {
38 return currentId_;
39 }
40
UpdateLocalCurrent(int32_t id)41 void ContainerScope::UpdateLocalCurrent(int32_t id)
42 {
43 currentLocalId_ = id;
44 }
45
CurrentLocalId()46 int32_t ContainerScope::CurrentLocalId()
47 {
48 return currentLocalId_;
49 }
50
DefaultId()51 int32_t ContainerScope::DefaultId()
52 {
53 if (ContainerCount() > 0) {
54 std::shared_lock<std::shared_mutex> lock(mutex_);
55 return *containerSet_.rbegin();
56 }
57 return INSTANCE_ID_UNDEFINED;
58 }
59
SingletonId()60 int32_t ContainerScope::SingletonId()
61 {
62 if (ContainerCount() != 1) {
63 return INSTANCE_ID_UNDEFINED;
64 }
65 std::shared_lock<std::shared_mutex> lock(mutex_);
66 return *containerSet_.begin();
67 }
68
RecentActiveId()69 int32_t ContainerScope::RecentActiveId()
70 {
71 return recentActiveId_.load(std::memory_order_relaxed);
72 }
73
RecentForegroundId()74 int32_t ContainerScope::RecentForegroundId()
75 {
76 return recentForegroundId_.load(std::memory_order_relaxed);
77 }
78
CurrentIdWithReason()79 std::pair<int32_t, InstanceIdGenReason> ContainerScope::CurrentIdWithReason()
80 {
81 int32_t currentId = CurrentId();
82 if (currentId >= 0) {
83 return { currentId, InstanceIdGenReason::SCOPE };
84 }
85 uint32_t containerCount = ContainerCount();
86 if (containerCount == 0) {
87 return { INSTANCE_ID_UNDEFINED, InstanceIdGenReason::UNDEFINED };
88 }
89 if (containerCount == 1) {
90 return { SingletonId(), InstanceIdGenReason::SINGLETON };
91 }
92 currentId = ContainerScope::RecentActiveId();
93 if (currentId >= 0) {
94 return { currentId, InstanceIdGenReason::ACTIVE };
95 }
96 currentId = ContainerScope::RecentForegroundId();
97 if (currentId >= 0) {
98 return { currentId, InstanceIdGenReason::FOREGROUND };
99 }
100 return { ContainerScope::DefaultId(), InstanceIdGenReason::DEFAULT };
101 }
102
UpdateCurrent(int32_t id)103 void ContainerScope::UpdateCurrent(int32_t id)
104 {
105 currentId_ = id;
106 }
107
UpdateRecentActive(int32_t id)108 void ContainerScope::UpdateRecentActive(int32_t id)
109 {
110 recentActiveId_.store(id, std::memory_order_relaxed);
111 }
112
UpdateRecentForeground(int32_t id)113 void ContainerScope::UpdateRecentForeground(int32_t id)
114 {
115 recentForegroundId_.store(id, std::memory_order_relaxed);
116 }
117
ContainerCount()118 uint32_t ContainerScope::ContainerCount()
119 {
120 std::shared_lock<std::shared_mutex> lock(mutex_);
121 return static_cast<uint32_t>(containerSet_.size());
122 }
123
Add(int32_t id)124 void ContainerScope::Add(int32_t id)
125 {
126 std::unique_lock<std::shared_mutex> lock(mutex_);
127 containerSet_.emplace(id);
128 }
129
Remove(int32_t id)130 void ContainerScope::Remove(int32_t id)
131 {
132 std::unique_lock<std::shared_mutex> lock(mutex_);
133 containerSet_.erase(id);
134 }
135
RemoveAndCheck(int32_t id)136 void ContainerScope::RemoveAndCheck(int32_t id)
137 {
138 Remove(id);
139 if (RecentActiveId() == id) {
140 UpdateRecentActive(INSTANCE_ID_UNDEFINED);
141 }
142 if (RecentForegroundId() == id) {
143 UpdateRecentForeground(INSTANCE_ID_UNDEFINED);
144 }
145 }
146
147 } // namespace OHOS::Ace
148