10

I'm currently writing an RTOS for microcontrollers. The whole thing is written in C++11 - if anyone is interested, and the link to the repository is at the bottom.

Currently I'm writing a class that is a simple data queue for passing objects between threads (or between interrupt handlers and threads or interrupt handlers and other interrupt handlers). Usually I try to follow some common APIs found on other projects, yet I didn't find any example of concurrent queue that has emplace() function AND supports timeouts.

My general "problem" is that I cannot decide between these two interfaces:

(std::chrono::duration<Rep, Period> is a templated type, I omit the template boilerplate for clarity)

First version:

template<typename T>
class FifoQueue
{
public:
    ...
    template<typename... Args>
    int tryEmplaceFor(std::chrono::duration<Rep, Period>, Args&&... args);
    int tryPopFor(T&, std::chrono::duration<Rep, Period>);
    int tryPushFor(const T&, std::chrono::duration<Rep, Period>);
    int tryPushFor(T&&, std::chrono::duration<Rep, Period>);
    ...
}

Second version:

template<typename T>
class FifoQueue
{
public:
    ...
    template<typename... Args>
    int tryEmplaceFor(std::chrono::duration<Rep, Period>, Args&&... args);
    int tryPopFor(std::chrono::duration<Rep, Period>, T&);
    int tryPushFor(std::chrono::duration<Rep, Period>, const T&);
    int tryPushFor(std::chrono::duration<Rep, Period>, T&&);
    ...
}

(there will be a second set of these functions with ...Until suffix - these would use timepoint instead of duration)

The first version follows a "common style" of having the timeout as the last parameter (examples are POSIX message queues, std::condition_variable, simple queues in any RTOS for microcontrollers). The issue is that it's not possible to have this timeout argument as the last one for tryEmplaceFor() function, because in case of variadic templates "known" arguments must be first (*). So the second version is "consistent" - all functions with timeout have the timeout as the first argument. This variant has an obvious problem of being probably the first example of having timeout as the first argument for such functionality.

Which interface would serve the OS better:

  • established standard of having the timeout as the last argument (with exception of tryEmplaceFor() and tryEmplaceUntil() - where it must be the first argument (*))?
  • consistency - prefer the timeout to be the first argument?

(*) - I know that technically I could have the timeout as last argument for tryEmplaceFor() and tryEmplaceUntil(), but I'd rather avoid using such template magic for such simple scenario - doing all these recursive instantiations just to get the last argument seems a bit overkill, especially when I visualize the errors compiler would produce in case user does something wrong...


2
  • What is the difference between the first and second version? Please highlight. Dec 24, 2014 at 8:30
  • 1
    Observation: not everyone knows POSIX well enough to be bothered by the placement of time, but everyone using your interface will be frustrated by the inconsistent API. I vote #2.
    – J Trana
    Dec 29, 2014 at 7:49

1 Answer 1

0

As suggested by an answer that was deleted (unfortunately) and comments, I followed the "consistency" line (second presented variant) - in all "try...For" and "try...Until" functions the timeout (duration or time point) is the first argument.

This is the code at current stage - link

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.