Рейтинг: 5 / 5

Звезда активнаЗвезда активнаЗвезда активнаЗвезда активнаЗвезда активна
 
#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):

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;
    }
}
Now we can use it like:
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