1 /*
2 * Copyright (c) 2023-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 "time_broker.h"
17 #include "steady_clock.h"
18 #include "dp_log.h"
19
20 namespace OHOS {
21 namespace CameraStandard {
22 namespace DeferredProcessing {
Create(std::string name)23 std::shared_ptr<TimeBroker> TimeBroker::Create(std::string name)
24 {
25 DP_DEBUG_LOG("(%s) created.", name.c_str());
26 auto timeBroker = std::make_shared<TimeBroker>(std::move(name));
27 timeBroker->Initialize();
28 return timeBroker;
29 }
30
TimeBroker(std::string name)31 TimeBroker::TimeBroker(std::string name)
32 : name_(std::move(name)), timer_(nullptr), timerInfos_(), expiringTimers_()
33 {
34 DP_DEBUG_LOG("(%s) entered.", name_.c_str());
35 }
36
~TimeBroker()37 TimeBroker::~TimeBroker()
38 {
39 std::lock_guard<std::mutex> lock(mutex_);
40 DP_DEBUG_LOG("(%s) entered.", name_.c_str());
41 if (timer_) {
42 timer_->Stop();
43 timer_.reset();
44 }
45 timerInfos_.clear();
46 expiringTimers_.clear();
47 }
48
Initialize()49 void TimeBroker::Initialize()
50 {
51 std::weak_ptr<TimeBroker> weakThis(shared_from_this());
52 timer_ = Timer::Create(name_, TimerType::ONCE, 0, [weakThis]() {
53 if (auto timeBroker = weakThis.lock()) {
54 timeBroker->TimerExpired();
55 }
56 });
57 }
58
RegisterCallback(uint32_t delayTimeMs,std::function<void (uint32_t handle)> timerCallback,uint32_t & handle)59 bool TimeBroker::RegisterCallback(uint32_t delayTimeMs, std::function<void(uint32_t handle)> timerCallback,
60 uint32_t& handle)
61 {
62 std::lock_guard<std::mutex> lock(mutex_);
63 DP_DEBUG_LOG("(%s) register callback with delayTimeMs (%{public}d).", name_.c_str(), static_cast<int>(delayTimeMs));
64 auto ret = GetNextHandle(handle);
65 if (ret) {
66 auto timestamp = SteadyClock::GetTimestampMilli() + delayTimeMs;
67 auto timerInfo = std::make_shared<TimerInfo>(handle, timestamp, std::move(timerCallback));
68 expiringTimers_[timestamp].push_back(timerInfo);
69 timerInfos_.emplace(handle, timerInfo);
70 timeline_.push(timestamp);
71 if (timestamp == timeline_.top()) {
72 timer_->StartAt(timestamp);
73 }
74 }
75 return ret;
76 }
DeregisterCallback(uint32_t handle)77 void TimeBroker::DeregisterCallback(uint32_t handle)
78 {
79 std::lock_guard<std::mutex> lock(mutex_);
80 if (handle == 0) {
81 DP_DEBUG_LOG("(%s) invalid handle (%{public}d).", name_.c_str(), static_cast<int>(handle));
82 return;
83 }
84 timerInfos_.erase(handle);
85 }
86
GetExpiredFunc(uint32_t handle)87 std::function<void(uint32_t handle)> TimeBroker::GetExpiredFunc(uint32_t handle)
88 {
89 std::lock_guard<std::mutex> lock(mutex_);
90 if (timerInfos_.count(handle)) {
91 return timerInfos_[handle]->timerCallback;
92 }
93 return [](uint32_t handle) {
94 DP_ERR_LOG("GetExpiredFunc invalid ExpiredFunc (%{public}d).", static_cast<int>(handle));
95 };
96 }
97
GetNextHandle(uint32_t & handle)98 bool TimeBroker::GetNextHandle(uint32_t& handle)
99 {
100 do {
101 handle = GenerateHandle();
102 } while (timerInfos_.count(handle) != 0 && handle != preHandle_);
103 if (handle != preHandle_) {
104 preHandle_ = handle;
105 return true;
106 }
107 return false;
108 }
109
GenerateHandle()110 uint32_t TimeBroker::GenerateHandle()
111 {
112 static uint32_t handle = 0;
113 if (++handle == 0) {
114 ++handle;
115 }
116 return handle;
117 }
118
TimerExpired()119 void TimeBroker::TimerExpired()
120 {
121 std::vector<std::shared_ptr<TimerInfo>> timerInfos;
122 {
123 std::lock_guard<std::mutex> lock(mutex_);
124 DP_DEBUG_LOG("(%s) TimerExpired.", name_.c_str());
125 if (timeline_.empty()) {
126 DP_DEBUG_LOG("(%s) unexpected TimerExpired", name_.c_str());
127 return;
128 }
129 auto timestamp = timeline_.top();
130 timeline_.pop();
131 timerInfos.reserve(expiringTimers_[timestamp].size());
132 for (auto& weakTimerInfoPtr : expiringTimers_[timestamp]) {
133 if (auto timerInfo = weakTimerInfoPtr.lock()) {
134 timerInfos_.erase(timerInfo->handle);
135 timerInfos.push_back(std::move(timerInfo));
136 }
137 }
138 expiringTimers_.erase(timestamp);
139 auto ret = RestartTimer(timestamp);
140 if (!ret) {
141 DP_DEBUG_LOG("(%s) RestartTimer failed (%{public}d)", name_.c_str(), ret);
142 }
143 }
144 for (auto &timerInfo : timerInfos) {
145 timerInfo->timerCallback(timerInfo->handle);
146 }
147 }
148
RestartTimer(bool force)149 bool TimeBroker::RestartTimer(bool force)
150 {
151 if (timeline_.empty() || (timer_->IsActive() && force == false)) {
152 DP_DEBUG_LOG("(%s) RestartTimer unnecessary.", name_.c_str());
153 return true;
154 }
155 auto timestamp = timeline_.top();
156 DP_DEBUG_LOG("(%s) restart timer, expiring timestamp: %{public}d", name_.c_str(), static_cast<int>(timestamp));
157 return timer_->StartAt(timestamp);
158 }
159 } //namespace DeferredProcessing
160 } // namespace CameraStandard
161 } // namespace OHOS
162