• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "circle_buffer.h"
17 #include "base.h"
18 
19 namespace Hdc {
CircleBuffer()20 CircleBuffer::CircleBuffer()
21 {
22     run_ = false;
23     TimerStart();
24 }
25 
~CircleBuffer()26 CircleBuffer::~CircleBuffer()
27 {
28     TimerStop();
29     for (auto iter = buffers_.begin(); iter != buffers_.end();) {
30         Data *data = iter->second;
31         delete[] data->buf;
32         delete data;
33         iter = buffers_.erase(iter);
34     }
35 }
36 
Malloc()37 uint8_t *CircleBuffer::Malloc()
38 {
39     const size_t bufSize = static_cast<size_t>(Base::GetUsbffsBulkSize());
40     uint8_t *buf = nullptr;
41     std::unique_lock<std::mutex> lock(mutex_);
42     for (auto iter = buffers_.begin(); iter != buffers_.end(); ++iter) {
43         Data *data = iter->second;
44         if (data->used == false) {
45             data->used = true;
46             data->begin = std::chrono::steady_clock::now();
47             buf = data->buf;
48             break;
49         }
50     }
51     if (buf == nullptr) {
52         Data *data = new(std::nothrow) Data();
53         if (data == nullptr) {
54             return nullptr;
55         }
56         data->used = true;
57         data->begin = std::chrono::steady_clock::now();
58         data->buf = new(std::nothrow) uint8_t[bufSize];
59         if (data->buf == nullptr) {
60             delete data;
61             return nullptr;
62         }
63         uint64_t key = reinterpret_cast<uint64_t>(data->buf);
64         buffers_[key] = data;
65         buf = data->buf;
66     }
67     (void)memset_s(buf, bufSize, 0, bufSize);
68     return buf;
69 }
70 
Free(const uint8_t * buf)71 void CircleBuffer::Free(const uint8_t *buf)
72 {
73     std::unique_lock<std::mutex> lock(mutex_);
74     uint64_t key = reinterpret_cast<uint64_t>(buf);
75     Data *data = buffers_[key];
76     data->used = false;
77     data->begin = std::chrono::steady_clock::now();
78 }
79 
FreeMemory()80 void CircleBuffer::FreeMemory()
81 {
82     std::unique_lock<std::mutex> lock(mutex_);
83     constexpr int64_t decreaseTime = 5; // 5s
84     auto end = std::chrono::steady_clock::now();
85     for (auto iter = buffers_.begin(); iter != buffers_.end();) {
86         bool remove = false;
87         Data *data = iter->second;
88         if (data->used == false) {
89             auto begin = data->begin;
90             auto duration = std::chrono::duration_cast<std::chrono::seconds>(end - begin);
91             if (duration.count() > decreaseTime) {
92                 remove = true;
93             }
94         }
95         if (remove) {
96             delete[] data->buf;
97             delete data;
98             iter = buffers_.erase(iter);
99         } else {
100             ++iter;
101         }
102     }
103 }
104 
Timer(void * object)105 void CircleBuffer::Timer(void *object)
106 {
107     CircleBuffer *cirbuf = reinterpret_cast<CircleBuffer *>(object);
108     while (cirbuf->run_) {
109         cirbuf->FreeMemory();
110         cirbuf->TimerSleep();
111     }
112 }
113 
TimerStart()114 void CircleBuffer::TimerStart()
115 {
116     if (!run_) {
117         run_ = true;
118         thread_ = std::thread(Timer, this);
119     }
120 }
121 
TimerStop()122 void CircleBuffer::TimerStop()
123 {
124     if (run_) {
125         run_ = false;
126         TimerNotify();
127         thread_.join();
128     }
129 }
130 
TimerSleep()131 void CircleBuffer::TimerSleep()
132 {
133     std::unique_lock<std::mutex> lock(timerMutex_);
134     timerCv_.wait_for(lock, std::chrono::seconds(1));
135 }
136 
TimerNotify()137 void CircleBuffer::TimerNotify()
138 {
139     std::unique_lock<std::mutex> lock(timerMutex_);
140     timerCv_.notify_one();
141 }
142 }
143