gpt4 book ai didi

c - 对复杂 C11 原子类型和非原子读取优化的部分更新

转载 作者:太空宇宙 更新时间:2023-11-04 02:31:46 25 4
gpt4 key购买 nike

我认为描述我的问题的简单方法是在代码中演示它,所以这里是一个人为的 C 示例来突出我有兴趣回答的问题:

// Just some complex user defined type
typedef struct {
...
} state_t;

typedef struct {
state_t states[16];
} state_list_t;

static _Atomic state_list_t s_stateList;
// For non-atomic reads
static state_t * const s_pCurrent = &s_stateList.states[0];

// Called from external threads
void get_state(state_list_t * pStateList)
{
*pStateList = atomic_load(&s_stateList);
}

// Only called by 'this' thread
static void update_state(struct state_data_t const * pData)
{
state_list_t stateList = atomic_load(&s_stateList);
for (int i = 0; i < 16; i++)
{
// Do some updating on the data
do_transition(&stateList[i], pData);
}
atomic_store(&s_stateList, stateList);
}

// Only called by 'this' thread
static void apply_state(state_t const * pState)
{
atomic_store(&s_stateList[0], *pState);
}

// Only called by this thread
static bool check_state()
{
// Check (read) some values in the current state
return isOkay(s_pCurrent);
}

首先,对于任何语法错误,我深表歉意,但这应该能说明问题......

前两个函数非常直接地使用了 C11 原子,即一个线程正在读取另一个线程正在写入的值。我的具体问题实际上是关于最后两个函数,apply_state 和 check_state,它实际上只是归结为这些是否可以做。

在 apply_state 中,您可以看到它只是以原子方式更新结构的一部分,特别是数组的第一个元素。据我了解,基本上 _Atomic s_stateList 的每个元素都被认为是原子的(很像 volatile),因此编译器可以使用 atomic_store 调用,但是当另一个线程“原子地”从对象读取时(即在 get_state 中),这会发生吗),或者同步本质上等同于每次调用中的锁定/解锁相同互斥量?我可以看到它是如何可能的,因为它基本上是一个不同的变量(好吧,相同的地址,但是如果我使用 states[1] 怎么办?)它可能会导致使用不同的互斥体。另外,如果 state_t 恰好是无锁的,会发生什么情况?

我更有信心在这里使用 check_state 函数是一件好事,因为它只对仅由同一线程修改的对象执行读取,但我想知道我是否这里缺少任何东西。我最近才发现,直接访问原子变量(我认为通过赋值或函数参数)就像调用 atomic_load() 或 atomic_store() 一样,所以我想知道是否为非原子读取保留私有(private)引用是一个有值(value)的优化,或者如果编译器足够聪明,可以自行完成类似的优化。

编辑:当取消引用指向原子值的非原子指针时,结果未定义。

最佳答案

不,这不符合 C11 的原子模型,并且有充分的理由。 _Atomic 只是语法上的限定符,语义上 _Atomic 是一种新类型。标准允许此类类型的大小和对齐方式与基类不同,这一事实反射(reflect)了这一点。

在您使用宽原子类型的情况下,允许的原子类型实现是向用作锁的 struct 添加一个隐藏字段。通常,此类类型实现为“非无锁”,即具有控制数据访问的隐藏状态(在 struct 内或单独)。

该标准只能通过将访问模型拼接在一起来保证您的自由竞争。如果您要求您的整个数据是原子可访问的(在一次对整个数据进行不可分割的操作的意义上),该模型只允许您做到这一点。

访问原子对象的各个字段具有未定义的行为。这意味着如果您的平台具有特定属性,它可以允许您访问各个字段。您必须阅读您平台的文档并抱有最好的希望,特别是它们不会从一个版本(编译器、处理器等)更改为另一个版本。

关于c - 对复杂 C11 原子类型和非原子读取优化的部分更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42378887/

25 4 0
文章推荐: html - 如何让 2 个单独的
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com