summaryrefslogtreecommitdiffstats
path: root/api/direct_bt/Ringbuffer.hpp
blob: 4a4c525cb617d2258ebeb59c04d9460dfceb67ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
 * Author: Sven Gothel <sgothel@jausoft.com>
 * 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 <cstring>
#include <string>
#include <memory>
#include <cstdint>

#include "BasicTypes.hpp"

namespace direct_bt {


/**
 * Ring buffer interface, a.k.a circular buffer.
 * <p>
 * Caller can chose whether to block until get / put is able to proceed or not.
 * </p>
 * <p>
 * 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.
 * </p>
 * <p>
 * Synchronization and hence thread safety details belong to the implementation.
 * </p>
 */
template <class T> 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 <code>null</code>.
         * <p>
         * {@link #isEmpty()} will return <code>true</code> and
         * {@link #getSize()} will return <code>0</code> after calling this method.
         * </p>
         */
        virtual void clear() = 0;

        /**
         * {@link #clear()} all elements and add all <code>copyFrom</code> 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<T> & 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.
         * <p>
         * The returned ring buffer slot will be set to <code>null</code> to release the reference
         * and move ownership to the caller.
         * </p>
         * <p>
         * Method is non blocking and returns immediately;.
         * </p>
         * @return the oldest put element if available, otherwise null.
         */
        virtual T get() = 0;

        /**
         * Dequeues the oldest enqueued element.
         * <p>
         * The returned ring buffer slot will be set to <code>null</code> to release the reference
         * and move ownership to the caller.
         * </p>
         * <p>
         * <code>timeoutMS</code> defaults to zero,
         * i.e. infinitive blocking until an element available via put.<br>
         * Otherwise this methods blocks for the given milliseconds.
         * </p>
         * @return the oldest put element or <code>null</code> 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 <code>null</code> 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.
         * <p>
         * <code>timeoutMS</code> defaults to zero,
         * i.e. infinitive blocking until an element available via put.<br>
         * Otherwise this methods blocks for the given milliseconds.
         * </p>
         * @return <code>null</code> if empty or timeout occurred, otherwise the element which would be read next.
         */
        virtual T peekBlocking(const int timeoutMS=0) /* throws InterruptedException */ = 0;

        /**
         * Drops up to {@code count} oldest enqueued elements.
         * <p>
         * Method is non blocking and returns immediately;.
         * </p>
         * @param count maximum number of elements to drop from ringbuffer.
         * @return actual number of dropped elements.
         */
        virtual int drop(const int count) = 0;

        /**
         * Enqueues the given element.
         * <p>
         * Returns true if successful, otherwise false in case buffer is full.
         * </p>
         * <p>
         * Method is non blocking and returns immediately;.
         * </p>
         */
        virtual bool put(const T & e) = 0;

        /**
         * Enqueues the given element.
         * <p>
         * <code>timeoutMS</code> defaults to zero,
         * i.e. infinitive blocking until a free slot becomes available via get.<br>
         * Otherwise this methods blocks for the given milliseconds.
         * </p>
         * <p>
         * Returns true if successful, otherwise false in case timeout occurred.
         * </p>
         */
        virtual bool putBlocking(const T & e, const int timeoutMS=0) = 0;

        /**
         * Enqueues the same element at it's write position, if not full.
         * <p>
         * Returns true if successful, otherwise false in case buffer is full.
         * </p>
         * <p>
         * Method is non blocking and returns immediately;.
         * </p>
         * @throws InterruptedException
         */
        virtual bool putSame() = 0;

        /**
         * Enqueues the same element at it's write position, if not full.
         * <p>
         * <code>timeoutMS</code> defaults to zero,
         * i.e. infinitive blocking until a free slot becomes available via get.<br>
         * Otherwise this methods blocks for the given milliseconds.
         * </p>
         * <p>
         * Returns true if successful, otherwise false in case timeout occurred.
         * </p>
         * @throws InterruptedException
         */
        virtual bool putSameBlocking(const int timeoutMS=0) = 0;

        /**
         * Blocks until at least <code>count</code> free slots become available.
         * @throws InterruptedException
         */
        virtual void waitForFreeSlots(const int count) /* throws InterruptedException */ = 0;

        /**
         * Resizes this ring buffer's capacity.
         * <p>
         * New capacity must be greater than current size.
         * </p>
         */
        virtual void recapacity(const int newCapacity) = 0;
};

} /* namespace direct_bt */

#endif /* RINGBUFFER_HPP_ */