Gleb Klochkov / Mbed OS Climatcontroll_Main

Dependencies:   esp8266-driver

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 { 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