c++ - 将 volatile 数据与未为 volatile 数据重载的方法一起使用

标签 c++ gcc shared-memory systemc

我有点不知所云了。

我有三个进程通过共享内存段进行通信。并发访问是通过正确的锁定处理的(以避免在这里被误解),所以我很确定我正在按照预期的方式使用 volatile 关键字。

我的共享内存段被强制转换为指向结构的 volatile 指针,我可以对其进行操作。该结构必须是 volatile 的,因为有时我需要旋转直到共享内存上的某些值发生变化 - 所以不使用 volatile 不是一种选择。

现在我正在使用一个外部 C++ 库(SystemC,但这在这里无关紧要),我的结构从中包含 sc_time 的成员。尽管我可以访问该库的源代码,但我不想依赖于我所做的修改,这可能会破坏内容或陷入维护困境。

现在这个类“sc_time”有用于比较和赋值的运算符。这些运算符不适用于 volatile sc_time - 到目前为止并不奇怪。

现在我的问题是:有没有一种方法可以在不破坏语义的情况下消除这种易变性?我可以使用经常提到的 const_cast<> 或简单的 C-cast,但编译器会做什么呢?我什至可以只使用 memcpy() 数据 - 但话又说回来,结果会是什么?

任何建议都将受到欢迎 - 使用 C-only 包装器或任何其他方法我完全没有问题 - 只要它有效(tm),但我最后的选择是一些小的类似 memcpy 的汇编代码真正读取数据 - 这是我想避免的事情。

感谢您花时间阅读本文:-)

编辑:添加小代码片段:

struct shared_memory{
     sc_time time1;
     sc_time time2;
     sc_time time3;
     ...
}

...

class foo 
{
    foo();   // attach shared memory and assign to *mem
    ...
    pthread_mutex_t mutex;
    volatile struct shared_memory *mem;
    ...
    void do_stuff();  // periodically called
};

void foo::do_stuff()
{
   ...
   lock_mutex(mutex);
   sc_time t1 = mem->time1;
   sc_time t2 = mem->time2;
   sc_time t3 = mem->time3;
   unlock_mutex(mutex);
   ... 
   while(t1 < t2 || t1 < t3){
       lock_mutex(mutex);
       t1 = mem->time1;
       t2 = mem->time2;
       t3 = mem->time3;
       unlock_mutex(mutex);
   }

}

最佳答案

如果您必须自旋等待变量的更改,则您没有正确锁定。自旋等待总是必须假定对数据的原子访问。这不仅与获取最新版本的数据有关,还与一致性有关,例如,数据可能会拆分为多个缓存行,您可能只获取旧版本的低字节和更新版本的高字节。

因此,新的 C 和 C++ 标准具有用于原子访问的概念和工具,请尽可能使用它们。如果您没有它们,请使用编译器(或库)扩展:所有现代处理器都有原子指令,任何像样的编译器都有提供此类功能的扩展。

volatile 玩游戏不是你应该走的路。如果您放弃 volatile 并将这样的对象传递给一个不希望在其下发生任何变化的函数,那么所有事情都可能发生。特别是,当没有 volatile 的库被编译时,可以执行破坏数据的优化。不要这样做。

编辑:因为您还用 gcc 标记了您的问题,所以他们有一个很好的理由 __sync_lock_test_and_set 内置函数作为扩展。用它。也许根据您的特定架构组合,这将解析为完全相同的代码,但请相信 gcc 人员,他们知道何时必须添加一些汇编程序魔法来为您提供有关数据的保证。

关于c++ - 将 volatile 数据与未为 volatile 数据重载的方法一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18506653/

相关文章:

xcode - 如何在 Lion 下将 PPC/PPC64 支持添加回 Xcode 4.2?

gcc - C程序找不到包含在头文件中的函数

mysql - 当尝试更改表时,我收到 "The table ' some table' is full”。为什么?

c++ - 为什么子类重写虚函数不能改变父类默认函数参数?

c++ - condition_variable.notify_all 是否应该被互斥锁覆盖?

c++ - 如何在 C++ 模板函数中设置默认值?

c++ - 对齐 SSBO 的内存(它是包含数组的结构数组)?

c - GCC优化错失良机

memory - Intellij IDEA 在打开的项目窗口之间共享的 ls -Xmx 内存限制?

c++ - 在共享内存中存储许多变量