为什么std::atomic中的所有成员函数都同时出现在有volatile和没有volatile的情况下
Why do all the member functions in std::atomic appear both with and without volatile?
我注意到std::atomic<T>
类型的大多数成员函数都声明了两次,一次使用volatile
修饰符,一次不使用(示例(。我检查了G++标准库实现的源代码,发现它们都是完全重复的,例如
bool
load(memory_order __m = memory_order_seq_cst) const noexcept
{ return _M_base.load(__m); }
bool
load(memory_order __m = memory_order_seq_cst) const volatile noexcept
{ return _M_base.load(__m); }
我找不到任何例子表明volatile
变体的行为与非volatile
变体不同,返回类型或诸如此类的东西也不同
为什么?我认为volatile
成员函数也可以在非volatile
的对象中调用。因此,声明和定义std::atomic::load(...) const volatile noexcept
等就足够了。
更新:
根据这些评论,我的问题基本上可以归结为:你能提供一个例子吗?在以下两种情况下,使用非volatile
实例(不一定是std::atomic
(的一些调用会生成不同的程序集,
每个成员函数都出现在具有和不具有
volatile
、的同一主体中只有
volatile
变体存在?
这是假设编译器可以进行标准允许的任何优化(或者只是最高优化级别(。
也许这一切都源于volatile
是什么,请参阅这个答案。由于与通常的应用程序开发相比,用例非常少,所以通常没有人关心。我假设您没有任何实际的场景,您想知道是否应该应用这些不稳定的过载。然后我会尝试想出一个你可能需要的例子(不要认为它太真实(。
volatile std::sig_atomic_t status = ~SIGINT;
std::atomic<int> shareable(100);
void signal_handler(int signal)
{
status = signal;
}
// thread 1
auto old = std::signal(SIGINT, signal_handler);
std::raise(SIGINT);
int s = status;
shareable.store(10, std::memory_order_relaxed);
std::signal(SIGINT, old);
// thread 2
int i = shareable.load(std::memory_order_relaxed);
memory_order_relaxed
保证原子性和修改顺序的一致性,没有副作用。volatile
不能因副作用而重新排序。那么,在线程2中,您可以得到等于10的shareable
,但状态仍然不是SIGINT
。但是,如果将类型限定符设置为必须保证的shareable
的volatile
。为此,您需要成员方法是volatile
限定的。
你为什么要做这样的事?我可能会想到的一种情况是,您有一些旧代码使用了旧的基于volatile
的东西,并且由于某种原因无法修改它。很难想象,但我想atomic
和volatile
内联程序集之间可能需要某种有保证的顺序。IMHO的底线是,只要有可能,您就可以使用新的原子库而不是volatile
对象,如果有一些volatile
对象无法删除,并且您想使用atomic
对象,那么您可能需要atomic
对象的volatile
限定符来具有适当的排序保证,因此您需要重载。
更新
但如果我只想让原子类型同时可用作易失性和非易失性,为什么不实现前者呢?
struct Foo {
int k;
};
template <typename T>
struct Atomic {
void store(T desired) volatile { t = desired; }
T t;
};
int main(int i, char** argv) {
//error: no viable overloaded '='
// void store(T desired) volatile { t = desired; }
Atomic<Foo>().store(Foo());
return 0;
}
load
和其他操作也是如此,因为它们通常不是需要复制运算符和/或复制构造函数(也可以是volatile
或非volatile
(的琐碎实现。
- 在没有太多条件句的情况下,我如何避免被零除
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 在未初始化映射的情况下,将值插入到映射的映射中
- 是默认情况下分配给char数组常量的值
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 如何在不产生任何垃圾的情况下获得C中的像素
- 在已经使用Git的情况下减少编译时间
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 如何在没有信号的情况下从C++执行QML插槽
- 如何在不知道向量大小的情况下输入向量内部的向量?
- 为什么在某些情况下不写入此文件?
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 在没有Xcode的情况下在Mac捆绑包中嵌入框架
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 为什么std::atomic中的所有成员函数都同时出现在有volatile和没有volatile的情况下
- 为什么volatile变量即使在非常简单的情况下也没有优化
- 易失性指针指向函数,在没有 typedef 的情况下使用时显示编译错误;需要帮助"void (* volatile userFunc)(void)"
- 互斥锁函数在没有volatile的情况下是否足够
- 为什么在一种情况下模板参数需要volatile,而在另一种情况下不需要