相关疑难解决方法(0)

如何在 C++14 中将多字节值写入共享内存?

假设我有两个进程,它们都使用shm_open和共享一个内存块,mmap并且存在一个共享同步原语 - 假设是一个信号量 - 确保对内存的独占访问。即没有竞争条件。

我的理解是,从返回的指针mmap仍必须标记为 volatile 以防止缓存读取。

现在,如何将例如 a 写入std::uint64_t内存中的任何对齐位置?

当然,我会简单地使用std::memcpy但它不适用于指向易失性内存的指针。

第一次尝试

// Pointer to the shared memory, assume it is aligned correctly.
volatile unsigned char* ptr;

// Value to store, initialize "randomly" to prevent compiler
// optimization, for testing purposes.
std::uint64_t value = *reinterpret_cast<volatile std::uint64_t*>(nullptr);

// Store byte-by-byte
unsigned char* src = reinterpret_cast<unsigned char*>(&value);
for(std::size_t i=0;i<sizeof(value);++i)
    ptr[i]=src[i];
Run Code Online (Sandbox Code Playgroud)

神箭

我坚信这个解决方案是正确的,但即使使用-O3,也有 8 个 1 字节传输。这真的不是最优的。

第二次尝试

因为我知道在我锁定内存时没有人会更改内存,所以也许 …

c++ volatile shared-memory c++14

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

编译器是否可以假设没有其他线程会修改参数?

考虑这个功能:

void foo(int * p)
{
   // something
}
Run Code Online (Sandbox Code Playgroud)

编译器是否可以假设没有其他线程会修改p指向的值?或者它是否必须表现得好像可以随时修改此值?

void bar(volatile int * p)
{
}
Run Code Online (Sandbox Code Playgroud)

如果没有,volatile关键字是否有帮助?GOTW#69指出,volatile编译器通常会忽略关键字.

编辑:显然对"编译器假定"这一短语存在一些误解.让我澄清一下:

  • 如果编译器假设,它可以*p在第一次读取时将值放入寄存器,然后使用它直到p超出范围.此时,它应该写入该*p内存地址的值.
  • 如果编译器不这样假设,那么每次*p读取时,编译器都应该从内存中获取它的值,因为有一些其他线程可能会修改它.每次*p更改时,编译器都应将其写入内存,以便其他线程可以读取它

c++ optimization volatile

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

逗号运算符和乱序执行

优化编译器可以重新安排内存访问,CPU可以不按顺序执行指令.

问题是:用逗号运算符分隔语句是否保证了执行的确切顺序?或者唯一的方法是使用内存屏障(这是非常棘手和非标准的)?

如果不是,那么对于逗号分隔语句的执行顺序究竟是什么呢?

c c++

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

错误传递volatile std :: queue <int>丢弃限定符[-fpermissive] C++ 98

我有一个

volatile std::queue<int> requestQueue;
Run Code Online (Sandbox Code Playgroud)

当我尝试在函数内调用其任何方法(pop,push,empty,front等)时,例如:

    while (!requestQueue.empty()){
        ...do something
    }
Run Code Online (Sandbox Code Playgroud)

我收到以下错误.

robot.cpp:43:31: error: passing 'volatile std::queue<int>' as 'this' 
argument of 'bool std::queue<_Tp, _Sequence>::empty() 
const [with _Tp = int, _Sequence = std::deque<int, std::allocator<int> >]'
discards qualifiers [-fpermissive]
Run Code Online (Sandbox Code Playgroud)

我在网上发现可能需要进行类型转换,但我不确定是否是这种情况.

有任何想法吗?提前致谢.

更新

1)程序使用这种数据结构来存储一系列请求,以便服务器可以以自己的服务速率获取请求.

2)volatile用于支持在不同核上运行的功能之间的数据共享.

3)我使用的库的文档说明了以下关于使用的文档

  • 使用static volatile声明全局变量,以便在不同核心中运行的函数之间共享.

c++

3
推荐指数
2
解决办法
2408
查看次数

字节操作在C++ 11中是原子的吗?

那么char上的操作是原子的吗?所以在线程AI中读取char T并在线程BI中写入相同的char T,这些标准操作是原子的吗?

char a;

#thread A
{ 
if(a & 0x01)
  ...

}

#thread B
{ 
 a =0x01;
  ...

}

# ATOMIC?
Run Code Online (Sandbox Code Playgroud)

谢谢!

multithreading atomic c++11

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

是什么从形式上保证了非原子变量不会看到空气中的稀疏值,并且在理论上可以像原子弛豫一样创建数据竞争呢?

这是有关C ++标准的形式保证的问题。

该标准指出,std::memory_order_relaxed原子变量规则允许“凭空” /“出乎意料”的值出现。

但是对于非原子变量,这个例子可以有UB吗?是否r1 == r2 == 42有可能在C ++抽象机?== 42最初都不是变量,因此您不希望任何if主体执行,这意味着不会写入共享变量。

// Global state
int x = 0, y = 0;

// Thread 1:
r1 = x;
if (r1 == 42) y = r1;

// Thread 2:
r2 = y;
if (r2 == 42) x = 42;
Run Code Online (Sandbox Code Playgroud)

上面的示例改编自标准,该标准明确表示原子对象规范允许这种行为

[注意:在以下示例中,要求确实允许r1 == r2 == 42,而x和y最初为零:

// Thread 1:
r1 = x.load(memory_order_relaxed);
if (r1 == 42) y.store(r1, memory_order_relaxed);
// …
Run Code Online (Sandbox Code Playgroud)

c++ multithreading language-lawyer stdatomic data-race

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

在共享内存上使用 volatile 安全吗?

让我们假设如下:

我在 Linux / Mac OS 上有两个进程。

我有mmap共享内存(或在文件中)。

然后在这两个过程中我都有以下内容:

struct Data{
   volatile int reload = 0; // using int because is more standard
   // more things in the future...
};
void *mmap_memory = mmap(...);
Data *data = static_cast<Data *>(mmap_memory); // suppose size is sufficient and all OK
Run Code Online (Sandbox Code Playgroud)

然后在我做的其中一个过程中:

//...
data->reload = 1;
//...
Run Code Online (Sandbox Code Playgroud)

在另一个我做的:

while(...){
    do_some_work();
    //...
    if (data->reload == 1)
        do_reload();
}
Run Code Online (Sandbox Code Playgroud)

这会是线程/进程间安全的吗?

想法来自这里:
https://embeddedartistry.com/blog/2019/03/11/improve-volatile-usage-with-volatile_load-and-volatile_store/

注意:
这对于 来说并不安全std::atomic<>,因为它不“承诺”有关共享内存的任何内容。此外,从两个不同的过程构建/销毁根本不清楚。

c++ volatile shared-memory stdatomic

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

使用boost线程:发出信号并等待终止

我目前正在编写ac/c ++ dll以供以后在Delphi中使用,我对Delphi中的线程比c/c ++更熟悉,尤其是boost.所以我想知道如何实现以下场景?

class CMyClass
{
    private:
        boost::thread* doStuffThread;
    protected:
        void doStuffExecute(void)
        {
            while(!isTerminationSignal()) // loop until termination signal
            {
                // do stuff
            }

            setTerminated(); // thread is finished
        };
    public:
        CMyClass(void)
        {
            // create thread
            this->doStuffThread = new boost::thread(boost::bind(&CMyClass::doStuffExecute, this));
        };

        ~CMyClass(void)
        {
            // finish the thread
            signalThreadTermination();
            waitForThreadFinish();

            delete this->doStuffThread;

            // do other cleanup
        };
}
Run Code Online (Sandbox Code Playgroud)

我有关于提升线程,信号和互斥量的红色无数文章,但我不明白,可能是因为它是星期五;)或者我认为这样做是不可行的?

关心丹尼尔

c++ multithreading boost

2
推荐指数
1
解决办法
2500
查看次数

可以(a == 1 && a == 2 && a == 3)在C或C++中评估为true吗?

我们知道它可以用JavaJavaScript.

但问题是,可以在下面的条件永远评估为true 在C或C++?

if(a==1 && a==2 && a==3) 
    printf("SUCCESS");
Run Code Online (Sandbox Code Playgroud)

编辑

如果a整数.

c c++

2
推荐指数
3
解决办法
414
查看次数

x64:并发写入布尔数组

假设我在 C 中有一个这样的数组:

static volatile bool my_array[128] = {0};
Run Code Online (Sandbox Code Playgroud)

最重要的是,我有 128 个线程,每个线程在完成时都会写入不同的索引。true

这会产生一些问题吗?在 x64 上写入单个字节不会影响周围的字节,对吗?

我只是问,因为我不确定CPU/内存控制器/等是否总是读取8(或4)字节,然后写入它们。这会产生一些奇怪的竞争条件。

多谢

c memory 64-bit x86 volatile

2
推荐指数
1
解决办法
106
查看次数