Ticker attachments

22 Dec 2010

I recently coded a function that returned an (int) value, which I used for debugging the function when it was called manually. Then I just hooked it to a ticker without bothering to recode it to remove the return value.

This does not work, as a function returning an (int) is not compatible with the ticker library as it stands. So the compiler objected.

Would it make sense to allow a ticker attachment to be a function that returns something other than (void)?

If that is not a good idea, then perhaps the ticker docs could at least highlight this restriction -- for those of us who don't read the fine print in the library definitions :-)

22 Dec 2010

It makes no sense for an "interrupt service routine" to return a value. What's it returning it to?

As for "then perhaps the ticker docs could at least highlight this restriction", it does. You need to read the function prototype, it says:-

void attach(    void     (*fptr)(void),
    float     t    )

See that "void" at the start? It's clearly stating it returns nothing.

22 Dec 2010

What would the ticker do with the return value?

I'm not sure this is worth documenting - the expected type is right there in the attach() function description and the compiler will tell you if you forget.

23 Dec 2010

I believe there is a larger question embodied here, one that goes to the heart of the mbed rapid prototyping philosophy:

How "rigorous" should an mbed library function attempt to be?

Suppose, for example, a developer in his discretion decides to call a function in the body of his code, and ignore its return value. Clearly, in an ideal world no function would return a value unless it were critical that that value be checked. So in an ideal world, the compiler might try to force the developer to check the return value.

But we are not in an ideal world, and the compiler does not behave that way. In the real world, it is not unusual for routines to return values that are just advisory (such as debugging information), and the developer may choose at times ignore such return values. That is a design decision, and the compiler stays out of it.

After all, the compiler can't know if the return value is meaningful in the context of the rest of the program.

Similarly, the mbed ticker library can't know if an attached function's return value is meaningful or not. But unlike the compiler, the present version of the ticker library does not stay out of it -- instead, it prevents binding non-void functions. No doubt this was done with good intentions, perhaps to encourage the noble practice of always checking return values. But is that appropriate for a rapid-prototyping library used in the real world?

I suggest the library should allow the same latitude to the developer as does the compiler. So, for example, if the developer wants to attach a non-void function to the ticker, that should be permitted. Clearly, the ticker will do nothing with the return value -- but that is exactly what the developer expects. Let him attach his function and get on with his business.

Maybe I am wrong, but I believe that allowing more leeway in ticker.attach would better promote truly rapid prototyping. What say, mbed development team?

24 Dec 2010

Hi Hexley,

They are some good questions. I certainly explored lots of options, and the current api is the result of those investigations and analysis; I think the main reasons it is how it is can be summarised as:

  • An interrupt function is naturally void f(void), as an interrupt has no arguments, and nothing to return to
  • Accepting different return types properly would add the complexity of requiring templates, and the associated code to be able to store/call the different function pointers; all doable, but perhaps not natural/intuative
  • If it is not a void f(void) function you want to attach (for the valid reasons you state), why is it limited to return type flexibility? Why not allow function arguments to be pre-set/passed? (think closures etc). In many cases, you probably end up wanting a little trampoline function, which for the 3 lines of code etc gives you all the options, without the api complexity.
  • The reality is close to the api, and the same function could in theory be statically or dynamically attached to an actual interrupt vector

You raise some good points, but I think it is probably the best compromise at the moment. I will be looking again at how we handle attching member function pointers, as c++ struggles here and I think I have a better solution to simplify things, so will look at static functions again too. This will be part of working on what I'll call 2.0; more on that in January, as I'll be after lots of feedback then :)

Merry Christmas, Simon

24 Dec 2010

Hi Simon -

Thanks for the thoughtful and well-reasoned reply.

I take your point about creeping elegance. It really would be nice to be able to pre-set or pass arguments, etc. But if the mbed library API starts approaching RTOS-like complexity, well, that really doesn't serve the needs of rapid prototyping either. Better to keep things streamlined. So I guess your current approach to the ticker is indeed a good compromise.

Still, I'm looking forward to see what you cook up in 2.0 :-)

Meanwhile,

Happy Holidays.

hb