Blocking inside a switch case - c++

On an embedded system, running freertos, is there any reason why you would not have a blocking function inside a case of a switch statement?
For example, a thread running through a state machine and one of the states is a wait for a task notification.
Typically I've done this with if-else's but is there any advantage or disadvantage to making it a switch case?
Using cpp17 and avoiding STL.
Edit: blocking function, i.e. one that sits forever until it gets a notification, such as xTaskNotifyWait(...)
Example:
switch (state)
{
case state1:
foo();
break;
case state2:
xTaskNotifyWait(...);
};
vs
if (state == state1)
{
foo();
}
else if (state == state2)
{
xTaskNotifyWait(...);
}
TIA

You can use either a switch or if statement. There isn't much a difference. You can have blocking calls in either of them.
I've heard that switch cases use hash tables but if-else doesn't. I'm not sure if there are differences in the asm code, and what impact that would have on code size, speed, etc.
See this to understand the difference between switch and if statement. I am quoting one of the answer below:
The main difference is that switch despatches immediately to the case concerned, typically via an indexed jump, rather than having to evaluate all the conditions that would be required in an if-else chain, which means that code at the end of the chain is reached more slowly than code at the beginning.
That in turn imposes some restrictions on the switch statement that the if-else chain doesn't have: it can't handle all datatypes, and all the case values have to be constant.
With a switch construct, you can use descriptive enum for your case label which says that this state is meant to be blocking. I would personally use a switch construct as the case label can be descriptive.
enum state_e {
INIT,
WAITING_FOR_EVENT
};
switch (state) {
case INIT:
{
foo();
state = WAITING_FOR_EVENT;
break;
}
case WAITING_FOR_EVENT:
{
xTaskNotifyWait(...);
// Change State
break;
}
};

Related

How to fix the transfer of control bypasses initialization of error? [duplicate]

I get a "transfer of control bypasses initialization of:" error when i try to build the following switch:
switch (retrycancel)
{
case 4: //The user pressed RETRY
//Enumerate all visible windows and store handle and caption in "windows"
std::vector<MainHandles::window_data> windows = MainHandles().enum_windows().get_results();
break;
case 2:
//code
}
It has something to do with my calling my enumerate function. If it is not allowed to call a function from within a switch, is there a workaround for this kind of problem?
section 6.6.4 of the C++ standard:
The goto statement unconditionally
transfers control to the statement
labeled by the identifier. The
identifier shall be a label (6.1)
located in the current function.
section 6.7 of the C++ standard:
It is possible to transfer into a
block, but not in a way that bypasses
declarations with initialization. A
program that jumps from a point
where a local variable with automatic
storage duration is not in scope to a
point where it is in scope is
ill-formed unless the variable has POD
type (3.9) and is declared without an
initializer
Emphasis added by me. Since switch is really goto in disguise, you're encountering this behavior. To solve this, add braces if you must use a switch
switch (retrycancel)
{
case 4:
{
const std::vector<MainHandles::window_data> windows(
MainHandles().enum_windows().get_results()
);
break;
}
case 2:
//code
}
or refactor into if/else
if (retrycancel == 4) {
const std::vector<MainHandles::window_data> windows(
MainHandles().enum_windows().get_results()
);
} else if (retrycancel == 2)
// code
} else {
...
}
Though it's not obvious to me what you're hoping to accomplish with creating the windows vector inside a switch, so you may want to rethink your design. Note I added a const qualifier to windows since it's not modified in your example.
a switch is essentially a goto, that is, it is a goto to the appropriate label. The C++ standard forbids a goto to bypass an initialization of a non-POD object. Take the vector declaration into braces and it will solve the problem
switch (retrycancel)
{
case 4: //The user pressed RETRY
{
std::vector<MainHandles::window_data> windows = MainHandles().enum_windows().get_results(); //Enumerate all visible windows and store handle and caption in "windows"
break;
}
case 2:
//code
}

Threading in object-oriented, event-driven application

I need to spawn a thread when a certain trigger event is received inside of a class Foo. The trigger event is received by a Winsock server class that has a reference to the variable triggerEvent.
bool Foo::HandleEvents()
{
while (1)
{
// Other things are done at the top of this loop
switch (triggerEvent)
{
case 'h':
{
// I instantiate an object here to do
// what I need to do in the thread.
// I use a pointer that is a private
// member of Foo.
thingMaker = new ThingMaker(params);
// Spawn a new thread here calling a
// function of ThingMaker and using thingMaker
break;
}
case ...: return true;
default: break;
}
}
}
Since the thread is local to its case in the switch, I lose access to it on break. I can't call join() because I'm dealing with real-time processing and cannot wait for the thread to finish unless I know it's already done.
I recently asked a question about threading here regarding the same application and was told detach() is bad practice; I also think my question was too vague as the solution offered ended up not fitting my needs and my application has since changed in architecture.
I have also tried to encapsulate the thread in short-life manager class that creates instances of ThingMaker but to no avail.
How do I go about this? I suspect my main issue is scope, but my options are limited. Foo::HandleEvents() cannot be delayed at all or else I lose critical data.
You could use a std::map (or one of the other similar containers):
class Foo
{
bool HandleEvents();
std::map<ThingMaker*, std::thread> m_map;
};
bool Foo::HandleEvents()
{
while (1)
{
switch (triggerEvent)
{
case 'h':
{
thingMaker = new ThingMaker(params);
m_map[thingMaker] = std::thread(function_ptr, thingMaker);
} break;
case 't': // termination event trigger
{
m_map[thingMaker].second.join();
m_map.erase(thingMaker);
delete thingMaker;
} break;
case ...: return true;
default: break;
}
}
}
Since this obviously isn't your full code you'd have to adjust the above code to fit your needs, but you could swap the map's key/value in the template, or use the thread ID instead if that would make more sense (e.g. std::map<std::thread::id, ThingMaker*>, etc.), but something like a map avoids iterating over an array and joining on each thread or having to implement a full thread pool implementation if you don't necessarily need one.
Side note: the use of detach is not bad, in fact it's quite useful; detaching a thread signals to the kernel that the thread can be "cleaned up" as soon as it's done executing (which releases certain resources and handles). Calling detach on a thread is useful when you know you will no longer need access to the underlying thread handle (like in an extremely short lived thread). It's neither bad nor good, simply a tool to utilize (like the infamous goto statement).
Hope that can help.

Switch statement with automatic break at each case step in C++

If we want to have a switch statement where for each case we need to run some instructions then break we would so something like this:
switch (condition) {
case (opt1):
// do stuff
break;
case (opt2):
// do stuff
break;
case (opt3):
// do stuff
break;
// ...
default:
// do stuff
}
Is it possible to have an exclusive switch, without fall through, where by default every option should break and not have to explicitly state the break instruction? And if not in C++ any idea if such a feature is available in other imperative languages?
C# needs the break too, but yells at you if you don't put it. You need to goto label; to explicitly fall through.
In C++, there is no way to do this natively (other than horrible macros, of course). However, Clang has the -Wimplicit-fallthrough warning. You can then insert [[clang::fallthrough]]; to silence the warning for a deliberate fallthrough.
Documentation : http://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough
I hate having break statements in my switches, so I use the pattern of wrapping a switch in a closure and returning from each case. For example:
auto result = [&] {
switch(enum_val) {
case A:
return Foo();
case B:
return Bar();
}
}();
"There is no automatic fall through" in Golang. https://golang.org/doc/effective_go.html#switch

Use of goto for cleanly exiting a loop

I have a question about use of the goto statement in C++. I understand that this topic is controversial, and am not interested in any sweeping advice or arguments (I usually stray from using goto). Rather, I have a specific situation and want to understand whether my solution, which makes use of the goto statement, is a good one or not. I would not call myself new to C++, but would not classify myself as a professional-level programmer either. The part of the code which has generated my question spins in an infinite loop once started. The general flow of the thread in pseudocode is as follows:
void ControlLoop::main_loop()
{
InitializeAndCheckHardware(pHardware) //pHardware is a pointer given from outside
//The main loop
while (m_bIsRunning)
{
simulated_time += time_increment; //this will probably be += 0.001 seconds
ReadSensorData();
if (data_is_bad) {
m_bIsRunning = false;
goto loop_end;
}
ApplyFilterToData();
ComputeControllerOutput();
SendOutputToHardware();
ProcessPendingEvents();
while ( GetWallClockTime() < simulated_time ) {}
if ( end_condition_is_satisified ) m_bIsRunning = false;
}
loop_end:
DeInitializeHardware(pHardware);
}
The pHardware pointer is passed in from outside the ControlLoop object and has a polymorphic type, so it doesn't make much sense for me to make use of RAII and to create and destruct the hardware interface itself inside main_loop. I suppose I could have pHardware create a temporary object representing a sort of "session" or "use" of the hardware which could be automatically cleaned up at exit of main_loop, but I'm not sure whether that idea would make it clearer to somebody else what my intent is. There will only ever be three ways out of the loop: the first is if bad data is read from the external hardware; the second is if ProcessPendingEvents() indicates a user-initiated abort, which simply causes m_bIsRunning to become false; and the last is if the end-condition is satisfied at the bottom of the loop. I should maybe also note that main_loop could be started and finished multiple times over the life of the ControlLoop object, so it should exit cleanly with m_bIsRunning = false afterwards.
Also, I realize that I could use the break keyword here, but most of these pseudocode function calls inside main_loop are not really encapsulated as functions, simply because they would need to either have many arguments or they would all need access to member variables. Both of these cases would be more confusing, in my opinion, than simply leaving main_loop as a longer function, and because of the length of the big while loop, a statement like goto loop_end seems to read clearer to me.
Now for the question: Would this solution make you uncomfortable if you were to write it in your own code? It does feel a little wrong to me, but then I've never made use of the goto statement before in C++ code -- hence my request for help from experts. Are there any other basic ideas which I am missing that would make this code clearer?
Thanks.
Avoiding the use of goto is a pretty solid thing to do in object oriented development in general.
In your case, why not just use break to exit the loop?
while (true)
{
if (condition_is_met)
{
// cleanup
break;
}
}
As for your question: your use of goto would make me uncomfortable. The only reason that break is less readable is your admittance to not being a strong C++ developer. To any seasoned developer of a C-like language, break will both read better, as well as provide a cleaner solution than goto.
In particular, I simply do not agree that
if (something)
{
goto loop_end;
}
is more readable than
if (something)
{
break;
}
which literally says the same thing with built-in syntax.
With your one, singular condition which causes the loop to break early I would simply use a break. No need for a goto that's what break is for.
However, if any of those function calls can throw an exception or if you end up needing multiple breaks I would prefer an RAII style container, this is the exact sort of thing destructors are for. You always perform the call to DeInitializeHardware, so...
// todo: add error checking if needed
class HardwareWrapper {
public:
HardwareWrapper(Hardware *pH)
: _pHardware(pH) {
InitializeAndCheckHardware(_pHardware);
}
~HardwareWrapper() {
DeInitializeHardware(_pHardware);
}
const Hardware *getHardware() const {
return _pHardware;
}
const Hardware *operator->() const {
return _pHardware;
}
const Hardware& operator*() const {
return *_pHardware;
}
private:
Hardware *_pHardware;
// if you don't want to allow copies...
HardwareWrapper(const HardwareWrapper &other);
HardwareWrapper& operator=(const HardwareWrapper &other);
}
// ...
void ControlLoop::main_loop()
{
HardwareWrapper hw(pHardware);
// code
}
Now, no matter what happens, you will always call DeInitializeHardware when that function returns.
UPDATE
If your main concern is the while loop is too long, then you should aim at make it shorter, C++ is an OO language and OO is for split things to small pieces and component, even in general non-OO language we generally still think we should break a method/loop into small one and make it short easy for read. If a loop has 300 lines in it, no matter break/goto doesn't really save your time there isn't it?
UPDATE
I'm not against goto but I won't use it here as you do, I prefer just use break, generally to a developer that he saw a break there he know it means goto to the end of the while, and with that m_bIsRunning = false he can easily aware of that it's actually exit the loop within seconds. Yes a goto may save the time for seconds to understand it but it may also make people feel nervous about your code.
The thing I can imagine that I'm using a goto would be to exit a two level loop:
while(running)
{
...
while(runnning2)
{
if(bad_data)
{
goto loop_end;
}
}
...
}
loop_end:
Instead of using goto, you should use break; to escape loops.
There are several alternative to goto: break, continue and return depending on the situation.
However, you need to keep in mind that both break and continue are limited in that they only affect the most inner loop. return on the other hand is not affected by this limitation.
In general, if you use a goto to exit a particular scope, then you can refactor using another function and a return statement instead. It is likely that it will make the code easier to read as a bonus:
// Original
void foo() {
DoSetup();
while (...) {
for (;;) {
if () {
goto X;
}
}
}
label X: DoTearDown();
}
// Refactored
void foo_in() {
while (...) {
for (;;) {
if () {
return;
}
}
}
}
void foo() {
DoSetup();
foo_in();
DoTearDown();
}
Note: if your function body cannot fit comfortably on your screen, you are doing it wrong.
Goto is not good practice for exiting from loop when break is an option.
Also, in complex routines, it is good to have only one exit logic (with cleaning up) placed at the end. Goto is sometimes used to jump to the return logic.
Example from QEMU vmdk block driver:
static int vmdk_open(BlockDriverState *bs, int flags)
{
int ret;
BDRVVmdkState *s = bs->opaque;
if (vmdk_open_sparse(bs, bs->file, flags) == 0) {
s->desc_offset = 0x200;
} else {
ret = vmdk_open_desc_file(bs, flags, 0);
if (ret) {
goto fail;
}
}
/* try to open parent images, if exist */
ret = vmdk_parent_open(bs);
if (ret) {
goto fail;
}
s->parent_cid = vmdk_read_cid(bs, 1);
qemu_co_mutex_init(&s->lock);
/* Disable migration when VMDK images are used */
error_set(&s->migration_blocker,
QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
"vmdk", bs->device_name, "live migration");
migrate_add_blocker(s->migration_blocker);
return 0;
fail:
vmdk_free_extents(bs);
return ret;
}
I'm seeing loads of people suggesting break instead of goto. But break is no "better" (or "worse") than goto.
The inquisition against goto effectively started with Dijkstra's "Go To Considered Harmful" paper back in 1968, when spaghetti code was the rule and things like block-structured if and while statements were still considered cutting-edge. ALGOL 60 had them, but it was essentially a research language used by academics (cf. ML today); Fortran, one of the dominant languages at the time, would not get them for another 9 years!
The main points in Dijkstra's paper are:
Humans are good at spatial reasoning, and block-structured programs capitalise on that because program actions that occur near each other in time are described near each other in "space" (program code);
If you avoid goto in all its various forms, then it's possible to know things about the possible states of variables at each lexical position in the program. In particular, at the end of a while loop, you know that that loop's condition must be false. This is useful for debugging. (Dijkstra doesn't quite say this, but you can infer it.)
break, just like goto (and early returns, and exceptions...), reduces (1) and eliminates (2). Of course, using break often lets you avoid writing convoluted logic for the while condition, getting you a net gain in understandability -- and exactly the same applies for goto.

Using continue in a switch statement

I want to jump from the middle of a switch statement, to the loop statement in the following code:
while (something = get_something())
{
switch (something)
{
case A:
case B:
break;
default:
// get another something and try again
continue;
}
// do something for a handled something
do_something();
}
Is this a valid way to use continue? Are continue statements ignored by switch statements? Do C and C++ differ on their behaviour here?
It's fine, the continue statement relates to the enclosing loop, and your code should be equivalent to (avoiding such jump statements):
while (something = get_something()) {
if (something == A || something == B)
do_something();
}
But if you expect break to exit the loop, as your comment suggest (it always tries again with another something, until it evaluates to false), you'll need a different structure.
For example:
do {
something = get_something();
} while (!(something == A || something == B));
do_something();
Yes, continue will be ignored by the switch statement and will go to the condition of the loop to be tested.
I'd like to share this extract from The C Programming Language reference by Ritchie:
The continue statement is related to break, but less often used; it causes the next iteration of the enclosing for, while, or do loop to begin. In the while and do, this means that the test part is executed immediately; in the for, control passes to the increment step.
The continue statement applies only to loops, not to a switch statement. A continue inside a switch inside a loop causes the next loop iteration.
I'm not sure about that for C++.
Yes, it's OK - it's just like using it in an if statement. Of course, you can't use a break to break out of a loop from inside a switch.
It's syntactically correct and stylistically okay.
Good style requires every case: statement should end with one of the following:
break;
continue;
return (x);
exit (x);
throw (x);
//fallthrough
Additionally, following case (x): immediately with
case (y):
default:
is permissible - bundling several cases that have exactly the same effect.
Anything else is suspected to be a mistake, just like if(a=4){...}
Of course you need enclosing loop (while, for, do...while) for continue to work. It won't loop back to case() alone. But a construct like:
while(record = getNewRecord())
{
switch(record.type)
{
case RECORD_TYPE_...;
...
break;
default: //unknown type
continue; //skip processing this record altogether.
}
//...more processing...
}
...is okay.
While technically valid, all these jumps obscure control flow -- especially the continue statement.
I would use such a trick as a last resort, not first one.
How about
while (something = get_something())
{
switch (something)
{
case A:
case B:
do_something();
}
}
It's shorter and perform its stuff in a more clear way.
Switch is not considered as loop so you cannot use Continue inside a case statement in switch...