2017-02-02 17:24:40 +01:00
|
|
|
//
|
|
|
|
// libtgvoip is free and unencumbered public domain software.
|
|
|
|
// For more information, see http://unlicense.org or the UNLICENSE file
|
|
|
|
// you should have received with this source code distribution.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef LIBTGVOIP_BLOCKINGQUEUE_H
|
|
|
|
#define LIBTGVOIP_BLOCKINGQUEUE_H
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <list>
|
|
|
|
#include "threading.h"
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2017-04-28 13:17:56 +02:00
|
|
|
namespace tgvoip{
|
2017-07-03 03:42:49 +02:00
|
|
|
|
|
|
|
template<typename T>
|
2017-04-28 13:17:56 +02:00
|
|
|
class BlockingQueue{
|
2017-02-02 17:24:40 +01:00
|
|
|
public:
|
2017-07-03 03:42:49 +02:00
|
|
|
BlockingQueue(size_t capacity) : semaphore(capacity, 0){
|
|
|
|
this->capacity=capacity;
|
|
|
|
overflowCallback=NULL;
|
|
|
|
};
|
|
|
|
|
|
|
|
~BlockingQueue(){
|
|
|
|
semaphore.Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Put(T thing){
|
|
|
|
MutexGuard sync(mutex);
|
2018-08-07 22:10:31 +02:00
|
|
|
queue.push_back(std::move(thing));
|
2017-07-03 03:42:49 +02:00
|
|
|
bool didOverflow=false;
|
|
|
|
while(queue.size()>capacity){
|
|
|
|
didOverflow=true;
|
|
|
|
if(overflowCallback){
|
2018-08-07 22:10:31 +02:00
|
|
|
overflowCallback(std::move(queue.front()));
|
2017-07-03 03:42:49 +02:00
|
|
|
queue.pop_front();
|
|
|
|
}else{
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!didOverflow)
|
|
|
|
semaphore.Release();
|
|
|
|
}
|
|
|
|
|
|
|
|
T GetBlocking(){
|
|
|
|
semaphore.Acquire();
|
|
|
|
MutexGuard sync(mutex);
|
2018-08-07 22:10:31 +02:00
|
|
|
return GetInternal();
|
2017-07-03 03:42:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
T Get(){
|
|
|
|
MutexGuard sync(mutex);
|
|
|
|
if(queue.size()>0)
|
|
|
|
semaphore.Acquire();
|
2018-08-07 22:10:31 +02:00
|
|
|
return GetInternal();
|
2017-07-03 03:42:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned int Size(){
|
|
|
|
return queue.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PrepareDealloc(){
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetOverflowCallback(void (*overflowCallback)(T)){
|
|
|
|
this->overflowCallback=overflowCallback;
|
|
|
|
}
|
2017-02-02 17:24:40 +01:00
|
|
|
|
|
|
|
private:
|
2017-07-03 03:42:49 +02:00
|
|
|
T GetInternal(){
|
|
|
|
//if(queue.size()==0)
|
|
|
|
// return NULL;
|
2018-08-07 22:10:31 +02:00
|
|
|
T r=std::move(queue.front());
|
2017-07-03 03:42:49 +02:00
|
|
|
queue.pop_front();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
list<T> queue;
|
2017-02-02 17:24:40 +01:00
|
|
|
size_t capacity;
|
2017-04-28 13:17:56 +02:00
|
|
|
//tgvoip_lock_t lock;
|
|
|
|
Semaphore semaphore;
|
2018-05-15 20:23:46 +02:00
|
|
|
Mutex mutex;
|
2017-07-03 03:42:49 +02:00
|
|
|
void (*overflowCallback)(T);
|
2017-02-02 17:24:40 +01:00
|
|
|
};
|
2017-04-28 13:17:56 +02:00
|
|
|
}
|
2017-02-02 17:24:40 +01:00
|
|
|
|
|
|
|
#endif //LIBTGVOIP_BLOCKINGQUEUE_H
|