如何在满足特定条件后立即退出函数(无需在每一行检查)?

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

提问人:cercio 提问时间:10/26/2023 最后编辑:Konrad Rudolphcercio 更新时间:11/6/2023 访问量:50

问:

我正在开发一个多线程应用程序。其中一个线程专用于处理报警系统,该系统根据报警情况播放一定的报警(特定音调序列)。还有一个选项可以通过从另一个线程发出标志来静音警报。每当闹钟静音时,我希望我的程序立即停止闹钟,而不是遍历所有序列。下面是一个玩具示例,说明我的代码是如何构建的:

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();
        . . .
    }
}

其他线程设置报警情况和静音选项。现在例如,如果警报线程当前在play_alarm_2内并且正在播放g_tone,如果用户突然将警报静音,我想退出功能play_alarm_2(g_tone可以完成播放,它不必将其缩短)。一个愚蠢的方法是每隔一行添加一行:

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);
. . .
} 

这看起来又有点愚蠢,但它确实解决了我的问题。我也可以为它设置一个宏。但我的问题是,有没有更合适的方法来做到这一点?可能有一个解决方案,包括引入另一个线程,但如果可以的话,我会避免它。如果真的没有另一个线程就无法做到这一点,那么实现这一点的正确方法是什么?

PS:此代码将在嵌入式系统上使用,我正在使用 ThreadX。

C 多线程返回 退出 ThreadX

评论

0赞 Fe2O3 10/26/2023
你知道怎么写循环吗?您知道如何使用“模”计数器吗?你知道如何使用吗?你能想到如何结合这三个基本思想来解决你的问题吗?switch()
0赞 cercio 10/26/2023
是的,我知道如何使用这些东西。但我不明白将它们结合起来如何解决这个问题,您能分享更多关于这个问题的见解吗?@Fe2O3
1赞 Solomon Slow 10/26/2023
回复,“一种愚蠢的方法是......”我称之为“简单”。不是“愚蠢”。有时,简单就是聪明。它对你来说是否聪明是一个见仁见智的问题,在这种情况下,你的意见是最重要的。Fe2O3 的答案(下图)实际上与您的“愚蠢”解决方案相同,但它 (A) 更紧凑(有些人说这很好),并且 (B) 更难阅读和理解(有些人说这很糟糕)。您的电话!
0赞 Fe2O3 10/27/2023
@SolomonSlow 话又说回来,由于“简单”,一长串繁琐、重复的代码有其自身的危害和缺点。拉威尔巧妙地利用迭代和模级数来写出他最著名的作品“波莱罗”。(据称这首曲子仍在地球上的某个地方 24/7/365 演奏。想想巴赫!人们可以努力编写代码,就像莫扎特写音乐一样......或者像萨列里写的东西一样......贝多芬:哒�

答:

1赞 Fe2O3 10/26/2023 #1

“如何做到这一点”的草图:

#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;
}

如果函数中唯一发生的事情是这个循环,你甚至可以:

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

并且不需要循环底部的额外内容......if()


更新:碰巧遇到了这个问题,并希望发布一个“改进”,将数据与功能明确分开:

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 );
}

这表明,如果将单独的函数组合成一个接受和使用参数的函数,则可以使它变得更加简单。没有看到该代码,所以这只是一个观察。play_X_tone()

(只需将 Donna Summer 的“I Feel Love”放在立体声音响上......多个线程??您正在重新发明“数字音序器”。:-))