Efficient generic buffer queue for sequential processing - c++

I have a producer-consumer queue which is being updated by parallel programs. The queue is queried for various statistics like mean or standard deviation or variance or something else on the current queue contents. For mean, this is the code, I use
class BufferQueue {
const int nMaxQueueSize_;
int* values;
int head, tail;
double sum;
::utils::FastMutex queue_mutex;
public:
BufferQueue(const int nMaxQueueSize) :
nMaxQueueSize_(nMaxQueueSize) {
head = tail = 0;
sum = 0;
values = new int[nMaxQueueSize_];
}
void enqueue(int val) {
values[head] = val;
if ((head + 1) % nMaxQueueSize_ == tail) {
queue_mutex.lock();
sum = val.value_point - values[tail].value_point;
utils::memory_barrier();
head = (1 + head) % nMaxQueueSize_;
tail = (1 + tail) % nMaxQueueSize_;
queue_mutex.unlock();
} else {
queue_mutex.lock();
sum += val.value_point;
utils::memory_barrier();
head = (1 + head) % nMaxQueueSize_;
queue_mutex.unlock();
}
}
bool dequeue() {
if (head != tail) {
queue_mutex.lock();
sum -= values[tail].value_point;
utils::memory_barrier();
tail = (1 + tail) % nMaxQueueSize_;
queue_mutex.unlock();
return true;
} else {
sum = 0;
return false;
}
}
MarketSpreadPoint& operator[](int i) {
return values[ (tail + i) % nMaxQueueSize_ ];
}
inline int getSize() {
return (head - tail + nMaxQueueSize_) % nMaxQueueSize_;
}
inline double average() {
queue_mutex.lock();
double result = sum / getSize();
queue_mutex.unlock();
return result;
}
~BufferQueue() {
delete values;
}
};
NOTE: One important thing to remember is that only one operation is being performed. Neither do I want to repeat code by writing separate implementations like BufferQueueAverage, BufferQueueVariance etc. I want very limit code redundancy(compiler optimizations). Even conditioning on type of queue for every update seems sub-optimal.
inline double average() {
queue_mutex.lock();
if(type_is_average){
double result = sum / getSize();
}else if(type_is_variance){
/// update accordingly.
}
double result = sum / getSize();
queue_mutex.unlock();
return result;
}
What can be a good alternative to this idea ?
Note: In this implementation, if queue is full, head automatically make the tail to move forward. In other words, the oldest element is deleted automatically.
Thanks

So you want to separate the queue from the statistics. I see two possible solutions:
Use a pattern like Template Method or Strategy to factor out the dependency.
Use a template that does this.
Assuming that all statistics you gather can gathered incrementally, the latter could look similar to the following (just meant as pseudo code):
class StatisticsMean
{
private:
int n = 0;
double mean = 0.0;
public:
void addSample(int s) { ++n; mean += (s - mean) / n; }
void removeSample(int s) { ... }
double getStatistic() const { return mean; }
}
template <typename TStatistics>
class BufferQueue
{
TStatistics statistics;
...
void enqueue(int val)
{
...
statistics.addSample(val);
}
...
double getStatistic() const { return statistics.getStatistic(); }
}
The template approach gives you full compile-time optimization. You can achieve the same with the Template Method pattern. This would also allow you to have distinct names for the getters (getStatistic() in the above example).
This could look similar to this:
class AbstractBufferQueue
{
virtual void addSample(int s) = 0;
virtual void removeSample(int s) = 0;
void enqueue(int val)
{
...
addSample(val);
}
}
class BufferQueueAverage : public AbstractBufferQueue
{
int n;
double mean;
void addSample(int s) { ++n; mean += (s - mean) / n; }
void removeSample(int s) { ... }
double getAverage() const { return mean; }
}

One way to do what you're asking is by using template classes.
First, decide on a common interface that an accumulator will have. It might be something like:
class accumulator
{
public:
typedef double value_type;
public:
void push(int v); // Called when pushing a new value.
void pop(int v); // Called when popping a new value;
value_type result(size_t n) const; // Returns the current accumulation.
};
As a special case, mean_accumulator could be this:
class mean_accumulator
{
public:
typedef double value_type;
public:
mean_accumulator() : m_sum{0} {}
void push(int v) { m_sum += v; }
void pop(int v); { m_sum -= v; }
double result(size_t n) const { return m_sum / n; };
private:
int m_sum;
};
Now, parameterize your queue by Accumulator, and call it when necessary (while you're at it, note that boost::circular_buffer has much of what you need for the implementation:
template<class Accumulator>
class queue
{
private:
boost::circular_buffer<int> m_buf;
std::mutex m_m;
public:
void push(int v)
{
// Lock the mutex, push to the circular buffer, and the accumulator
}
bool pop()
{
// Lock the mutex; if relevant, update the accumulator and pop the circular buffer
}
typename Accumulator::value_type result() const
{
// Lock the mutex and return the accumulator's result.
}
};

Related

How to restructure this code without duplicating too much code?

class
{
public:
void func(const int val, const bool flag)
{
if(flag)
{
while(!lower.empty() && val <= lower.top())
{
// do a bunch of stuff with lower
}
}
else
{
while(!higher.empty() && val >= higher.top())
{
// do a bunch of stuff with higher, but it's the same stuff as would've done
// for lower
}
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
I'm trying to figure out a better way to write the clauses because currently, I have a lot of duplicate code in both. The only difference is one clause operates on lower and the other on higher and the <= in the first clause is changed to >= higher in the second one.
I could wrap the clause in a helper function and call it in each clause (and pass in the lower and higher as an argument), e.g.,
class
{
public:
void func(const int val, const bool flag)
{
if(flag)
{
helper(lower, comparer);
}
else
{
helper(lower, comparer);
}
}
void helper(std::stack<int> &st)
{
// do a bunch of stuff with st
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
I'm not sure if this is a good idea and if it is, I'm not sure how to get around the >= vs. <=. I'm hoping for suggestions on my design!
You can do something like the following:
class
{
public:
void func(const int val, const bool flag)
{
std::stack<int> *st;
bool (*compare)(int, int);
if (flag)
{
st = &lower;
compare = [](int a, int b){ return a <= b; };
}
else
{
st = &higher;
compare = [](int a, int b){ return a >= b; };
}
while (!st->empty() && compare(val, st->top()))
{
// do a bunch of stuff with *st
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
Alternatively, using a helper would certainly work, too:
class
{
public:
void func(const int val, const bool flag)
{
if (flag)
func_helper(lower, val, std::less_equal{});
else
func_helper(higher, val, std::greater_equal{});
}
private:
std::stack<int> lower;
std::stack<int> higher;
template<typename Comparer>
void func_helper(stack<int> &st, const int val, Comparer compare)
{
while (!st.empty() && compare(val, st.top()))
{
// do a bunch of stuff with st
}
}
}
How about something like this
class
{
public:
void func(const int val, const bool flag)
{
int sign = 1;
std::stack<int>* higher_or_lower = &higher;
if(flag)
{
higher_or_lower = &lower;
sign = -1;
}
while(!higher_or_lower->empty() && sign*val >= sign*higher_or_lower->top())
{
// do a bunch of stuff with higher_or_lower
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
}
The higher_or_lower covers both stacks and the sign takes care of less than vs. greater than.
Or a bit more compact:
class C
{
public:
void func(const int val, const bool flag)
{
const std::stack<int>* st[] = {&lower, &higher};
bool (*compare[])(int, int) = { [](int a, int b) { return a <= b; } , [](int a, int b) { return a >= b; } };
while (!st[flag]->empty() && compare[flag](val, st[flag]->top()))
{
// do a bunch of stuff with *st
}
}
private:
std::stack<int> lower;
std::stack<int> higher;
};

Setting a maximum possible value to a variable C++

it's supposed to be an easy question, but i couldnt find the answer on google. So, how do i assign a maximum possible value to a variable?
So i want my variable to be no more than 10 as apossible value no matter what
int example;
example = ?;
You might create a custom class to handle your needs, something like:
template <int Min, int Max>
class BoundedValue
{
public:
BoundedValue(int value = Min) : mValue(Min) { set_value(value); }
int get_value() const { return mValue; }
void set_value(int value) {
if (value < Min || Max < value) {
throw std::out_of_range("!"); // Or other error handling as clamping
// value = std::clamp(value, Min, Max);
}
mValue = value;
}
BoundedValue& operator= (int value) { set_value(value); }
BoundedValue& operator ++() { set_value(mValue + 1); return *this; }
BoundedValue operator ++(int) { auto tmp = *this; ++*this; return tmp; }
// other convenient functions
operator int() const { return mValue; }
private:
int mValue = Min;
};
And then use it:
BoundedValue<0, 10> example;
++example;
example = 11; // "Error"

How to use Function Pointer as a parameter in a Class

I am trying to construct a class that is essentially a queue of futures that are all handled asynchronously and eventually all stored when main wants to get their values. I am having trouble creating the function parameters that will accept these functions and their arguments in order to create an async operation that is then pushed in to the queue of futures. The areas in question are the call constructor and the member function add(). Here is what I have so far:
#include <iostream>
#include <queue>
#include <future>
#include <thread>
using namespace std;
using longInt = unsigned long long int;
//prototypes
longInt isPrime(longInt);
template <typename return_type>
class TaskQueue {
private:
queue<future<return_type>> tasks;
public:
//return a copy of the queue
queue<future<return_type>> copy() const {
return tasks;
}
//default constructor
//does nothing, waits for input
TaskQueue() {
//do nothing
}
//call constructors
//adds task to queue
TaskQueue(return_type (*func)(), Args&& ... args) {
tasks.push(new async(func, args));
}
//copy constructor
//copies another queue to this one
TaskQueue(const queue<future<return_type>> & in) {
tasks = in.copy();
}
//setter and getter functions
//inserts a new task into the queue
void add(return_type(*func)(), Args&& ... args) {
tasks.push(new aync(in, args));
}
//returns true if the task at the top of the queue is ready
bool valid() {
return tasks.front().valid();
}
//gets the value, if the value is not ready, waits for it to be ready
//pops the top task after getting it
return_type get() {
return_type temp = tasks.top().get();
tasks.pop();
return temp;
}
//waits for the value of the top of the queue to become ready
void wait() {
tasks.top().wait();
}
};
int main() {
TaskQueue<longInt> checkPrimes;
checkPrimes.add(isPrime, 5);
longInt test = checkPrimes.get();
cout << test << endl;
}
//returns the number if it is prime or 0 if it is not
longInt isPrime(longInt n) {
if (n <= 3) {
if (n > 1) {
return n;
}
return 0;
}
if (n % 2 == 0 || n % 3 == 0) {
return 0;
}
for (unsigned short i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return 0;
}
}
return n;
}
A compilable version:
template <typename return_type>
class TaskQueue {
private:
queue<future<return_type>> tasks;
public:
//return a copy of the queue
queue<future<return_type>> copy() const {
return tasks;
}
//default constructor
//does nothing, waits for input
TaskQueue() {
//do nothing
}
//call constructors
//adds task to queue
template <typename ... Args, typename ... Ts>
TaskQueue(return_type (*func)(Ts...), Args&& ... args) {
tasks.push(std::async(func, args...));
}
//copy constructor
//copies another queue to this one
TaskQueue(const queue<future<return_type>> & in) {
tasks = in.copy();
}
//setter and getter functions
//inserts a new task into the queue
template <typename ... Args, typename ... Ts>
void add(return_type(*func)(Ts...), Args&& ... args) {
tasks.push(std::async(func, args...));
}
//returns true if the task at the top of the queue is ready
bool valid() {
return tasks.front().valid();
}
//gets the value, if the value is not ready, waits for it to be ready
//pops the top task after getting it
return_type get() {
return_type temp = tasks.front().get();
tasks.pop();
return temp;
}
//waits for the value of the top of the queue to become ready
void wait() {
tasks.top().wait();
}
};
Demo
I think you can define a type for the function you want to pass and then apply them in the order you want. For example, the following snippet will define a intfunc type, which is a function that takes an int and returns an int.
typedef int (*intfunc) (int);
We can then define functions like
int sum2(int n) {
return n + 2;
}
int mult3(int n) {
return 3 * n;
}
and give them to a vector,
vector<intfunc> funcs;
vector<intfunc>::iterator func;
int start = 0;
funcs.push_back(sum2);
funcs.push_back(mult3);
cin >> start;
for (func = funcs.begin(); func != funcs.end(); ++func)
{
start = (*func)(start);
}
cout << start << endl;
If we enter 5 to that program, it will return 21 as expected.

Generic Segment Tree implementation using C++ Templates

I am trying to make a generic Segment Tree Class for updates and range queries.
Instead of assuming that the elements would just be integers and the operation to be done over a range of elements would be their sum or product, i would want the user to provide the type T of the element and a function, which i named compose.
This function takes in two parameters of type T and returns a value of the same type T. This return value is the result when that desired operation is performed over range of 2 elements which i can use to perform that same operation on a range of any number of elements.
The class is as follows:
#include <functional>
template<class T>
class SegmentTree {
public:
class binary_function_unitype: public std::binary_function<T,T,T> {
public:
virtual T operator() (T arg1, T arg2) {};
};
private:
class Node {
public:
T value;
int seg_start, seg_end;
Node* left;
Node* right;
Node (T value, int seg_start, int seg_end, Node* left=0, Node* right=0) {
this->value = value;
this->seg_start = seg_start;
this->seg_end = seg_end;
this->left = left;
this->right = right;
}
};
// Not expecting the compose function to be robust enough.
T composeUtil (T arg1, T arg2) {
if (arg1!=0 && arg2!=0)
return compose(arg1,arg2);
else if (arg1!=0)
return arg1;
else if (arg2!=0)
return arg2;
}
// Creating the Segment Tree.
Node* createTree (T leaves[], int start, int end) {
// base case - leaf of tree.
if (start==end)
return new Node(leaves[start],start,start,0,0);
// general case.
int mid = start + (end-start)/2;
Node* left = createTree(leaves,start,mid);
Node* right = createTree(leaves,mid+1,end);
T retValue = composeUtil(left->value,right->value);
return new Node(retValue,start,end,left,right);
}
// Range Query helper.
T queryUtil (Node* root, int start, int end) {
int seg_start = root->seg_start, seg_end = root->seg_end;
if (seg_start>end || seg_end<start)
return 0;
else if (seg_start>=start && seg_end<=end)
return root->value;
else
return compose( queryUtil(root->left,start,end), queryUtil(root->right,start,end));
}
// Helper function for Updating the Segment Tree.
void updateUtil (Node* root, int position, T updatedValue) {
int seg_start = root->seg_start, seg_end = root->seg_end;
if(seg_start>position || seg_end<position)
return;
else if(seg_start==seg_end)
root->value = updatedValue;
else
root->value = composeUtil(root->left->value,root->right->value);
}
// Freeing the memory allocated to the Segment Tree.
void destroyTree(Node* root) {
if (root->left!=0)
destroyTree(root->left);
if (root->right!=0)
destroyTree(root->right);
delete root;
}
Node* root;
binary_function_unitype compose;
public:
SegmentTree (T leaves[], binary_function_unitype compose, int start, int end) {
this->compose = compose;
this->root = createTree(leaves, start, end);
}
T query (int start, int end) {
return queryUtil(root, start, end);
}
void update (int position, T updatedValue) {
updateUtil(root, position, updatedValue);
}
~SegmentTree () {
destroyTree(root);
}
};
When I tried to use this class, it turns out that the compose function, which I took in as a paramater is not being used, on the contrary the one from the class binary_function_unitype is being used.
I expected that the function definition from the user would override the one in class binary_function_unitype and my work would be done. But that did not happen. The program using this class is as follows:
#include <iostream>
#include "SegmentTree.h"
using namespace std;
class Compose: public SegmentTree<int>::binary_function_unitype {
public:
int operator() (int arg1, int arg2) {
return arg1+arg2;
}
};
int main()
{
int num;
cin>>num;
int arr[num];
for(int i=0;i<num;i++)
cin>>arr[i];
Compose compose;
SegmentTree<int> segTree(arr, compose, 0, num-1);
int s,e;
cin>>s>>e;
cout<<segTree.query(s-1,e-1);
return 0;
}
Can somebody tell me whats the flaw in my approach or if I misunderstood some basic concept about using inheritance or templates in C++ ?
Thanks.
The constructor takes a binary_function_unitype by value, so it will slice.

Transient Copy Constructor weirdness

I've got this here class defined in a header file:
class E_IndexList {
public:
E_UIntegerList* l;
inline void *data() { // retrieve packed data: stride depends on type (range)
return l->data();
}
inline void insert(unsigned value) {
if (value > maxval[l->range]) {
promote();
insert(value);
} else {
l->push_back(value);
}
}
inline size_t size() {
return l->size();
}
inline unsigned long get(int index) {
return l->get(index);
}
void promote() {
if (l->range == E_UIntegerList::e_byte) {
E_UShortList *new_short_list = new E_UShortList(*((E_UByteList*)l));
delete l;
l = new_short_list;
} else if (l->range == E_UIntegerList::e_short) {
E_UIntList *new_int_list = new E_UIntList(*((E_UShortList*)l));
delete l;
l = new_int_list;
} else ASSERT(false);
}
// start off with bytes by default
E_IndexList() {
l = new E_UByteList;
}
E_IndexList(E_UIntegerList::int_bits range) {
switch(range) {
case E_UIntegerList::e_byte:
l = new E_UByteList;
break;
case E_UIntegerList::e_short:
l = new E_UShortList;
break;
case E_UIntegerList::e_int:
l = new E_UIntList;
break;
default:
ASSERT(false);
break;
}
}
E_IndexList(const E_IndexList& cpy) { // copy ctor
switch(cpy.l->range) {
case E_UIntegerList::e_byte:
l = new E_UByteList(((E_UByteList*)cpy.l)->list);
break;
case E_UIntegerList::e_short:
l = new E_UShortList(((E_UShortList*)cpy.l)->list);
break;
case E_UIntegerList::e_int:
l = new E_UIntList(((E_UShortList*)cpy.l)->list);
break;
default:
ASSERT(false);
break;
}
}
~E_IndexList() {
delete l;
}
};
Here are some more classes it makes use of:
static const unsigned long maxval[] = {0xff,0xffff,0xffffffff};
class E_UIntegerList {
public:
enum int_bits {e_byte = 0, e_short = 1, e_int = 2};
virtual ~E_UIntegerList() {}
int_bits range;
virtual void push_back(int i) = 0;
virtual void *data() = 0;
virtual size_t size() = 0;
virtual unsigned long get(int index) = 0;
};
struct E_UByteList:public E_UIntegerList {
std::vector<unsigned char> list;
E_UByteList() {
range = e_byte;
}
E_UByteList(const std::vector<unsigned char>& copy) {
list = copy;
}
inline void push_back(int i) {
list.push_back(i);
}
inline void *data() { return list.data(); }
inline size_t size() { return list.size(); }
inline unsigned long get(int index) { return list[index]; }
};
struct E_UShortList:public E_UIntegerList {
std::vector<unsigned short> list;
E_UShortList() {
range = e_short;
}
E_UShortList(const std::vector<unsigned short>& copy) {
list = copy;
}
E_UShortList(const E_UByteList& promotee) {
range = e_short;
list.assign(promotee.list.begin(),promotee.list.end()); // assignment should be compatible
}
inline void push_back(int i) {
list.push_back(i);
}
inline void *data() { return list.data(); }
inline size_t size() { return list.size(); }
inline unsigned long get(int index) { return list[index]; }
};
struct E_UIntList:public E_UIntegerList {
std::vector<unsigned int> list;
E_UIntList() {
range = e_int;
}
E_UIntList(const std::vector<unsigned int>& copy) {
list = copy;
}
E_UIntList(const E_UShortList& promotee) {
range = e_int;
list.assign(promotee.list.begin(),promotee.list.end());
}
inline void push_back(int i) {
list.push_back(i);
}
inline void *data() { return list.data(); }
inline size_t size() { return list.size(); }
inline unsigned long get(int index) { return list[index]; }
};
Now the way that I use this class is I have a std::vector<E_IndexList> that I use as a container of index lists.
The strange behavior is that when I run the program sometimes it has no problems and sometimes it asserts false.
So this is a big red flag for me because something super fishy is going on. I will very likely end up abandoning the entire E_IndexList until I start working on game netcode which is a long ways off. But, I'd like to know what's going on here.
Every ctor I have sets the range to a valid value out of the enum in E_UIntegerList, so how could that assertion ever get tripped? And I can't begin to come up with an explanation of why the behavior is inconsistent. The test that calls this code is not multi-threaded.
Your E_UByteList from-vector constructor does not set the range value.
The entire design is a bit shoddy; you should learn how to use constructor initializer lists, and I would probably endow the base class with a protected constructor that sets the range value and which can be invoked from within the derived constructors' initializers.
You didn't define an assignment operator. See rule of three.
Your constructors such as this one:
E_UByteList(const std::vector<unsigned char>& copy) {
list = copy;
}
do not initialise range from the parent E_UIntegerList class.