And, despite some missing features, a crash bug (for which I have posted a fix), and a scary number of goto statements (i.e. more than 0), it does the job admirably.
The crash bug was due to an unimplemented feature of MQTT-SN, but let’s get onto the use of gotos. The RSMB code is written in C, not C++. I made that decision in 2008 when I started to implement RSMB in C++. I thought I would use all the features of C++ to build a nicely object oriented architecture, while making the code as efficient and small as it could be. That approach lasted all of a few hours, as I discovered that template support in the version of gcc I had to hand was decidedly dodgy.
Nothing for it, I had to resort to standard, portable C. On the bright side, that meant I didn’t have to contend with huge standard libraries being included in the executable. On the down side (and this is a big downside) I had to obtain or write my own collection libraries.
As RSMB became part of WebSphere MQ for a while, under the name of Telemetry Daemon for Devices, I was required to add some features to aid bug fixing. One of these is a stack trace (the pros and cons of that belong in a different post). What that meant is that each function had to end with a macro:
In those functions where some code inside a nested loop or two found an error and needed to leave the function, I had two potential approaches (apart from restructuring the loops):
- have multiple returns from the function, with multiple FUNC_EXIT macros, or
- use a goto to the single exit point of the function.
I chose the latter, as it meant only one FUNC_EXIT call was needed, meaning less scope for forgetting to include it before any return statement. This means that each function only has one exit point, which some people prefer in any case.
The use of goto is therefore constrained to the following pattern:
int function(int parm)
goto exit; /* an error condition */
goto exit; /* another error condition */
It struck me recently, rather belatedly, that this is what exceptions are. So if you dislike my use of gotos, please consider them to be exceptions instead.
With the right sort of macros, maybe I could even make them look like exceptions
#define raise(label) goto label;
#define handle(label) label:
but I think that would be wilfully obscure 🙂