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 currentId_(DEFAULT_ID);
31  std::atomic<int32_t> recentActiveId_(DEFAULT_ID);
32  std::atomic<int32_t> recentForegroundId_(DEFAULT_ID);
33  }
34  
CurrentId()35  int32_t ContainerScope::CurrentId()
36  {
37      return currentId_;
38  }
39  
DefaultId()40  int32_t ContainerScope::DefaultId()
41  {
42      if (ContainerCount() > 0) {
43          std::shared_lock<std::shared_mutex> lock(mutex_);
44          return *containerSet_.rbegin();
45      }
46      return INSTANCE_ID_UNDEFINED;
47  }
48  
SingletonId()49  int32_t ContainerScope::SingletonId()
50  {
51      if (ContainerCount() != 1) {
52          return INSTANCE_ID_UNDEFINED;
53      }
54      std::shared_lock<std::shared_mutex> lock(mutex_);
55      return *containerSet_.begin();
56  }
57  
RecentActiveId()58  int32_t ContainerScope::RecentActiveId()
59  {
60      return recentActiveId_.load(std::memory_order_relaxed);
61  }
62  
RecentForegroundId()63  int32_t ContainerScope::RecentForegroundId()
64  {
65      return recentForegroundId_.load(std::memory_order_relaxed);
66  }
67  
CurrentIdWithReason()68  std::pair<int32_t, InstanceIdGenReason> ContainerScope::CurrentIdWithReason()
69  {
70      int32_t currentId = CurrentId();
71      if (currentId >= 0) {
72          return { currentId, InstanceIdGenReason::SCOPE };
73      }
74      uint32_t containerCount = ContainerCount();
75      if (containerCount == 0) {
76          return { INSTANCE_ID_UNDEFINED, InstanceIdGenReason::UNDEFINED };
77      }
78      if (containerCount == 1) {
79          return { SingletonId(), InstanceIdGenReason::SINGLETON };
80      }
81      currentId = ContainerScope::RecentActiveId();
82      if (currentId >= 0) {
83          return { currentId, InstanceIdGenReason::ACTIVE };
84      }
85      currentId = ContainerScope::RecentForegroundId();
86      if (currentId >= 0) {
87          return { currentId, InstanceIdGenReason::FOREGROUND };
88      }
89      return { ContainerScope::DefaultId(), InstanceIdGenReason::DEFAULT };
90  }
91  
UpdateCurrent(int32_t id)92  void ContainerScope::UpdateCurrent(int32_t id)
93  {
94      currentId_ = id;
95  }
96  
UpdateRecentActive(int32_t id)97  void ContainerScope::UpdateRecentActive(int32_t id)
98  {
99      recentActiveId_.store(id, std::memory_order_relaxed);
100  }
101  
UpdateRecentForeground(int32_t id)102  void ContainerScope::UpdateRecentForeground(int32_t id)
103  {
104      recentForegroundId_.store(id, std::memory_order_relaxed);
105  }
106  
ContainerCount()107  uint32_t ContainerScope::ContainerCount()
108  {
109      std::shared_lock<std::shared_mutex> lock(mutex_);
110      return static_cast<uint32_t>(containerSet_.size());
111  }
112  
Add(int32_t id)113  void ContainerScope::Add(int32_t id)
114  {
115      std::unique_lock<std::shared_mutex> lock(mutex_);
116      containerSet_.emplace(id);
117  }
118  
Remove(int32_t id)119  void ContainerScope::Remove(int32_t id)
120  {
121      std::unique_lock<std::shared_mutex> lock(mutex_);
122      containerSet_.erase(id);
123  }
124  
RemoveAndCheck(int32_t id)125  void ContainerScope::RemoveAndCheck(int32_t id)
126  {
127      Remove(id);
128      if (RecentActiveId() == id) {
129          UpdateRecentActive(INSTANCE_ID_UNDEFINED);
130      }
131      if (RecentForegroundId() == id) {
132          UpdateRecentForeground(INSTANCE_ID_UNDEFINED);
133      }
134  }
135  
136  } // namespace OHOS::Ace
137