2

I just needed something like this:

I have got a robot class which contains a motor object and a predefined callback function (which is triggered on an interrupt).

robot.h

class robot
{
public:
    motor motor1;
};

motor.h

class motor
{
public:
   int incrementPosition();
   int getPosition();
private:
    int position;
};

callback.cpp

void callback(){
   motor1.incrementPosition(); //callback function needs to reach this already created motor1
}

What I am trying to achive is:

  • Robot and motor objects has to be created only once (only one robot and one motor are allowable, bacause it is connected to a real physical robot and a motor),
  • Motor object (motor1) has to be created automatically and most importantly, it should be callable from the prefined callback function.

So the main should be like this,

main(){
   robot myRobot;
   robot myRobot2; //is not allowed or should be useless

   printf("%d\n", myRobot.motor1.getPosition());
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
pmundt
  • 57
  • 9
  • Can you install any user parameters for the callback function? – user0042 Oct 25 '17 at 12:04
  • [This](https://stackoverflow.com/questions/1008019/c-singleton-design-pattern) may help. – Jabberwocky Oct 25 '17 at 12:05
  • 1
    Maybe you could write some sort of "GetOrCreate" function? Should the `robot` be managed by anything? – George Oct 25 '17 at 12:07
  • I can not install any user parameters for the callback function. I can only use global variables/object in 'callback'. Singleton only solves (as I understood), "object has to be created once" problem. How will I react that 'motor' object from 'callback'? – pmundt Oct 25 '17 at 12:26
  • @DreamsOfElectricSheep, I am not sure I understood, what do you mean by "robot be managed by anything"? – pmundt Oct 25 '17 at 12:27
  • 1
    *" I can only use global variables/object in 'callback'"* - Sorry to tell you, but the framwork you are working with is either c*ap, or you are abusing it. – StoryTeller - Unslander Monica Oct 25 '17 at 12:27
  • Yes. `callback` is a `__weak void` function defined in another **.c** file. – pmundt Oct 25 '17 at 12:43

1 Answers1

7

Not that I really like to recommend that1, but obviously the Singleton Pattern comes to mind:

class robot {
    robot() {}
public:
    motor motor1;
    static robot& instance() {
        static robot theRobot;
        return theRobot;
    }
};

The only way to access an instance of robot is to use the instance() function then.

main(){
   robot myRobot; // Fails to compile since the constructor is private

   printf("%d\n", robot::instance().motor1.getPosition());
               // ^^^^^^^^^^^^^^^^^ Access the one and only instance 
}

The same way the single motor instance can be accessed in the callback function:

void callback(){
   robot::instance().motor1.incrementPosition();
}

Some more considerations:

  • Make your robot class implement an interface like

     struct IRobot {
         virtual ~IRobot() {}
         virtual std::vector<std::shared_ptr<IMotor>>& motors() = 0;
     };
    

    this makes it easier to write isolated unit tests and mock the robot singleton.

  • Instead of the static instance() function provide a global access function for the singleton instance that returns the above mentioned interface. This also can be easier replaced with a function that returns a mock object for unit testing.


1)The Singleton Design Pattern is often blamed as a bad design, and in most cases it actually is a bad decision. Nevertheless there are valid use cases, especially when designing embedded systems. You have one single and autonomous robot, that's clear and deserves a singleton.
It's considerable though, if you should fix yourself to a single motor from the beginning, it would be hard to change if the HW engineers decide to need a second motor.

user0042
  • 7,917
  • 3
  • 24
  • 39