/* * Author: Sven Gothel * Copyright (c) 2020 Gothel Software e.K. * Copyright (c) 2020 ZAFENA AB * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef RINGBUFFER_HPP_ #define RINGBUFFER_HPP_ #include #include #include #include #include "BasicTypes.hpp" namespace direct_bt { /** * Ring buffer interface, a.k.a circular buffer. *

* Caller can chose whether to block until get / put is able to proceed or not. *

*

* Caller can chose whether to pass an empty array and clear references at get, * or using a preset array for circular access of same objects. *

*

* Synchronization and hence thread safety details belong to the implementation. *

*/ template class Ringbuffer { public: virtual ~Ringbuffer() {} /** Returns a short string representation incl. size/capacity and internal r/w index (impl. dependent). */ virtual std::string toString() const = 0; /** Debug functionality - Dumps the contents of the internal array. */ virtual void dump(FILE *stream, std::string prefix) const = 0; /** Returns the net capacity of this ring buffer. */ virtual int capacity() const = 0; /** * Releasing all elements by assigning null. *

* {@link #isEmpty()} will return true and * {@link #getSize()} will return 0 after calling this method. *

*/ virtual void clear() = 0; /** * {@link #clear()} all elements and add all copyFrom elements thereafter. * @param copyFrom Mandatory array w/ length {@link #capacity()} to be copied into the internal array. */ virtual void reset(const T * copyFrom, const int copyFromCount) = 0; virtual void reset(const std::vector & copyFrom) = 0; /** Returns the number of elements in this ring buffer. */ virtual int getSize() const = 0; /** Returns the number of free slots available to put. */ virtual int getFreeSlots() const = 0; /** Returns true if this ring buffer is empty, otherwise false. */ virtual bool isEmpty() const = 0; /** Returns true if this ring buffer is full, otherwise false. */ virtual bool isFull() const = 0; /** * Dequeues the oldest enqueued element if available, otherwise null. *

* The returned ring buffer slot will be set to null to release the reference * and move ownership to the caller. *

*

* Method is non blocking and returns immediately;. *

* @return the oldest put element if available, otherwise null. */ virtual T get() = 0; /** * Dequeues the oldest enqueued element. *

* The returned ring buffer slot will be set to null to release the reference * and move ownership to the caller. *

*

* timeoutMS defaults to zero, * i.e. infinitive blocking until an element available via put.
* Otherwise this methods blocks for the given milliseconds. *

* @return the oldest put element or null if timeout occurred. * @throws InterruptedException */ virtual T getBlocking(const int timeoutMS=0) /* throws InterruptedException */ = 0; /** * Peeks the next element at the read position w/o modifying pointer, nor blocking. * @return null if empty, otherwise the element which would be read next. */ virtual T peek() = 0; /** * Peeks the next element at the read position w/o modifying pointer, but with blocking. *

* timeoutMS defaults to zero, * i.e. infinitive blocking until an element available via put.
* Otherwise this methods blocks for the given milliseconds. *

* @return null if empty or timeout occurred, otherwise the element which would be read next. */ virtual T peekBlocking(const int timeoutMS=0) /* throws InterruptedException */ = 0; /** * Enqueues the given element. *

* Returns true if successful, otherwise false in case buffer is full. *

*

* Method is non blocking and returns immediately;. *

*/ virtual bool put(const T & e) = 0; /** * Enqueues the given element. *

* timeoutMS defaults to zero, * i.e. infinitive blocking until a free slot becomes available via get.
* Otherwise this methods blocks for the given milliseconds. *

*

* Returns true if successful, otherwise false in case timeout occurred. *

*/ virtual bool putBlocking(const T & e, const int timeoutMS=0) = 0; /** * Enqueues the same element at it's write position, if not full. *

* Returns true if successful, otherwise false in case buffer is full. *

*

* Method is non blocking and returns immediately;. *

* @throws InterruptedException */ virtual bool putSame() = 0; /** * Enqueues the same element at it's write position, if not full. *

* timeoutMS defaults to zero, * i.e. infinitive blocking until a free slot becomes available via get.
* Otherwise this methods blocks for the given milliseconds. *

*

* Returns true if successful, otherwise false in case timeout occurred. *

* @throws InterruptedException */ virtual bool putSameBlocking(const int timeoutMS=0) = 0; /** * Blocks until at least count free slots become available. * @throws InterruptedException */ virtual void waitForFreeSlots(const int count) /* throws InterruptedException */ = 0; /** * Resizes this ring buffer's capacity. *

* New capacity must be greater than current size. *

*/ virtual void recapacity(const int newCapacity) = 0; }; } /* namespace direct_bt */ #endif /* RINGBUFFER_HPP_ */