#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; } } #endifUSAGE:
#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