gpt4 book ai didi

c++ - 有没有办法在 Linux 上用 C++ 原子地刷新二进制信号量?

转载 作者:行者123 更新时间:2023-12-01 12:46:28 25 4
gpt4 key购买 nike

一些内核在信号量上提供“flush”操作来解除所有等待信号量的任务的阻塞。

例如,VxWorks 有一个 semFlush() API 原子地解除对指定信号量上挂起的所有任务的阻塞,即所有任务在允许运行之前都将被解除阻塞。

我正在 Linux 上实现一个 C++ 类,它的行为类似于二进制信号量,并且还具有这种“刷新”功能。不幸的是,semaphore.h在 Linux 上不提供类似 API 的 flush() 或 broadcast() 。

我尝试过的:使用 condition variables实现二进制信号量 .
这是我的伪代码:

class BinarySem
{
BinarySem();

bool given;
mutex m;
condition_var cv;
give();
take();
take( Timeout T );
tryTake();
flush();
}

BinarySem::BinarySem()
: given(false)
{}

// take(Timeout T), tryTake() not shown
// to make question concise on StackOverflow

BinarySem::give()
{
{
lock_guard lk(m);
given = true;
}
cv.notify_one();
}

BinarySem::flush()
{
{
lock_guard lk(m);
given = true;
}
cv.notify_all();
}

BinarySem::take()
{
unique_lock lk(m);
while(!given)
{
cv.wait(lk);
}
given = false;
lk.unlock();
}

然而,这个 flush()不会以正确的方式行事。
假设,我们有 2 个线程在等待 BinarySem(即它们都调用了 take())。
让这些线程成为 hiPrioThreadloPrioThread .

flush()BinarySem 上被调用对象, hiPrioThread将从 take() 退出并运行。
当它产生时( hiPrioThread 只是产生,它还没有退出), loPrioThread仍然无法运行,因为 bool 值 given现在是 false再次。需要 bool 值来防止虚假唤醒。

相反,信号量的 flush()函数应该只是解除所有线程的阻塞,只要有机会它们就可以运行。

如果我不设置怎么办 given = falsetake() ?这将使我的代码容易受到虚假唤醒的影响,然后当 give() 时多个线程可能会被解除阻塞。用来。

有没有人有什么建议?

最佳答案

从一些“CyclicBarrier”实现中借用一个概念,并有一个生成或循环计数器。

“刷新”信号量然后推进一代。每个接受者在等待之前记下它的代,接受者等待信号量是given或为了世代改变:

BinarySem::flush() {
{
lock_guard lk(m);
current_gen++; // "flush" all waiters from the previous gen
//given = true; // No need to give; the 'current' taker will do this when done
}
cv.notify_all();
}

BinarySem::take() {
lock_guard lk(m);
uint64_t my_generation = current_gen;
while (!given && my_generation == current_gen) {
cv.wait(lk);
}
if (my_generation == current_gen) {
given = false;
}
}

(警告:未经测试)

关于c++ - 有没有办法在 Linux 上用 C++ 原子地刷新二进制信号量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60497508/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com