View Single Post
  #3   Spotlight this post!  
Unread 09-07-2016, 04:12
Jaci's Avatar
Jaci Jaci is online now
Registered User
AKA: Jaci R Brunning
FRC #5333 (Can't C# | OpenRIO)
Team Role: Mentor
 
Join Date: Jan 2015
Rookie Year: 2015
Location: Perth, Western Australia
Posts: 251
Jaci has a reputation beyond reputeJaci has a reputation beyond reputeJaci has a reputation beyond reputeJaci has a reputation beyond reputeJaci has a reputation beyond reputeJaci has a reputation beyond reputeJaci has a reputation beyond reputeJaci has a reputation beyond reputeJaci has a reputation beyond reputeJaci has a reputation beyond reputeJaci has a reputation beyond repute
Re: The OpenRIO C++ Coding Guidelines for FRC

Quote:
Originally Posted by Peter Johnson View Post
Why the dislike of std::unique_ptr? I can understand not wanting the locking/reference counting overheads of std::shared_ptr, but std::unique_ptr is essentially just a simple wrapper around a pointer to provide scoped destruction (basically a less dangerous version of std::auto_ptr).
Although these calls are known to be safe, we know that this additional safety isn't really required if Rule 4 (no dynamic memory allocation outside of one-time code initialization) is followed. We're aware that the overhead is fairly small, and that they are a wrapper.

We've found that when developing software specifically for embedded systems, especially those on a periodic loop, we want to try and reduce the use of both locking functions and the C++ STL. The main reasoning behind this is that compilers are specifically terrible at optimizing templates and the STL.

You'll often find this mindset also carried in Game Development and other applications where performance (and memory usage) is a key factor.

Quote:
Originally Posted by Peter Johnson View Post
While std::map and its kin are very allocation-intensive, it's hard to get more efficient than std::vector when you need a dynamically allocated or resizeable array. It's basically a wrapper around a pointer and a size.
The main goal around this is to avoid allocating memory after a one-time task initialization (Rule 4: heap memory). The main idea is to "allocate what you will need", even if that means over-allocating a static array. This mostly follows from the JPL Institutional Coding Standard's Rule 5. Of course, in some cases, this rule is made to be broken. It should be noted that most of these rules should be read in a "periodic context", tasks which occur over and over again that can very easily bog down the system if optimizations do not occur.

Quote:
Originally Posted by Peter Johnson View Post
I'm surprised at the recommendation to use std::exception and std::runtime_error. Exception-safe code is very hard to write well, and usually the exception paths are not effectively tested anyway (as they're hard to test). You're almost better off crashing and letting the auto-program-restart functionality get you back up and running.
To clear this up: we're not promoting the use of exceptions or runtime_error where a simple return-value check will suffice. We're trying to use these types as opposed to calls to assertions. Assertions are great for debugging, but when running on a robot in a match, they can be disastrous. By allowing assertions to occur, you can easily slip into a code reboot loop, and the code startup time during a match is far from desirable. It should be noted that Rule 5 (error processing and catching) is designed to enforce exception-safe code. It should also be noted that this rule is one of the few rules not meant to be read in a periodic context, but instead in an initialization context (i.e. allocating a hardware object that isn't there).

I'll update the document tonight to reflect these clarifications
__________________
Jacinta R

Curtin FRC (5333+5663) : Mentor
5333 : Former [Captain | Programmer | Driver], Now Mentor
OpenRIO : Owner

Website | Twitter | Github
jaci.brunning@gmail.com
Reply With Quote