1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci#include <iostream> 16fb299fa2Sopenharmony_ci#include <cstring> 17fb299fa2Sopenharmony_ci#include <string> 18fb299fa2Sopenharmony_ci#include <thread> 19fb299fa2Sopenharmony_ci 20fb299fa2Sopenharmony_ci#include "log.h" 21fb299fa2Sopenharmony_ci#include "securec.h" 22fb299fa2Sopenharmony_ci#include "ring_buffer.h" 23fb299fa2Sopenharmony_ci 24fb299fa2Sopenharmony_cinamespace Updater { 25fb299fa2Sopenharmony_ciRingBuffer::~RingBuffer() 26fb299fa2Sopenharmony_ci{ 27fb299fa2Sopenharmony_ci Release(); 28fb299fa2Sopenharmony_ci} 29fb299fa2Sopenharmony_ci 30fb299fa2Sopenharmony_cibool RingBuffer::Init(uint32_t singleSize, uint32_t num) 31fb299fa2Sopenharmony_ci{ 32fb299fa2Sopenharmony_ci if (singleSize == 0 || num == 0 || (num & (num - 1)) != 0) { // power of 2 33fb299fa2Sopenharmony_ci LOG(ERROR) << "singleSize:" << singleSize << " num:" << num << " error"; 34fb299fa2Sopenharmony_ci return false; 35fb299fa2Sopenharmony_ci } 36fb299fa2Sopenharmony_ci bufArray_ = new (std::nothrow) uint8_t* [num] {}; 37fb299fa2Sopenharmony_ci lenArray_ = new (std::nothrow) uint32_t [num] {}; 38fb299fa2Sopenharmony_ci if (bufArray_ == nullptr || lenArray_ == nullptr) { 39fb299fa2Sopenharmony_ci LOG(ERROR) << "new buf or len " << num << " error"; 40fb299fa2Sopenharmony_ci return false; 41fb299fa2Sopenharmony_ci } 42fb299fa2Sopenharmony_ci for (uint32_t i = 0; i < num; i++) { 43fb299fa2Sopenharmony_ci bufArray_[i] = new (std::nothrow) uint8_t [singleSize] {}; 44fb299fa2Sopenharmony_ci if (bufArray_[i] == nullptr) { 45fb299fa2Sopenharmony_ci LOG(ERROR) << "new buf " << i << " size " << singleSize << " error"; 46fb299fa2Sopenharmony_ci return false; 47fb299fa2Sopenharmony_ci } 48fb299fa2Sopenharmony_ci } 49fb299fa2Sopenharmony_ci 50fb299fa2Sopenharmony_ci writeIndex_ = 0; 51fb299fa2Sopenharmony_ci readIndex_ = 0; 52fb299fa2Sopenharmony_ci num_ = num; 53fb299fa2Sopenharmony_ci singleSize_ = singleSize; 54fb299fa2Sopenharmony_ci return true; 55fb299fa2Sopenharmony_ci} 56fb299fa2Sopenharmony_ci 57fb299fa2Sopenharmony_civoid RingBuffer::Reset() 58fb299fa2Sopenharmony_ci{ 59fb299fa2Sopenharmony_ci isStop_ = false; 60fb299fa2Sopenharmony_ci writeIndex_ = 0; 61fb299fa2Sopenharmony_ci readIndex_ = 0; 62fb299fa2Sopenharmony_ci for (uint32_t i = 0; i < num_; ++i) { 63fb299fa2Sopenharmony_ci lenArray_[i] = 0; 64fb299fa2Sopenharmony_ci } 65fb299fa2Sopenharmony_ci} 66fb299fa2Sopenharmony_ci 67fb299fa2Sopenharmony_cibool RingBuffer::IsFull() 68fb299fa2Sopenharmony_ci{ 69fb299fa2Sopenharmony_ci // writeIndex readIndex real size: 0 ~ num_ -1, logic size: 0 ~ 2num_ - 1 70fb299fa2Sopenharmony_ci // when writeIndex_ - readIndex_ == n means full 71fb299fa2Sopenharmony_ci return writeIndex_ == (readIndex_ ^ num_); 72fb299fa2Sopenharmony_ci} 73fb299fa2Sopenharmony_ci 74fb299fa2Sopenharmony_cibool RingBuffer::IsEmpty() 75fb299fa2Sopenharmony_ci{ 76fb299fa2Sopenharmony_ci // writeIndex readIndex real size: 0 ~ num_ -1, logic size: 0 ~ 2num_ - 1 77fb299fa2Sopenharmony_ci // when same means empty 78fb299fa2Sopenharmony_ci return writeIndex_ == readIndex_; 79fb299fa2Sopenharmony_ci} 80fb299fa2Sopenharmony_ci 81fb299fa2Sopenharmony_cibool RingBuffer::Push(uint8_t *buf, uint32_t len) 82fb299fa2Sopenharmony_ci{ 83fb299fa2Sopenharmony_ci if (buf == nullptr || len == 0 || len > singleSize_) { 84fb299fa2Sopenharmony_ci LOG(ERROR) << "RingBuffer push error, len:" << len << " singleSize:" << singleSize_; 85fb299fa2Sopenharmony_ci return false; 86fb299fa2Sopenharmony_ci } 87fb299fa2Sopenharmony_ci if (IsFull()) { 88fb299fa2Sopenharmony_ci std::unique_lock<std::mutex> pushLock(notifyMtx_); 89fb299fa2Sopenharmony_ci while (IsFull()) { 90fb299fa2Sopenharmony_ci if (isStop_) { 91fb299fa2Sopenharmony_ci LOG(WARNING) << "RingBuffer push stopped"; 92fb299fa2Sopenharmony_ci return false; 93fb299fa2Sopenharmony_ci } 94fb299fa2Sopenharmony_ci LOG(DEBUG) << "RingBuffer full, wait !!!"; 95fb299fa2Sopenharmony_ci notFull_.wait(pushLock); 96fb299fa2Sopenharmony_ci } 97fb299fa2Sopenharmony_ci } 98fb299fa2Sopenharmony_ci 99fb299fa2Sopenharmony_ci uint32_t index = writeIndex_ & (num_ - 1); 100fb299fa2Sopenharmony_ci if (memcpy_s(bufArray_[index], singleSize_, buf, len) != EOK) { 101fb299fa2Sopenharmony_ci LOG(ERROR) << "memcpy error, len:" << len; 102fb299fa2Sopenharmony_ci return false; 103fb299fa2Sopenharmony_ci } 104fb299fa2Sopenharmony_ci lenArray_[index] = len; 105fb299fa2Sopenharmony_ci writeIndex_ = (writeIndex_ + 1) & (2 * num_ - 1); // 2: logic buffer size 106fb299fa2Sopenharmony_ci 107fb299fa2Sopenharmony_ci std::unique_lock<std::mutex> popLock(notifyMtx_); 108fb299fa2Sopenharmony_ci notEmpty_.notify_all(); 109fb299fa2Sopenharmony_ci return true; 110fb299fa2Sopenharmony_ci} 111fb299fa2Sopenharmony_ci 112fb299fa2Sopenharmony_cibool RingBuffer::Pop(uint8_t *buf, uint32_t maxLen, uint32_t &len) 113fb299fa2Sopenharmony_ci{ 114fb299fa2Sopenharmony_ci if (buf == nullptr) { 115fb299fa2Sopenharmony_ci LOG(ERROR) << "RingBuffer pop para error"; 116fb299fa2Sopenharmony_ci return false; 117fb299fa2Sopenharmony_ci } 118fb299fa2Sopenharmony_ci if (IsEmpty()) { 119fb299fa2Sopenharmony_ci std::unique_lock<std::mutex> popLock(notifyMtx_); 120fb299fa2Sopenharmony_ci while (IsEmpty()) { 121fb299fa2Sopenharmony_ci if (isStop_) { 122fb299fa2Sopenharmony_ci LOG(WARNING) << "RingBuffer pop stopped"; 123fb299fa2Sopenharmony_ci return false; 124fb299fa2Sopenharmony_ci } 125fb299fa2Sopenharmony_ci LOG(DEBUG) << "RingBuffer empty, wait !!!"; 126fb299fa2Sopenharmony_ci notEmpty_.wait(popLock); 127fb299fa2Sopenharmony_ci } 128fb299fa2Sopenharmony_ci } 129fb299fa2Sopenharmony_ci 130fb299fa2Sopenharmony_ci uint32_t index = readIndex_ & (num_ - 1); 131fb299fa2Sopenharmony_ci if (memcpy_s(buf, maxLen, bufArray_[index], lenArray_[index]) != EOK) { 132fb299fa2Sopenharmony_ci LOG(ERROR) << "memcpy error, len:" << lenArray_[index]; 133fb299fa2Sopenharmony_ci return false; 134fb299fa2Sopenharmony_ci } 135fb299fa2Sopenharmony_ci len = lenArray_[index]; 136fb299fa2Sopenharmony_ci readIndex_ = (readIndex_ + 1) & (2 * num_ - 1); // 2: logic buffer size 137fb299fa2Sopenharmony_ci 138fb299fa2Sopenharmony_ci std::unique_lock<std::mutex> popLock(notifyMtx_); 139fb299fa2Sopenharmony_ci notFull_.notify_all(); 140fb299fa2Sopenharmony_ci return true; 141fb299fa2Sopenharmony_ci} 142fb299fa2Sopenharmony_ci 143fb299fa2Sopenharmony_civoid RingBuffer::Stop() 144fb299fa2Sopenharmony_ci{ 145fb299fa2Sopenharmony_ci isStop_ = true; 146fb299fa2Sopenharmony_ci notFull_.notify_all(); 147fb299fa2Sopenharmony_ci notEmpty_.notify_all(); 148fb299fa2Sopenharmony_ci} 149fb299fa2Sopenharmony_ci 150fb299fa2Sopenharmony_civoid RingBuffer::StopPush() 151fb299fa2Sopenharmony_ci{ 152fb299fa2Sopenharmony_ci { 153fb299fa2Sopenharmony_ci std::unique_lock<std::mutex> pushLock(notifyMtx_); 154fb299fa2Sopenharmony_ci isStop_ = true; 155fb299fa2Sopenharmony_ci } 156fb299fa2Sopenharmony_ci notFull_.notify_all(); 157fb299fa2Sopenharmony_ci} 158fb299fa2Sopenharmony_ci 159fb299fa2Sopenharmony_civoid RingBuffer::StopPop() 160fb299fa2Sopenharmony_ci{ 161fb299fa2Sopenharmony_ci { 162fb299fa2Sopenharmony_ci std::unique_lock<std::mutex> popLock(notifyMtx_); 163fb299fa2Sopenharmony_ci isStop_ = true; 164fb299fa2Sopenharmony_ci } 165fb299fa2Sopenharmony_ci notEmpty_.notify_all(); 166fb299fa2Sopenharmony_ci} 167fb299fa2Sopenharmony_ci 168fb299fa2Sopenharmony_civoid RingBuffer::Release() 169fb299fa2Sopenharmony_ci{ 170fb299fa2Sopenharmony_ci if (lenArray_ != nullptr) { 171fb299fa2Sopenharmony_ci delete[] lenArray_; 172fb299fa2Sopenharmony_ci lenArray_ = nullptr; 173fb299fa2Sopenharmony_ci } 174fb299fa2Sopenharmony_ci 175fb299fa2Sopenharmony_ci if (bufArray_ != nullptr) { 176fb299fa2Sopenharmony_ci for (uint32_t i = 0; i < num_ && bufArray_[i] != nullptr; i++) { 177fb299fa2Sopenharmony_ci delete[] bufArray_[i]; 178fb299fa2Sopenharmony_ci bufArray_[i] = nullptr; 179fb299fa2Sopenharmony_ci } 180fb299fa2Sopenharmony_ci delete[] bufArray_; 181fb299fa2Sopenharmony_ci bufArray_ = nullptr; 182fb299fa2Sopenharmony_ci } 183fb299fa2Sopenharmony_ci} 184fb299fa2Sopenharmony_ci} // namespace Updater 185