Quote:
Originally Posted by Peter Johnson
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
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
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