mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
CircularBuffer.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2015 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #ifndef MBED_CIRCULARBUFFER_H 00018 #define MBED_CIRCULARBUFFER_H 00019 00020 #include "platform/mbed_critical.h" 00021 #include "platform/mbed_assert.h" 00022 00023 namespace mbed { 00024 00025 namespace internal { 00026 /* Detect if CounterType of the Circular buffer is of unsigned type. */ 00027 template<typename T> 00028 struct is_unsigned { 00029 static const bool value = false; 00030 }; 00031 template<> 00032 struct is_unsigned<unsigned char> { 00033 static const bool value = true; 00034 }; 00035 template<> 00036 struct is_unsigned<unsigned short> { 00037 static const bool value = true; 00038 }; 00039 template<> 00040 struct is_unsigned<unsigned int> { 00041 static const bool value = true; 00042 }; 00043 template<> 00044 struct is_unsigned<unsigned long> { 00045 static const bool value = true; 00046 }; 00047 template<> 00048 struct is_unsigned<unsigned long long> { 00049 static const bool value = true; 00050 }; 00051 }; 00052 00053 /** \addtogroup platform */ 00054 /** @{*/ 00055 /** 00056 * \defgroup platform_CircularBuffer CircularBuffer functions 00057 * @{ 00058 */ 00059 00060 /** Templated Circular buffer class 00061 * 00062 * @note Synchronization level: Interrupt safe 00063 * @note CounterType must be unsigned and consistent with BufferSize 00064 */ 00065 template<typename T, uint32_t BufferSize, typename CounterType = uint32_t> 00066 class CircularBuffer { 00067 public: 00068 CircularBuffer() : _head(0), _tail(0), _full(false) 00069 { 00070 MBED_STATIC_ASSERT( 00071 internal::is_unsigned<CounterType>::value, 00072 "CounterType must be unsigned" 00073 ); 00074 00075 MBED_STATIC_ASSERT( 00076 (sizeof(CounterType) >= sizeof(uint32_t)) || 00077 (BufferSize < (((uint64_t) 1) << (sizeof(CounterType) * 8))), 00078 "Invalid BufferSize for the CounterType" 00079 ); 00080 } 00081 00082 ~CircularBuffer() 00083 { 00084 } 00085 00086 /** Push the transaction to the buffer. This overwrites the buffer if it's 00087 * full 00088 * 00089 * @param data Data to be pushed to the buffer 00090 */ 00091 void push(const T &data) 00092 { 00093 core_util_critical_section_enter(); 00094 if (full()) { 00095 _tail++; 00096 if (_tail == BufferSize) { 00097 _tail = 0; 00098 } 00099 } 00100 _pool[_head++] = data; 00101 if (_head == BufferSize) { 00102 _head = 0; 00103 } 00104 if (_head == _tail) { 00105 _full = true; 00106 } 00107 core_util_critical_section_exit(); 00108 } 00109 00110 /** Pop the transaction from the buffer 00111 * 00112 * @param data Data to be popped from the buffer 00113 * @return True if the buffer is not empty and data contains a transaction, false otherwise 00114 */ 00115 bool pop(T &data) 00116 { 00117 bool data_popped = false; 00118 core_util_critical_section_enter(); 00119 if (!empty()) { 00120 data = _pool[_tail++]; 00121 if (_tail == BufferSize) { 00122 _tail = 0; 00123 } 00124 _full = false; 00125 data_popped = true; 00126 } 00127 core_util_critical_section_exit(); 00128 return data_popped; 00129 } 00130 00131 /** Check if the buffer is empty 00132 * 00133 * @return True if the buffer is empty, false if not 00134 */ 00135 bool empty() const 00136 { 00137 core_util_critical_section_enter(); 00138 bool is_empty = (_head == _tail) && !_full; 00139 core_util_critical_section_exit(); 00140 return is_empty; 00141 } 00142 00143 /** Check if the buffer is full 00144 * 00145 * @return True if the buffer is full, false if not 00146 */ 00147 bool full() const 00148 { 00149 core_util_critical_section_enter(); 00150 bool full = _full; 00151 core_util_critical_section_exit(); 00152 return full; 00153 } 00154 00155 /** Reset the buffer 00156 * 00157 */ 00158 void reset() 00159 { 00160 core_util_critical_section_enter(); 00161 _head = 0; 00162 _tail = 0; 00163 _full = false; 00164 core_util_critical_section_exit(); 00165 } 00166 00167 /** Get the number of elements currently stored in the circular_buffer */ 00168 CounterType size() const 00169 { 00170 core_util_critical_section_enter(); 00171 CounterType elements; 00172 if (!_full) { 00173 if (_head < _tail) { 00174 elements = BufferSize + _head - _tail; 00175 } else { 00176 elements = _head - _tail; 00177 } 00178 } else { 00179 elements = BufferSize; 00180 } 00181 core_util_critical_section_exit(); 00182 return elements; 00183 } 00184 00185 /** Peek into circular buffer without popping 00186 * 00187 * @param data Data to be peeked from the buffer 00188 * @return True if the buffer is not empty and data contains a transaction, false otherwise 00189 */ 00190 bool peek(T &data) const 00191 { 00192 bool data_updated = false; 00193 core_util_critical_section_enter(); 00194 if (!empty()) { 00195 data = _pool[_tail]; 00196 data_updated = true; 00197 } 00198 core_util_critical_section_exit(); 00199 return data_updated; 00200 } 00201 00202 private: 00203 T _pool[BufferSize]; 00204 CounterType _head; 00205 CounterType _tail; 00206 bool _full; 00207 }; 00208 00209 /**@}*/ 00210 00211 /**@}*/ 00212 00213 } 00214 00215 #endif
Generated on Tue Jul 12 2022 20:41:14 by 1.7.2