如果在触发if语句后触发条件失败,是否存在IF语句提前退出的情况?

问题:对于包含使触发它的条件无效的代码的条件语句,是否存在条件会在没有中断函数的情况下过早退出的条件?与此类似:

IF(x == 0){x=1;}

背景
我正在使用一个相当大的 c++ 程序,该程序由一个充当包装器的商业程序组成。这个包装器处理 etherCAT 通信和与计算机链路层的接口,我的程序存在于其中。我的程序存在 3 个线程(此商业包装器中存在其他线程,但我对它们的信息有限):

  • MyAppPD:商业函数,从内存中检索 EtherCAT PD 信息并将其传递给全局类。该线程与 EtherCAT 周期同步运行,我几乎无法控制它的内存访问。
  • 转换:该线程从全局类接收数据,对其进行处理,并通过全局类将输出返回给 MyAppPD。该线程与 MyAppPD 同步运行。
  • 计算:该线程与其他线程异步运行,通过全局类接收数据,因为它在转换中可用。它的输出通过相同的全局类返回到 Conversions。
  • 全局类:我一直提到的全局类是一个对象,它通过使用 pthread 互斥锁在两个线程之间来回传递数据。每个数据路径都使用一个锁(转换 -> 计算和计算 -> 转换由两个锁组成),私有类变量用作临时存储,因此在没有互斥锁的情况下,来自一个线程的数据永远不会被另一个线程直接访问先申请。

深度问题:
最近我在这个全局类中添加了一个新级别,以方便将轨迹数据从 Calculations 传输到 Conversions。它由以下形式的结构组成:

struct DCommand {
    struct DOptions {
        bool CSPI = false;
        bool Blend = false;
        bool Cyclic = false;
        bool StopM = false;
    };
    DOptions Opt;
    struct Drive {
        int INC_max;
        bool Init_Accel = false;
        bool Init_MTorq = false;
        std::vector<int32_t> Th = std::vector<int32_t>(200);
        std::vector<uint32_t> ThDot = std::vector<uint32_t>(200);
        std::vector<uint32_t> ThDotDot = std::vector<uint32_t>(200);
        std::vector<uint16_t> MTorq = std::vector<uint16_t>(200);
    };
    Drive D1;
    Drive D2;
};

这个结构从计算线程传递到全局类(通过互斥锁),在那里它被复制到一个私有全局结构,这个操作设置一个布尔值。转换线程在每个周期查询全局类以检查是否有新数据可用,如果布尔值为真,则启动查询。从全局类到Conversions的查询函数如下:

DCommand PDSync::Sync2Conv(){
    DCommand Out_DCom; //Create temporary struct

    pthread_mutex_lock(&Calc_lock_mutex);
    
    Out_DCom = DrvCom; //copy intermediate struct
    
    pthread_mutex_unlock(&Calc_lock_mutex);
    
    Conv_shouldread = false; //If true, Conv_ReadAvail returns true

    return Out_DCom;
} 

来自 Conversions 的请求函数如下:

if(ThreadSync.Conv_ReadAvail()){ 
    ConvDrv = ThreadSync.Sync2Conv();

    TS.SetEE_LoadStruct(ConvDrv); //Copy struct from threadsync to local trajectory 
}

其中 ThreadSync 是全局类对象。现在,此代码由于某种原因出现故障。我可以将问题追溯到“Sync2Conv”中的“return”语句之前,其中一个简单的 cout 跟踪器可以正常工作,它充当语句“ConvDrv = ThreadSync.Sync2Conv();” 不完成。更奇怪的是,在语句“if(ThreadSync.Conv_ReadAvail())”之后的程序就好像遇到了一个简单的中断一样继续执行;在 if 语句中。更奇怪的是,一旦我 CTRL+C 退出程序(在商业包装器上设置关闭并终止 ethercat 连接),语句 Sync2Conv 和 SetEE_LoadStruct 就在关闭之前完成。

解决问题的尝试:

  • 重命名从全局类接收数据的转换线程结构,以防它碰巧与商业包装器中的某些函数具有冲突标识符。
  • 检查互斥锁是否存在死锁情况。不存在。
  • 检查是否只有适当的线程试图通过 pthread_self() 访问 Sync2Conv 函数。在程序的生命周期内,没有其他线程访问该函数。
  • 逐行依次停用该功能,这使我找到了迄今为​​止找到的唯一解决方案:

部分解决方案:
停用防止重复读取 Sync2Conv 函数的触发器:

Conv_shouldread = false; //If true, Conv_ReadAvail returns true

将允许程序正确进行,但随后每个周期都会访问该功能,而不仅仅是在新数据可用时。这有点像当允许 IF 条件语句的变量切换状态时,IF 条件退出(或以某种方式挂起)。任何人都可以提供这方面的建议吗?

完整解决方案
竞争条件似乎出现在上面显示的条件 IF 语句的触发条件内。布尔值 Conv_shouldread 在触发条件中使用以确定何时尝试访问全局中的数据。

在布尔访问点周围扩展相同的互斥锁,以便在触发条件的上下文中知道该布尔的状态,然后才能在其他任何地方访问它似乎已经纠正了这个问题。见下文:

前:

bool PDSync::Conv_ReadAvail(){
    if(Calc_isavailable && Conv_shouldread){
        return true;
    }else{
        return false;
    }
}

后:

bool PDSync::Conv_ReadAvail(){
    bool temp = false;
    pthread_mutex_lock(&Calc_lock_mutex);
        if(Conv_shouldread){
            temp = true;
        }else{temp = false;}
    pthread_mutex_unlock(&Calc_lock_mutex);

    if(Calc_isavailable && temp){
        return true;
    }else{
        return false;
    }
}

读取重置布尔值 Conv_shouldread = false 也被移回互斥保护器内部,以便它不能与 IF 条件触发器语句同时访问。

应该注意的是,我在全局类的其他 3 个位置有类似的代码,它们从未遇到过有问题的竞争条件,但所有这些都传输了更少量的数据,所以我认为复制时间可能是这里的一个因素。无论哪种方式,我都会纠正它们,因为这样做是为了避免将来出现问题。谢谢大家的帮助!

以上是如果在触发if语句后触发条件失败,是否存在IF语句提前退出的情况?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>