• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
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 #ifndef RINGBUFFER_H
17 #define RINGBUFFER_H
18 
19 #include <mutex>
20 #include <securec.h>
21 
22 class RingBuffer {
23 public:
24     enum MemAlignShift:std::size_t {
25         B_ALIGN_SHIFT = 0,  // byte alingment
26         H_ALIGN_SHIFT = 1,  // half word alignment
27         W_ALIGN_SHIFT = 2,  // word alignment
28         D_ALIGN_SHIFT = 3,  // double word alignment
29     };
30 
31     RingBuffer(
32         const std::size_t bufSize = DEFAULT_SIZE,
33         const enum MemAlignShift shift = B_ALIGN_SHIFT);
34 
~RingBuffer()35     inline ~RingBuffer()
36     {
37         if (buffer_ != nullptr) {
38             delete[] buffer_;
39             buffer_ = nullptr;
40         }
41     }
42     inline operator bool()
43     {
44         std::lock_guard<std::mutex> lk {mtx_};
45         return buffer_;
46     }
GetFreeSize()47     inline std::size_t GetFreeSize()
48     {
49         std::lock_guard<std::mutex> lk {mtx_};
50         return FreeSize();
51     }
GetDataSize()52     inline std::size_t GetDataSize()
53     {
54         std::lock_guard<std::mutex> lk {mtx_};
55         return DataSize();
56     }
GetCapacity()57     inline std::size_t GetCapacity()
58     {
59         std::lock_guard<std::mutex> lk {mtx_};
60         return Capacity();
61     }
62     template<typename T>
Peek(T * var)63     int Peek(T *var)
64     {
65         const std::size_t len {sizeof(T)};
66         char *dest = reinterpret_cast<char*>(var);
67         if (dest == nullptr) {
68             return -1;
69         }
70         if (len == 0) {
71             return -1;
72         }
73         std::lock_guard<std::mutex> lk {mtx_};
74         auto dataSize = DataSize();
75         if (dataSize < len) {
76             return -1;
77         }
78         if (head_ + len > bufSize_) {
79             // data splitted
80             int ret = memcpy_s(dest, len, buffer_ + head_, bufSize_ - head_);
81             if (ret != EOK) {
82                 return -1;
83             }
84             ret = memcpy_s(dest + bufSize_ - head_, len + head_ - bufSize_, buffer_, len + head_ - bufSize_);
85             if (ret != EOK) {
86                 return -1;
87             }
88         } else {
89             if (memcpy_s(dest, len, buffer_ + head_, len) != EOK) {
90                 return -1;
91             }
92         }
93         return 0;
94     }
95 
96     ssize_t Read(const int fd, const std::size_t len);
97     ssize_t Write(const int fd, const std::size_t len);
98     std::size_t Get(char* dest, const std::size_t len);
99     int Put(const char* str, const std::size_t len);
100     int Put(const std::string& str);
101 
102 private:
FreeSize()103     inline std::size_t FreeSize() const
104     {
105         int res {0};
106         res = head_ - tail_;
107         if (res <= 0) {
108             res += bufSize_;
109         }
110         return static_cast<std::size_t>(res);
111     }
112     inline std::size_t DataSize(int noLock = 1) const
113     {
114         int res {0};
115         res = tail_ - head_;
116         if (res < 0) {
117             res += bufSize_;
118         }
119         return static_cast<std::size_t>(res);
120     }
121     inline std::size_t Capacity(int noLock = 1) const
122     {
123         return bufSize_;
124     }
125 
126     int Resize();
127     char* Allocate(std::size_t bufSize);
128 
129     enum BufferSize:std::size_t {
130         DEFAULT_SIZE = (1 << 8),
131     };
132     char *buffer_ {nullptr};
133     std::size_t bufSize_ {DEFAULT_SIZE};
134     const std::size_t alignShift_ {B_ALIGN_SHIFT};
135     /* head_ = tail_ mean empty, the buffer can never be full */
136     std::size_t head_ {0};   // first readable byte
137     std::size_t tail_ {0};          // first writebale byte
138     std::mutex mtx_;
139 };
140 #endif