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