1 /*
2 * Copyright (c) 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 #include "finite_state_machine_impl.h"
16
17 #include <set>
18
19 #include "iam_logger.h"
20
21 #define LOG_TAG "FACE_AUTH_SA"
22 namespace OHOS {
23 namespace UserIam {
24 namespace FaceAuth {
25 using namespace OHOS;
FiniteStateMachineImpl(std::string name,uint32_t initialState,TransitionMap & transitionMap,EnterMap & enterMap,LeaveMap & leaveMap)26 FiniteStateMachineImpl::FiniteStateMachineImpl(std::string name, uint32_t initialState, TransitionMap &transitionMap,
27 EnterMap &enterMap, LeaveMap &leaveMap)
28 : name_(std::move(name)),
29 currentState_(initialState),
30 threadHandler_(ThreadHandler::GetSingleThreadInstance()),
31 transitionMap_(std::move(transitionMap)),
32 enterMap_(std::move(enterMap)),
33 leaveMap_(std::move(leaveMap))
34 {
35 IAM_LOGI("fsm %{public}s created for %{public}zu transitions", name_.c_str(), transitionMap_.size());
36 }
37
~FiniteStateMachineImpl()38 FiniteStateMachineImpl::~FiniteStateMachineImpl()
39 {
40 pendingEvents_.Clear();
41 IAM_LOGI("fsm %{public}s destroyed for %{public}zu transitions", name_.c_str(), transitionMap_.size());
42 }
43
Schedule(uint32_t event)44 void FiniteStateMachineImpl::Schedule(uint32_t event)
45 {
46 if (threadHandler_ == nullptr) {
47 IAM_LOGE("machine %{public}s 's threadHandler not set", GetMachineName().c_str());
48 return;
49 }
50 pendingEvents_.Push(event);
51 IAM_LOGI("fsm %{public}s new schedule event input:%{public}u", name_.c_str(), event);
52 threadHandler_->PostTask([self = weak_from_this(), this]() {
53 if (auto machine = self.lock(); machine != nullptr) {
54 Inner inner(machine);
55 ScheduleInner(inner);
56 }
57 });
58 }
59
ScheduleInner(FiniteStateMachine & machine)60 void FiniteStateMachineImpl::ScheduleInner(FiniteStateMachine &machine)
61 {
62 std::lock_guard<std::mutex> lock(mutex_);
63 uint32_t runTimes = 0;
64 while (true) {
65 uint32_t event = 0;
66 bool result = pendingEvents_.Pop(event);
67 if (!result) {
68 break;
69 }
70
71 uint32_t oldState = currentState_;
72 auto iter = transitionMap_.find(GetTransitionIndex(currentState_, event));
73 if (iter != transitionMap_.end()) {
74 auto invoker = iter->second.second;
75 if (invoker) {
76 invoker(machine, event);
77 }
78 currentState_ = iter->second.first;
79 }
80
81 DealWithStateLeaveAndEnter(machine, oldState, currentState_);
82
83 IAM_LOGI("fsm %{public}s schedule [state:%{public}u] + [event:%{public}u] -> [nextState:%{public}u]",
84 name_.c_str(), oldState, event, currentState_);
85
86 ++runTimes;
87 if (runTimes >= FiniteStateMachineImpl::MAX_SCHEDULE_TIMES) {
88 IAM_LOGE("fsm %{public}s schedule too many times", name_.c_str());
89 break;
90 }
91 }
92 }
93
DealWithStateLeaveAndEnter(FiniteStateMachine & machine,uint32_t oldState,uint32_t newState)94 void FiniteStateMachineImpl::DealWithStateLeaveAndEnter(FiniteStateMachine &machine, uint32_t oldState,
95 uint32_t newState)
96 {
97 if (oldState == newState) {
98 return;
99 }
100 if (auto iter = leaveMap_.find(oldState); iter != leaveMap_.end()) {
101 if (auto invoker = iter->second; invoker) {
102 invoker(machine, oldState);
103 }
104 }
105
106 if (auto iter = enterMap_.find(currentState_); iter != enterMap_.end()) {
107 if (auto invoker = iter->second; invoker) {
108 invoker(machine, currentState_);
109 }
110 }
111 }
112
GetCurrentState() const113 uint32_t FiniteStateMachineImpl::GetCurrentState() const
114 {
115 return currentState_;
116 }
117
EnsureCurrentState()118 uint32_t FiniteStateMachineImpl::EnsureCurrentState()
119 {
120 if (threadHandler_) {
121 threadHandler_->EnsureTask(nullptr);
122 }
123
124 return currentState_;
125 }
126
GetMachineName() const127 const std::string &FiniteStateMachineImpl::GetMachineName() const
128 {
129 return name_;
130 }
131
SetThreadHandler(const std::shared_ptr<ThreadHandler> & threadHandler)132 void FiniteStateMachineImpl::SetThreadHandler(const std::shared_ptr<ThreadHandler> &threadHandler)
133 {
134 threadHandler_ = threadHandler;
135 }
136
Inner(std::shared_ptr<FiniteStateMachineImpl> & machine)137 FiniteStateMachineImpl::Inner::Inner(std::shared_ptr<FiniteStateMachineImpl> &machine) : machine_(machine)
138 {
139 }
140
Schedule(uint32_t event)141 void FiniteStateMachineImpl::Inner::Schedule(uint32_t event)
142 {
143 machine_->pendingEvents_.Push(event);
144 }
145
GetCurrentState() const146 uint32_t FiniteStateMachineImpl::Inner::GetCurrentState() const
147 {
148 return machine_->GetCurrentState();
149 }
150
EnsureCurrentState()151 uint32_t FiniteStateMachineImpl::Inner::EnsureCurrentState()
152 {
153 return machine_->GetCurrentState();
154 }
155
GetMachineName() const156 const std::string &FiniteStateMachineImpl::Inner::GetMachineName() const
157 {
158 return machine_->GetMachineName();
159 }
160
SetThreadHandler(const std::shared_ptr<ThreadHandler> & threadHandler)161 void FiniteStateMachineImpl::Inner::SetThreadHandler(const std::shared_ptr<ThreadHandler> &threadHandler)
162 {
163 IAM_LOGE("can not set thread handler inner");
164 }
165 } // namespace FaceAuth
166 } // namespace UserIam
167 } // namespace OHOS
168