Using function pointers in a scheduler class

Hello, I'm trying to write a simple game engine and I came to the point where I need to add some kind of timing mechanism.

Most specifically, I'm trying to write some sort of scheduler class that has a method "runAfterDelay(delay, toRun);"

But I'm wondering, what should I pass into this function?

I know that in Java, the usual way to do it is to create a class that has the "Runnable" interface and implements the "run()" method. On the other hand, I know that C++ has function pointers.

I like the idea of Runnable because you can attach some extra data, which might be useful in a situation like "In 5 seconds, turn the traffic light to green", where the code being run needs to know about the traffic light object.

What is the correct way to do it in C++?
Gotta like C++11.

If I understand well, I simply pass the dependency in as an argument?
> What is the correct way to do it in C++?

Something along these lines would be canonical
(In C++, we like to let the user decide about the choice of implementation).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <functional>
#include <queue>
#include <string>

struct task_queue
{
    template < typename CALLABLE, typename... ARGS >
    void run_when_asked( CALLABLE fn, ARGS&&... args )
    { pending.push( std::bind( fn, args... ) ) ; }

    void execute_pending()
    {
        while( !pending.empty() )
        {
            pending.front()() ;
            pending.pop() ;
        }
    }

    std::queue< std::function< void() > > pending ;
};

int free_fun( int a, int b )
{
    std::cout << "free_fun(" << a << ',' << b << ")\n" ;
    return a+b ;
}

struct function_object
{
    void operator() ( const std::string& str ) const
    { std::cout << "function_object()(" << str << ")\n" ; }
};

struct some_class
{
    double mem_fun( double a, double b ) const
    {
        std::cout << "some_class::mem_fun( (" << this << "), " << a << ", " << b << " )\n" ;
        return a+b+v ;
    }
    int v = 7 ;
};


int main()
{
    task_queue tq ;
    tq.run_when_asked( free_fun, 1, 2 ) ;

    function_object f ;
    tq.run_when_asked( f, "hello world" ) ;

    some_class obj ;
    tq.run_when_asked( &some_class::mem_fun, std::ref(obj), 3.4, 5.6 ) ;

    tq.run_when_asked( [] ( int a, int b )
                       { std::cout << "closure(" << a << ',' << b << ")\n" ; },
                       5, 6 ) ;

    tq.execute_pending() ;
}

http://coliru.stacked-crooked.com/a/f990287a4fb91eab
JLBorges, so, the function doesn't have to have a fixed signature? That's exactly what I'm looking for, let's see if I can reproduce that...
Werner2 wrote:
I'm trying to write some sort of scheduler class that has a method "runAfterDelay(delay, toRun);"

incidentally, this looks a lot like deadline_timer::async_wait from boost:

http://www.boost.org/doc/libs/release/doc/html/boost_asio/tutorial/tuttimer2.html
http://www.boost.org/doc/libs/release/doc/html/boost_asio/reference/basic_deadline_timer/async_wait.html

-- perhaps you don't need to write it yourself.

Last edited on
@Cubbi Thanks for the tip, but my goal is as much to learn about C++ as to write a game engine, so I'm trying to write this myself.

Now, I'm getting a compiler error when trying to compile the code I wrote based on JLBorges' answer. I left out the bit that actually runs the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Scheduler {
    
    struct Task {
        bool synchronous;
        bool repeating;
        float delay;
        float interval;
        boost::function<void()> toRun;
    };
    
    std::list<Task> tasks;
    
public:
    
    template <typename Functype, typename... Arg>
    void runAfterDelay(float delay, Functype toRun, Arg&&... args){
        tasks.push_back(Task{
                            true, // synchronous
                            false, // repeating
                            delay, // delay
                            1, // interval
                            boost::bind(toRun, args...) // function
                        });
    }
    
};

The error:
boost/bind/bind_cc.hpp:30:45: Ambiguous conversion for functional-style cast from 'luabridge::LuaRef' to 'list_type' (aka 'list1<B1>')

luabridge::LuaBridge is the type of one of the arguments I'm trying to use.

Note that I'm using boost::function rather than std::function. I cannot use c++11 without drowning in linker errors. I probably have to recompile some libraries to use a different standard library or something. Is this the problem, or something else I missed?

EDIT:
Hey... If I just use a little test function that takes only an int, the program compiles just like it should! There must be some problem related to that LuaRef, not to the way I'm registering the functions in my scheduler class.

Thank you for your help.
Last edited on
> I cannot use c++11 without drowning in linker errors.
> I probably have to recompile some libraries to use a different standard library or something.
> Is this the problem, or something else I missed?

Yes. The libraries have to be compiled for C++11.
For instance, with GCC: http://gcc.gnu.org/wiki/Cxx11AbiCompatibility

boost::function<>, boost::bind() etc are header-only libraries, so they are compiled along with your code.
Topic archived. No new replies allowed.