3

I am building a simple scheduler, which takes functions as parameter, puts them in a queue and executes them at a later time. The class is intended to be inherited, and later enqueue(function_ptr) to be called from the methods of the child class.

My problem is that the scheduling will be happening based on time, and that is measured with a 2ms interrupt. One can subscribe for callbacks from the interrupt handler, but those return only a void* to the object that got subscribed.

So how can I know what is the type of the object being passed back, so that I can cast it and call the appropriate method?

I was thinking about template parameter at class Scheduler creation, but then the callback function doesn't know what the template parameter was. So maybe some way of storing Scheduler's child class inside a member variable - cast object to Scheduler and looking at that field, cast it to the final type? I guess this can be solved by a global enum of schedulable classes, but that seems like a bad solution.

Or maybe my whole approach of this is wrong?


Here is some code for the Scheduler. I was refraining from posting, because possibly my whole approach is wrong.

class Scheduler {
     private: std::vector<QueueItem> m_queue;
     protected: void schedule(void *foo_ptr);
     public: void callback_2ms_passed();  // Note that we are getting only 'this' as a parameter.
}
class Child1 : public Scheduler, public OtherClasses {
    void slow_foo(bool execute_immediately = false) {
        if(!execute_immediately)
            schedule(slow_foo);
        else
            // Do slow stuff.
    }
}

The idea is that the scheduler decides when at a later moment to call the slow function, and does it with parameter true so that the actual calculations are made.

Vorac
  • 8,726
  • 11
  • 58
  • 101
  • 1
    How do you define "appropriate method"? How does it differ from inappropriate ones? Why does `Scheduler` need to know what class is being derived from it? Can you show some code demonstrating what `Scheduler` looks like, and how it's intended to be used? – Igor Tandetnik Nov 12 '14 at 21:38
  • @IgorTandetnik, I was trying to outline my goal more than the implementation. I have added my approach above, but it is entirely possible that another architecture, e.g. composition, would suit the task better. – Vorac Nov 13 '14 at 08:39
  • Technically, you could use `std::function`, which is a perfect abstraction for an action. Insert items with [`std::bind`](http://en.cppreference.com/w/cpp/utility/functional/bind) or [lambdas](http://en.cppreference.com/w/cpp/language/lambda). Your lambdas could i.e. contain side-effects, as assigning a value somewhere, or calling methods of other objects – Dmitry Ledentsov Nov 13 '14 at 08:47
  • @DmitryLedentsov, this approach sounds great. However, it turns out I am using [quite an old compiler](http://stackoverflow.com/questions/26907586/stdfunction-has-no-member-named-target). – Vorac Nov 13 '14 at 11:15
  • @Vorac: why not switch to a newer compiler? In any case, you could probably substitute it with Boost [function](http://www.boost.org/doc/libs/1_56_0/doc/html/function.html) & [bind](http://www.boost.org/doc/libs/1_56_0/libs/bind/bind.html) – Dmitry Ledentsov Nov 13 '14 at 12:23
  • If `Scheduler` were a template, used as in `class Child1 : public Scheduler`, then `callback_2ms_passed` would have access to `Child1` via a template parameter. What makes you believe otherwise? – Igor Tandetnik Nov 13 '14 at 14:32
  • 1
    @DmitryLedentsov, thank you a lot. I used `std::function` and it worked great. – Vorac Mar 21 '15 at 08:24

1 Answers1

0

What you are searching for are delegates. Since you don't want to use boost or the other mentioned implementations of delegates you could try this.

SomeObject obj;
delegate d = delegate::from_member<SomeObject, 
              &SomeObject::someMethod>(&obj);

Your Scheduler should use delegate objects in your vector. Have a look here: http://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegates

Tim Kathete Stadler
  • 1,067
  • 4
  • 26
  • 52