mesytec-mnode/external/taskflow-3.8.0/3rd-party/ff/squeue.hpp
2025-01-04 01:25:05 +01:00

236 lines
5.9 KiB
C++

/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*!
* \link
* \file squeue.hpp
* \ingroup aux_classes
*
* \brief Simple yet efficient (not concurrent) unbounded FIFO queue.
*
* This queue have to be used by one single thread at a time, or, each method
* call have to be protected by a mutex lock. For an unbounded
* producer-consumer queue implementation see \ref ubuffer.hpp
*
*/
/* ***************************************************************************
*
* FastFlow is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3 as
* published by the Free Software Foundation.
* Starting from version 3.0.1 FastFlow is dual licensed under the GNU LGPLv3
* or MIT License (https://github.com/ParaGroup/WindFlow/blob/vers3.x/LICENSE.MIT)
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*
****************************************************************************
*/
#ifndef FF_SQUEUE_HPP
#define FF_SQUEUE_HPP
#include <stdlib.h>
namespace ff {
/**
* \class squeue
* \ingroup aux_classes
*
* \brief Unbound sequential FIFO queue
*/
template <typename T>
class squeue {
private:
struct data_type {
data_type():h(-1),t(-1),entry(0) {};
data_type(int h, int t, T * entry):h(h),t(t),entry(entry) {}
data_type(const data_type & de):h(de.h),t(de.t),entry(de.entry) {}
int h;
int t;
T * entry;
};
typedef T elem_type;
protected:
enum {DATA_CHUNK=1024, SQUEUE_CHUNK=4096};
inline T * newchunk() {
T * v =(T *)malloc(chunk*sizeof(T));
return v;
}
inline void deletechunk(int idx) {
free(data[idx].entry);
data[idx].entry = NULL;
}
public:
squeue(size_t chunk=SQUEUE_CHUNK):data(0),datacap(DATA_CHUNK),
nelements(0),
head(0),tail(0),chunk(chunk) {
data = (data_type *)malloc(datacap*sizeof(data_type));
data[0] = data_type(0, -1, newchunk());
}
~squeue() {
if (!data) return;
for(unsigned int i=0;i<=tail;++i)
if (data[i].entry) free(data[i].entry);
free(data);
}
inline void push_back(const elem_type & elem) {
T * current = data[tail].entry;
int current_tail = data[tail].t++;
if ((unsigned)current_tail == (chunk-1)) {
if (tail == (datacap-1)) {
datacap += DATA_CHUNK;
data = (data_type *)realloc(data, datacap*sizeof(data_type));
}
T * v = newchunk();
data[++tail] = data_type(0,0,v);
current = v;
current_tail=-1;
}
current[current_tail+1] = elem;
++nelements;
}
inline void pop_back() {
if (!nelements) return;
T * current = data[tail].entry;
int current_tail = data[tail].t--;
current[current_tail].~T();
--nelements;
if (!current_tail && (tail>0)) {
deletechunk(tail);
--tail;
data[tail].t = chunk-1;
}
}
inline elem_type& back() {
if (!nelements) return *(elem_type*)0;
T * current = data[tail].entry;
int current_tail = data[tail].t;
return current[current_tail];
}
inline void pop_front() {
if (!nelements) return;
T * current = data[head].entry;
int current_head = data[head].h++;
current[current_head].~T();
--nelements;
if (((unsigned)current_head==(chunk-1)) && (tail>head)) {
deletechunk(head);
++head;
}
}
inline elem_type& front() {
if (!nelements) return *(elem_type*)0;
T * current = data[head].entry;
int current_head = data[head].h;
return current[current_head];
}
inline elem_type& at(size_t idx) {
if (!nelements || idx > nelements) return *(elem_type*)0;
T * current = data[head].entry;
int current_head = data[head].h+idx;
return current[current_head];
}
inline size_t size() const { return nelements; }
private:
data_type * data;
size_t datacap;
size_t nelements;
unsigned int head;
unsigned int tail;
size_t chunk;
};
} // namespace ff
#endif /* FF_SQUEUE_HPP */
#if 0
#include <iosfwd>
#include <deque>
#include <squeue.hpp>
int main() {
std::deque<int> e;
ffTime(START_TIME);
for(int i=0;i<200000;++i) e.push_back(i);
while(e.size()) {
//std::cout << d.back() << " ";
e.pop_back();
}
ffTime(STOP_TIME);
std::cerr << "DONE deque, time= " << ffTime(GET_TIME) << " (ms)\n";
squeue<int> d;
ffTime(START_TIME);
for(int i=0;i<200000;++i) d.push_back(i);
while(d.size()) {
//std::cout << d.back() << " ";
d.pop_back();
}
ffTime(STOP_TIME);
std::cerr << "DONE squeue, time= " << ffTime(GET_TIME) << " (ms)\n";
for(int i=0;i<1500;++i) d.push_back(i);
for(int i=0;i<500;++i) {
std::cout << d.back() << " ";
d.pop_back();
}
while(d.size()) {
std::cout << d.front() << " ";
d.pop_front();
}
std::cerr << "size= " << d.size() << "\n";
return 0;
}
#endif