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