How can I exit a function as soon as a certain condition is met (without checking it at every line)?

74 Views Asked by At

I am developing a multi-threaded application. One of the threads is dedicated to handling an alarm system, which plays a certain alarm (sequence of specific tones) according to the alarm case. There's also an option to mute the alarm, by raising a flag from another thread. Whenever an alarm is muted, I want my program to immediately stop the alarm and not go through all the sequence. Below is a toy example of how my code is structured:

static int mute = 0;
static int current_alarm = 0;

void play_alarm_2 (void)
{
play_g_tone();
sleep(30);
play_a_tone();
sleep(20);
. . .
} 

void play_alarm_1 (void)
{
play_c_tone();
sleep(10);
play_f_tone();
sleep(20);
. . .
} 

void set_mute_status (int mute_status)
{
mute = mute_status;
}
void set_current_alarm (int alarm)
{
current_alarm = alarm;
}

int main()
{
    for(;;)
    {
    switch(current_alarm)
        case 1:
            play_alarm_1();
        case 2:
            play_alarm_2();
        . . .
    }
}

Other threads set the alarm case and the muting option. Now for example, if the alarm thread is currently inside play_alarm_2 and is playing the g_tone, if the user suddenly mutes the alarm, I would like to exit the function play_alarm_2 (the g_tone can finish to play, it doesnt have to cut it short necessarly). A stupid way to do it would be to add an every other line:

void play_alarm_2 (void)
{
if (mute)
    return

play_g_tone();

if (mute)
    return

sleep(30);

if (mute)
    return

play_a_tone();

if (mute)
    return

sleep(20);
. . .
} 

Which again looks a bit stupid but does it solves my problem. I could also set up a macro maybe for it. But my question is, is there a more proper way to do this? Probably there is a solution that includes introducing another thread, but I would avoid it If i can. If really there's no way to do this without another thread, what would be the proper way to implement this?

P.S: This code will go on an embedded system and I am using ThreadX.

1

There are 1 best solutions below

0
On BEST ANSWER

A sketch of "how to do this":

#define N 6 // 0-5 steps
for( int i = 0; ; i = (i+1) % N ) { // 0-1-2-3-4-5-0-1-2...
    switch( i ) {
        case 0: play_a_tone(); break;
        case 2: play_g_tone(); break;
        case 4: play_c_tone(); break;

        case 1:
        case 3:
            sleep(30);
            break;
        case 5:
            sleep(200);
            break;
    }
    if( mute ) return;
}

If the only thing happening in the function is this loop, you could even:

for( int i = 0; !mute; i = (i+1) % N ) {

and wouldn't need the extra if() at the bottom of the loop...


UPDATE:
Happened across this and wanted to post an 'improvement' that clearly separates the data from the functionality:

struct {
    void (*tone)();
    int dur;
} sqnc[] = {
    { play_a_tone,  30 }, // repeatedly played in sequence
    { play_g_tone,  30 },
    { play_c_tone, 200 },
    { play_f_tone,  30 },
};
const int N = sizeof sqnc/sizeof *sqnc;

for( int i = 0; !mute; i = (i+1) % N ) {
    sqnc[i].tone(); if( !mute ) sleep( sqnc[i].dur );
}

This suggests it could be made even simpler if the separate play_X_tone() functions were combined into a single function that takes and uses a parameter. Haven't seen that code, so this is just an observation.

(Just put Donna Summer's "I Feel Love" on the stereo... Multiple threads?? You're on your way to re-inventing the 'digital sequencer'. :-))