15
15
#include < stdexcept>
16
16
#include < array>
17
17
#include < limits>
18
+ #include < bitset>
18
19
#include < stddef.h>
19
20
#include " threading.h"
20
21
#include " utils.h"
@@ -88,37 +89,24 @@ namespace tgvoip{
88
89
bool bufferProvided;
89
90
};
90
91
91
- class BufferPool {
92
- public:
93
- TGVOIP_DISALLOW_COPY_AND_ASSIGN (BufferPool);
94
- BufferPool (unsigned int size, unsigned int count);
95
- ~BufferPool ();
96
- unsigned char * Get ();
97
- void Reuse (unsigned char * buffer);
98
- size_t GetSingleBufferSize ();
99
- size_t GetBufferCount ();
100
-
101
- private:
102
- uint64_t usedBuffers;
103
- int bufferCount;
104
- size_t size;
105
- unsigned char * buffers[64 ];
106
- Mutex mutex;
107
- };
108
-
109
92
class Buffer {
110
93
public:
111
94
Buffer (size_t capacity){
112
- if (capacity>0 )
95
+ if (capacity>0 ){
113
96
data=(unsigned char *) malloc (capacity);
114
- else
97
+ if (!data)
98
+ throw std::bad_alloc ();
99
+ }else {
115
100
data=NULL ;
101
+ }
116
102
length=capacity;
117
103
};
118
104
TGVOIP_DISALLOW_COPY_AND_ASSIGN (Buffer); // use Buffer::CopyOf to copy contents explicitly
119
105
Buffer (Buffer&& other) noexcept {
120
106
data=other.data ;
121
107
length=other.length ;
108
+ freeFn=other.freeFn ;
109
+ reallocFn=other.reallocFn ;
122
110
other.data =NULL ;
123
111
};
124
112
Buffer (BufferOutputStream&& stream){
@@ -131,17 +119,29 @@ namespace tgvoip{
131
119
length=0 ;
132
120
}
133
121
~Buffer (){
134
- if (data)
135
- free (data);
122
+ if (data){
123
+ if (freeFn)
124
+ freeFn (data);
125
+ else
126
+ free (data);
127
+ }
136
128
data=NULL ;
129
+ length=0 ;
137
130
};
138
131
Buffer& operator =(Buffer&& other){
139
132
if (this !=&other){
140
- if (data)
141
- free (data);
133
+ if (data){
134
+ if (freeFn)
135
+ freeFn (data);
136
+ else
137
+ free (data);
138
+ }
142
139
data=other.data ;
143
140
length=other.length ;
141
+ freeFn=other.freeFn ;
142
+ reallocFn=other.reallocFn ;
144
143
other.data =NULL ;
144
+ other.length =0 ;
145
145
}
146
146
return *this ;
147
147
}
@@ -174,23 +174,47 @@ namespace tgvoip{
174
174
memcpy (data+dstOffset, ptr, count);
175
175
}
176
176
void Resize (size_t newSize){
177
- data=(unsigned char *) realloc (data, newSize);
177
+ if (reallocFn)
178
+ data=(unsigned char *) reallocFn (data, newSize);
179
+ else
180
+ data=(unsigned char *) realloc (data, newSize);
181
+ if (!data)
182
+ throw std::bad_alloc ();
178
183
length=newSize;
179
184
}
180
185
size_t Length () const {
181
186
return length;
182
187
}
183
188
bool IsEmpty () const {
184
- return length==0 ;
189
+ return length==0 || !data ;
185
190
}
186
191
static Buffer CopyOf (const Buffer& other){
192
+ if (other.IsEmpty ())
193
+ return Buffer ();
187
194
Buffer buf (other.length );
188
195
buf.CopyFrom (other, other.length );
189
196
return buf;
190
197
}
198
+ static Buffer CopyOf (const Buffer& other, size_t offset, size_t length){
199
+ if (offset+length>other.Length ())
200
+ throw std::out_of_range (" offset+length out of bounds" );
201
+ Buffer buf (length);
202
+ buf.CopyFrom (other, length, offset);
203
+ return buf;
204
+ }
205
+ static Buffer Wrap (unsigned char * data, size_t size, std::function<void (void *)> freeFn, std::function<void*(void *, size_t )> reallocFn){
206
+ Buffer b=Buffer ();
207
+ b.data =data;
208
+ b.length =size;
209
+ b.freeFn =freeFn;
210
+ b.reallocFn =reallocFn;
211
+ return b;
212
+ }
191
213
private:
192
214
unsigned char * data;
193
215
size_t length;
216
+ std::function<void (void *)> freeFn;
217
+ std::function<void *(void *, size_t )> reallocFn;
194
218
};
195
219
196
220
template <typename T, size_t size, typename AVG_T=T> class HistoricBuffer {
@@ -199,26 +223,26 @@ namespace tgvoip{
199
223
std::fill (data.begin (), data.end (), (T)0 );
200
224
}
201
225
202
- AVG_T Average (){
226
+ AVG_T Average () const {
203
227
AVG_T avg=(AVG_T)0 ;
204
- for (T& i:data){
228
+ for (T i:data){
205
229
avg+=i;
206
230
}
207
231
return avg/(AVG_T)size;
208
232
}
209
233
210
- AVG_T Average (size_t firstN){
234
+ AVG_T Average (size_t firstN) const {
211
235
AVG_T avg=(AVG_T)0 ;
212
236
for (size_t i=0 ;i<firstN;i++){
213
237
avg+=(*this )[i];
214
238
}
215
239
return avg/(AVG_T)firstN;
216
240
}
217
241
218
- AVG_T NonZeroAverage (){
242
+ AVG_T NonZeroAverage () const {
219
243
AVG_T avg=(AVG_T)0 ;
220
244
int nonZeroCount=0 ;
221
- for (T& i:data){
245
+ for (T i:data){
222
246
if (i!=0 ){
223
247
nonZeroCount++;
224
248
avg+=i;
@@ -234,18 +258,18 @@ namespace tgvoip{
234
258
offset=(offset+1 )%size;
235
259
}
236
260
237
- T Min (){
261
+ T Min () const {
238
262
T min=std::numeric_limits<T>::max ();
239
- for (T& i:data){
263
+ for (T i:data){
240
264
if (i<min)
241
265
min=i;
242
266
}
243
267
return min;
244
268
}
245
269
246
- T Max (){
270
+ T Max () const {
247
271
T max=std::numeric_limits<T>::min ();
248
- for (T& i:data){
272
+ for (T i:data){
249
273
if (i>max)
250
274
max=i;
251
275
}
@@ -257,6 +281,15 @@ namespace tgvoip{
257
281
offset=0 ;
258
282
}
259
283
284
+ T operator [](size_t i) const {
285
+ assert (i<size);
286
+ // [0] should return the most recent entry, [1] the one before it, and so on
287
+ ptrdiff_t _i=offset-i-1 ;
288
+ if (_i<0 )
289
+ _i=size+_i;
290
+ return data[_i];
291
+ }
292
+
260
293
T& operator [](size_t i){
261
294
assert (i<size);
262
295
// [0] should return the most recent entry, [1] the one before it, and so on
@@ -266,13 +299,59 @@ namespace tgvoip{
266
299
return data[_i];
267
300
}
268
301
269
- size_t Size (){
302
+ size_t Size () const {
270
303
return size;
271
304
}
272
305
private:
273
306
std::array<T, size> data;
274
307
ptrdiff_t offset=0 ;
275
308
};
309
+
310
+ template <size_t bufSize, size_t bufCount> class BufferPool {
311
+ public:
312
+ TGVOIP_DISALLOW_COPY_AND_ASSIGN (BufferPool);
313
+ BufferPool (){
314
+ bufferStart=(unsigned char *)malloc (bufSize*bufCount);
315
+ if (!bufferStart)
316
+ throw std::bad_alloc ();
317
+ };
318
+ ~BufferPool (){
319
+ assert (usedBuffers.none ());
320
+ free (bufferStart);
321
+ };
322
+ Buffer Get (){
323
+ auto freeFn=[this ](void * _buf){
324
+ assert (_buf!=NULL );
325
+ unsigned char * buf=(unsigned char *)_buf;
326
+ size_t offset=buf-bufferStart;
327
+ assert (offset%bufSize==0 );
328
+ size_t index =offset/bufSize;
329
+ assert (index <bufCount);
330
+
331
+ MutexGuard m (mutex);
332
+ assert (usedBuffers.test (index ));
333
+ usedBuffers[index ]=0 ;
334
+ };
335
+ auto resizeFn=[](void * buf, size_t newSize)->void *{
336
+ if (newSize>bufSize)
337
+ throw std::invalid_argument (" newSize>bufferSize" );
338
+ return buf;
339
+ };
340
+ MutexGuard m (mutex);
341
+ for (size_t i=0 ;i<bufCount;i++){
342
+ if (!usedBuffers[i]){
343
+ usedBuffers[i]=1 ;
344
+ return Buffer::Wrap (bufferStart+(bufSize*i), bufSize, freeFn, resizeFn);
345
+ }
346
+ }
347
+ throw std::bad_alloc ();
348
+ }
349
+
350
+ private:
351
+ std::bitset<bufCount> usedBuffers;
352
+ unsigned char * bufferStart;
353
+ Mutex mutex;
354
+ };
276
355
}
277
356
278
357
#endif // LIBTGVOIP_BUFFERINPUTSTREAM_H
0 commit comments