#ifndef _NORTOS_H
#define _NORTOS_H
typedef void(*fP)(void);
/// @brief class for finctional pointers queue with supporting of transfer of parameters
class fQ {
private:
int first;
int last;
int length;
fP * fQueue;
public:
fQ(int sizeQ);
~fQ();
int push(fP);
int pull(void);
};
fQ::fQ(int sizeQ){ // initialization of Queue
fQueue = new fP[sizeQ];
last = 0;
first = 0;
length = sizeQ;
};
fQ::~fQ(){ // initialization of Queue
delete [] fQueue;
};
int fQ::push(fP pointerF){ // push element from the queue
if ((last+1)%length == first){
return 1;
}
fQueue[last++] = pointerF;
last = last%length;
return 0;
};
int fQ::pull(void){ // pull element from the queue
if (last != first){
fQueue[first++]();
first = first%length;
return 0;
}
else{
return 1;
}
};
template <typename T>
class fQP {
private:
int first;
int last;
int length;
typedef void (*FunctionPointer)(T*);
FunctionPointer* FP_Queue;
T* PARAMS_array;
public:
fQP(int sizeQ);
~fQP();
int push(void (*pointerQ)(T*), T parameterQ);
int pull();
};
template <typename T>
fQP<T>::fQP(int sizeQ) {
FP_Queue = new FunctionPointer[sizeQ];
PARAMS_array = new T[sizeQ];
last = 0;
first = 0;
length = sizeQ;
}
template <typename T>
fQP<T>::~fQP() {
delete[] FP_Queue;
delete[] PARAMS_array;
}
template <typename T>
int fQP<T>::push(void (*pointerQ)(T*), T parameterQ) {
if ((last + 1) % length == first) return 1;
FP_Queue[last] = pointerQ;
PARAMS_array[last] = parameterQ;
last = (last + 1) % length;
return 0;
}
template <typename T>
int fQP<T>::pull() {
FunctionPointer pullVar;
if (last != first) {
T* Params = &PARAMS_array[first];
pullVar = FP_Queue[first];
first = (first + 1) % length;
pullVar(Params);
return 0;
}
else {
return 1;
}
}
#endif
USAGE:#include <iostream>
#include <chrono>
#include <random>
#include <future>
#include <thread>
#include <unistd.h>
#include "nortos.h"
using namespace std;
random_device dev;
mt19937 rng(dev());
uniform_int_distribution<mt19937::result_type> dist1_1000(1,1000);
fQ F1(16);
fQ F2(12);
fQ F3(18);
fQP<int32_t> F4(20);
void SomeTestFunctionOne(void){
static int i = 0;
cout << "SomeTestFunctionOne #"<< i++ << endl;
}
void SomeTestFunctionTwo(void){
static int i = 0;
cout << "SomeTestFunctionTwo #"<< i++ << endl;
}
void SomeTestFunctionThree(void){
static int i = 0;
cout << "SomeTestFunctionThree #"<< i++ << endl;
}
void SomeTestFunctionFour(int32_t * parameter){
static int i = 0;
cout << "SomeTestFunctionFour #"<< i++ << " passed parameter:" << *parameter<< " located at addr: "<< parameter << endl;
}
volatile int FlagStop = 0;
using namespace std::this_thread; // sleep_for, sleep_until
using namespace std::chrono;
void Timer1() {
while(!FlagStop){
F1.push(SomeTestFunctionOne);
sleep_for(milliseconds(dist1_1000(rng)));
}
}
void Timer2() {
while(!FlagStop){
F2.push(SomeTestFunctionTwo);
sleep_for(milliseconds(dist1_1000(rng)));
}
}
void Timer3() {
while(!FlagStop){
F3.push(SomeTestFunctionThree);
sleep_for(milliseconds(dist1_1000(rng)));
}
}
void Timer4() {
while(!FlagStop){
F4.push(SomeTestFunctionFour,42);
sleep_for(milliseconds(dist1_1000(rng)));
}
}
int main()
{
auto Q_one = async(launch::async, &Timer1);
auto Q_two = async(launch::async, &Timer2);
auto Q_three = async(launch::async, &Timer3);
auto Q_four = async(launch::async, &Timer4);
for(;;){
F1.pull();
F2.pull();
F3.pull();
F4.pull();
usleep(10000);
}
return 0;
}
In case we need to pass parameter's values(for easier usage only):
Now we can use it like: template <typename T>class fQP {private:int first;int last;int length;typedef void (*FunctionPointer)(T);FunctionPointer* FP_Queue;T* PARAMS_array;public:fQP(int sizeQ);~fQP();int push(void (*pointerQ)(T), T parameterQ);int pull();};template <typename T>fQP<T>::fQP(int sizeQ) {FP_Queue = new FunctionPointer[sizeQ];PARAMS_array = new T[sizeQ];last = 0;first = 0;length = sizeQ;}template <typename T>fQP<T>::~fQP() {delete[] FP_Queue;delete[] PARAMS_array;}template <typename T>int fQP<T>::push(void (*pointerQ)(T), T parameterQ) {if ((last + 1) % length == first) return 1;FP_Queue[last] = pointerQ;PARAMS_array[last] = parameterQ;last = (last + 1) % length;return 0;}template <typename T>int fQP<T>::pull() {FunctionPointer pullVar;if (last != first) {T Params = PARAMS_array[first];pullVar = FP_Queue[first];first = (first + 1) % length;pullVar(Params);return 0;}else {return 1;}}
void SomeTestFunctionFour(int32_t parameter){
static int i = 0;
cout << "SomeTestFunctionFour #"<< i++ << " passed parameter:" << parameter << endl;
}
F4.push(SomeTestFunctionFour,42);
Be careful with handling arrays, passing their pointer to push function, they should be static, otherwise better to envelop them into structure/class - in this case memory for storage of parameters will be allocated in queue
