GNU C++ 中的原子交换 [英] Atomic swap in GNU C++

查看:27
本文介绍了GNU C++ 中的原子交换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想验证我的理解是否正确.这种事情很棘手,所以我几乎可以肯定我错过了一些东西.我有一个由实时线程和非实时线程组成的程序.我希望非 RT 线程能够交换指向 RT 线程使用的内存的指针.

I want to verify that my understanding is correct. This kind of thing is tricky so I'm almost sure I am missing something. I have a program consisting of a real-time thread and a non-real-time thread. I want the non-RT thread to be able to swap a pointer to memory that is used by the RT thread.

从文档中,我的理解是这可以在 g++ 中使用:

From the docs, my understanding is that this can be accomplished in g++ with:

// global
Data *rt_data;

Data *swap_data(Data *new_data)
{
#ifdef __GNUC__
    // Atomic pointer swap.
    Data *old_d = __sync_lock_test_and_set(&rt_data, new_data);
#else
    // Non-atomic, cross your fingers.                                          
    Data *old_d = rt_data;
    rt_data = new_data;
#endif
    return old_d;
}

这是程序中唯一修改rt_data 的地方(初始设置除外).当 rt_data 在实时上下文中使用时,它被复制到本地指针.对于old_d,稍后当确定没有使用旧内存时,将在非RT线程中释放它.这样对吗?我在任何地方都需要 volatile 吗?我应该调用其他同步原语吗?

This is the only place in the program (other than initial setup) where rt_data is modified. When rt_data is used in the real-time context, it is copied to a local pointer. For old_d, later on when it is sure that the old memory is not used, it will be freed in the non-RT thread. Is this correct? Do I need volatile anywhere? Are there other synchronization primitives I should be calling?

顺便说一下,我是用 C++ 做这件事的,尽管我对 C 的答案是否不同很感兴趣.

By the way I am doing this in C++, although I'm interested in whether the answer differs for C.

提前致谢.

推荐答案

C/C++中编写并发代码时,一般不要使用volatile.volatile 的语义非常接近你想要的,它很诱人,但最终 volatile 是 不够.不幸的是Java/C# volatile != C/C++ volatile.Herb Sutter 有一篇很棒的文章解释了一团糟.

Generally don't use volatile when writing concurrent code in C/C++. The semantics of volatile are so close to what you want that it is tempting but in the end volatile is not enough. Unfortunately Java/C# volatile != C/C++ volatile. Herb Sutter has a great article explaining the confusing mess.

您真正想要的是内存栅栏.__sync_lock_test_and_set 为您提供围栏.

What you really want is a memory fence. __sync_lock_test_and_set provides the fencing for you.

当您将 rt_data 指针复制(加载)到本地副本时,您还需要一个内存栅栏.

You will also need a memory fence when you copy (load) the rt_data pointer to your local copy.

无锁编程很棘手.如果你愿意使用 Gcc 的 c++0x 扩展,那就简单一点:

Lock free programming is tricky. If you're willing to use Gcc's c++0x extensions, it's a bit easier:

#include <cstdatomic>

std::atomic<Data*> rt_data;

Data* swap_data( Data* new_data )
{
   Data* old_data = rt_data.exchange(new_data);
   assert( old_data != new_data );
   return old_data;
}

void use_data( )
{
   Data* local = rt_data.load();
   /* ... */
}

这篇关于GNU C++ 中的原子交换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆