简体   繁体   中英

How to create a queue of function pointers in C++

I am trying to create a co-operative scheduler using C++, for which i need a queue that will contain function pointers.

Does the C++ queue STL library help in this context?

This is obviously the exact sort of problem std::queue was intended to help solve.

I would change a few things though. One would be to store an std::function instead of a raw pointer to a function:

struct task {
    int id;
    std::function<void()> f;
};

This allows you to pass essentially anything that can be invoked like a function, not just a pointer to an actual function. For one obvious example, you can use a lambda expression:

    task t { 1, [] {cout << "having fun!\n"; } };  
    q.push(t);
    auto tsk = q.front();
    tsk.f();

Since nearly the only thing you can do with a task is to invoke it, I'd also consider providing task with an overloaded operator() to do the invocation: void operator()() { f(); } void operator()() { f(); } , so if you just want to invoke a task, you could do something like this:

auto f = q.front();
f();

Your test program expanded to include these might look more like this:

#include <iostream>
#include <queue>
#include <functional>

using namespace std;

struct task {
    int id;
    std::function<void()> f;

    void operator()() { f(); }
};

queue<struct task> q;

void fun(void) {
    cout << "Having fun!" << endl;
}

int main() {

    cout << "Creating a task object" << endl;

    task t;
    t.id = 1;
    t.f = &fun;

    cout << "Calling function directly from object" << endl;
    t.f();

    cout << "adding the task into the queue" << endl;
    q.push(t);

    cout << "calling the function from the queue" << endl;
    task tsk = q.front();
    tsk.f();
    q.pop();

    q.push({ 1, [] {std::cout << "Even more fun\n"; } });

    auto t2 = q.front();
    t2.f(); // invoke conventionally

    t2();   // invoke via operator()

    q.pop();
}

Seems like i found a simple enough method using structures to implement the function queue. May not be perfect or efficient, for now this works.

#include <iostream>
#include <queue>

using namespace std;

struct task {
    int id;
    void (*fptr) (void);
};

queue<struct task> q;

void fun(void) {
    cout<<"Having fun!"<<endl;
}

int main() {

    cout<<"Creating a task object"<<endl;

    task t;
    t.id = 1;
    t.fptr = &fun;

    cout<<"Calling function directly from object"<<endl;
    t.fptr();

    cout << "adding the task into the queue"<<endl;
    q.push(t);

    cout << "calling the function from the queue"<<endl;
    task tsk = q.front();
    tsk.fptr();
    q.pop();

    return 0;

}


OUTPUT : 

Creating a task object
Calling function directly from object
Having fun!
adding the task into the queue
calling the function from the queue
Having fun!

I would not use a queue as described in the std::queue format.

It does not allow you to insert at any given location. You should build your own.

If you do it like below and add priorities and names, then you can easily come up with logic to switch tasks, switch/update priorities, and even insert at a desired location.

I will say that linked lists always have speed issues. you could also do something similar with a struct array and use array logic to move and insert.

struct function_T {
    string name;
    uint8_t priority;
    void(*func_ptr)(void);
};

struct node_T {
    node_T * previous = NULL;
    function_T fptr;
    node_T * next;
};

int main(void){

    function_T task1;
    task1.name = "task1";
    task1.priority = 1;
    task1.func_ptr = func4;

    node_T first_node;
    first_node.previous = NULL;
    first_node.fptr = task1;
    first_node.next = NULL;

    first_node.fptr.func_ptr();
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM