相关疑难解决方法(0)

为什么我没有从volatile中提供默认的复制构造函数?

这段代码:

class X {
  int member;  
};

volatile X a;
X b = a;
Run Code Online (Sandbox Code Playgroud)

失败并出现错误:

prog.cpp:6:7: error: no matching function for call to ‘X::X(volatile X&)’
prog.cpp:6:7: note: candidates are:
prog.cpp:1:7: note: X::X()
prog.cpp:1:7: note:   candidate expects 0 arguments, 1 provided
prog.cpp:1:7: note: X::X(const X&)
prog.cpp:1:7: note:   no known conversion for argument 1 from ‘volatile X’ to ‘const X&’
Run Code Online (Sandbox Code Playgroud)

有什么办法可以让编译器为我生成易失性复制构造函数吗?

c++ volatile copy-constructor

22
推荐指数
1
解决办法
2057
查看次数

在R值中使用volatile两次

该声明:

volatile unsigned char * volatile p = (volatile unsigned char * volatile)v;
Run Code Online (Sandbox Code Playgroud)

在MSVC v14.1中生成警告C4197:

警告C4197:'volatile unsigned char*volatile':忽略强制转换中的顶级volatile

2011 C标准([N1570] 6.7.3 4.)规定:"与限定类型相关联的属性仅对表达式有意义,即l值",因此此投射中的顶级volatile将被忽略并生成这个警告.

该代码的作者指出,它不违反C标准,并且需要阻止一些GCC优化.他通过以下代码说明了代码的问题:https://godbolt.org/g/xP4eGz

#include <stddef.h>

static void memset_s(void * v, size_t n) {
  volatile unsigned char * p = (volatile unsigned char *)v;
  for(size_t i = 0; i < n; ++i) {
    p[i] = 0;
  }
}

void f1() {
  unsigned char x[4];
  memset_s(x, sizeof x);
}

static void memset_s_volatile_pnt(void * v, size_t n) {
  volatile unsigned …
Run Code Online (Sandbox Code Playgroud)

c c++ gcc visual-c++

12
推荐指数
1
解决办法
548
查看次数

避免多次读取或写入内存的易失性位域赋值表达式

我想使用易失性位字段结构来设置硬件寄存器,如以下代码

union foo {
    uint32_t value;
    struct {
        uint32_t x : 1;
        uint32_t y : 3;
        uint32_t z : 28;
    };
};
union foo f = {0};
int main()
{
    volatile union foo *f_ptr = &f;
    //union foo tmp;
    *f_ptr =  (union foo) {
        .x = 1,
        .y = 7,
        .z = 10,
    };
    //*f_ptr = tmp;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,编译器会将其多次写入STRLDR HW 寄存器。可怕的是,当寄存器被写入时,它会立即触发硬件工作。

main:
    @ args = 0, pretend = 0, frame = 0
    @ frame_needed …
Run Code Online (Sandbox Code Playgroud)

c embedded assembly volatile bit-fields

4
推荐指数
1
解决办法
405
查看次数

单个编写者+读者的发布/检查更新类可以使用memory_order_relaxed还是获取/发布以提高效率?

介绍

我有一个小类,它使用std :: atomic进行无锁操作。由于该课程被广泛调用,因此影响了性能,并且遇到了麻烦。

类说明

该类类似于LIFO,但是一旦调用pop()函数,它仅返回其环形缓冲区的最后写入元素(仅当自上次pop()之后存在新元素时)。

一个线程正在调用push(),另一个线程正在调用pop()。

我读过的资料

由于这占用了我的计算机时间太多,因此我决定进一步研究std :: atomic类及其memory_order。我已经阅读了很多StackOverflow以及其他来源和书籍中的memory_order帖子,但是我无法对不同的模式有一个清晰的了解。特别是,我在获取和释放模式之间挣扎:我也看不出为什么它们与memory_order_seq_cst不同。

根据我自己的研究,我认为每个记忆顺序都是用我的话做的

memory_order_relaxed:在同一线程中,原子操作是即时的,但是其他线程可能无法立即看到最新的值,它们将需要一些时间才能被更新。编译器或OS可以自由地对代码进行重新排序。

memory_order_acquire / release:由atomic :: load使用。它防止重新排序之前存在的代码行(编译器/ OS可能在此行之后对其重新排序),并使用此线程或另一个线程中的memory_order_releasememory_order_seq_cst读取存储在此原子上的最新值。memory_order_release还可以防止对该代码重新排序之后的代码。因此,在获取/发布中,两者之间的所有代码都可以被OS改组。我不确定这是在同一线程还是不同线程之间。

memory_order_seq_cst:最容易使用,因为就像我们使用变量的自然写法一样,立即刷新其他线程加载函数的值。

LockFreeEx类

template<typename T>
class LockFreeEx
{
public:
    void push(const T& element)
    {
        const int wPos = m_position.load(std::memory_order_seq_cst);
        const int nextPos = getNextPos(wPos);
        m_buffer[nextPos] = element;
        m_position.store(nextPos, std::memory_order_seq_cst);
    }

    const bool pop(T& returnedElement)
    {

        const int wPos = m_position.exchange(-1, std::memory_order_seq_cst);
        if (wPos != -1)
        {
            returnedElement = m_buffer[wPos]; …
Run Code Online (Sandbox Code Playgroud)

c++ atomic lock-free memory-barriers stdatomic

3
推荐指数
1
解决办法
128
查看次数