SilentSensors / mbed-dev

Fork of mbed-dev by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CircularBuffer.h Source File

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 {
00028     static const bool value = false;
00029 };
00030 template<>
00031 struct is_unsigned<unsigned char> {
00032     static const bool value = true;
00033 };
00034 template<>
00035 struct is_unsigned<unsigned short> {
00036     static const bool value = true;
00037 };
00038 template<>
00039 struct is_unsigned<unsigned int> {
00040     static const bool value = true;
00041 };
00042 template<>
00043 struct is_unsigned<unsigned long> {
00044     static const bool value = true;
00045 };
00046 template<>
00047 struct is_unsigned<unsigned long long> {
00048     static const bool value = true;
00049 };
00050 };
00051 
00052 /** \addtogroup platform */
00053 /** @{*/
00054 /**
00055  * \defgroup platform_CircularBuffer CircularBuffer functions
00056  * @{
00057  */
00058 
00059 /** Templated Circular buffer class
00060  *
00061  *  @note Synchronization level: Interrupt safe
00062  *  @note CounterType must be unsigned and consistent with BufferSize
00063  */
00064 template<typename T, uint32_t BufferSize, typename CounterType = uint32_t>
00065 class CircularBuffer {
00066 public:
00067     CircularBuffer() : _head(0), _tail(0), _full(false)
00068     {
00069         MBED_STATIC_ASSERT(
00070             internal::is_unsigned<CounterType>::value,
00071             "CounterType must be unsigned"
00072         );
00073 
00074         MBED_STATIC_ASSERT(
00075             (sizeof(CounterType) >= sizeof(uint32_t)) ||
00076             (BufferSize < (((uint64_t) 1) << (sizeof(CounterType) * 8))),
00077             "Invalid BufferSize for the CounterType"
00078         );
00079     }
00080 
00081     ~CircularBuffer()
00082     {
00083     }
00084 
00085     /** Push the transaction to the buffer. This overwrites the buffer if it's
00086      *  full
00087      *
00088      * @param data Data to be pushed to the buffer
00089      */
00090     void push(const T &data)
00091     {
00092         core_util_critical_section_enter();
00093         if (full()) {
00094             _tail++;
00095             _tail %= BufferSize;
00096         }
00097         _pool[_head++] = data;
00098         _head %= BufferSize;
00099         if (_head == _tail) {
00100             _full = true;
00101         }
00102         core_util_critical_section_exit();
00103     }
00104 
00105     /** Pop the transaction from the buffer
00106      *
00107      * @param data Data to be popped from the buffer
00108      * @return True if the buffer is not empty and data contains a transaction, false otherwise
00109      */
00110     bool pop(T &data)
00111     {
00112         bool data_popped = false;
00113         core_util_critical_section_enter();
00114         if (!empty()) {
00115             data = _pool[_tail++];
00116             _tail %= BufferSize;
00117             _full = false;
00118             data_popped = true;
00119         }
00120         core_util_critical_section_exit();
00121         return data_popped;
00122     }
00123 
00124     /** Check if the buffer is empty
00125      *
00126      * @return True if the buffer is empty, false if not
00127      */
00128     bool empty() const
00129     {
00130         core_util_critical_section_enter();
00131         bool is_empty = (_head == _tail) && !_full;
00132         core_util_critical_section_exit();
00133         return is_empty;
00134     }
00135 
00136     /** Check if the buffer is full
00137      *
00138      * @return True if the buffer is full, false if not
00139      */
00140     bool full() const
00141     {
00142         core_util_critical_section_enter();
00143         bool full = _full;
00144         core_util_critical_section_exit();
00145         return full;
00146     }
00147 
00148     /** Reset the buffer
00149      *
00150      */
00151     void reset()
00152     {
00153         core_util_critical_section_enter();
00154         _head = 0;
00155         _tail = 0;
00156         _full = false;
00157         core_util_critical_section_exit();
00158     }
00159 
00160     /** Get the number of elements currently stored in the circular_buffer */
00161     CounterType size() const
00162     {
00163         core_util_critical_section_enter();
00164         CounterType elements;
00165         if (!_full) {
00166             if (_head < _tail) {
00167                 elements = BufferSize + _head - _tail;
00168             } else {
00169                 elements = _head - _tail;
00170             }
00171         } else {
00172             elements = BufferSize;
00173         }
00174         core_util_critical_section_exit();
00175         return elements;
00176     }
00177 
00178     /** Peek into circular buffer without popping
00179      *
00180      * @param data Data to be peeked from the buffer
00181      * @return True if the buffer is not empty and data contains a transaction, false otherwise
00182      */
00183     bool peek(T &data) const
00184     {
00185         bool data_updated = false;
00186         core_util_critical_section_enter();
00187         if (!empty()) {
00188             data = _pool[_tail];
00189             data_updated = true;
00190         }
00191         core_util_critical_section_exit();
00192         return data_updated;
00193     }
00194 
00195 private:
00196     T _pool[BufferSize];
00197     volatile CounterType _head;
00198     volatile CounterType _tail;
00199     volatile bool _full;
00200 };
00201 
00202 /**@}*/
00203 
00204 /**@}*/
00205 
00206 }
00207 
00208 #endif