在 C++ 中轮询原子变量(bool)?
Polling for a atomic variable (bool) in C++?
我有一个修改一个原子变量 (bool) 的线程和另一个想要轮询该变量的线程。我的应用程序在 thread A
中进行了少量函数调用,并开始轮询一个特定的原子变量。 Thread B
继续读取一些外部应用程序 (application on dbus
) 的状态并相应地修改几个原子变量。 Thread A
中的一个函数想要确保如果它 returns,那么一些外部应用程序已经将它的状态更改为期望的状态,它将通过这些原子标志获知。
我的申请详情:
thread A
中的函数是start_scan()
函数,它使用dbus API
开始扫描附近的BLE设备。然而,即使 start scan
调用成功但外部应用程序 (org.bluez
) 仍然需要一些时间来更新它的属性 (Property: Discovering
)。我还定义了像 isScanning
这样的函数,它查询一些变量(我的应用程序内部)以获取外部应用程序的当前状态。每当更新外部应用程序的属性时,它都会通过 dbus
上的 PropertiesChanged
信号通知其他应用程序,是的,在我收到 PropertiesChanged
信号进行扫描之前需要一些时间(不到一秒)成功调用 start_scan
。所以,我想在我从 start_scan
函数 return 之前轮询我的本地原子标志(使用我自己的超时机制),这将确保是否有人在调用 [=26= 之后查询扫描状态],那么 isScanning
将 return 一个有效状态。
我不能使用 condition_variable,因为我有很多函数和标志需要在 syn 中。
问题:
std::atomic<bool> scanning_;
// Thread A
void start_scan()
{
// Dbus methods call
while (scanning_ == false) { // With some timeout
// Timeout mechanism
}
}
// Thread B receving asyn signals from DBus
void propertyUpdate(std::string name, bool value)
{
if (name == "Discovering")
scanning_ = value;
...
}
当线程 A 将轮询 scanning_
标志时,线程 B 将收到 dbus
信号以更新 scanning_
标志。我不确定 Thread A
是否会阻塞线程 B,就好像它会不断读取标志并且我的标志是原子的一样?我想知道如果原子变量可用,等待原子变量访问的线程是如何安排的?
编辑:
我正在做这样的事情:
void setter(bool value)
{
std::lock_guard<std::mutex lock(mutex_);
member_ = value;
}
bool getter(void)
{
std::lock_guard<std::mutex lock(mutex_);
return member_;
}
// Thread A is blocking on a class member value
while (getter() == false);
// Thread B will modify the class member when required
setter(true);
我想知道由于在公共互斥锁上调度阻塞线程可能会遇到的问题。线程 A 是否有可能继续获取 mutex_ 而线程 B 将永远被阻塞。如果线程 B 未在线程 A return 中的 getter
函数之后和线程 A 再次获取 mutex_ 之前调度,则可能会发生这种情况。
如果您需要阻塞线程直到条件变为真(在您的情况下,scanning_
超时),那么您应该使用 condition variables。这样,scanning_
将只是一个普通变量,而不是原子变量,并且它将受到互斥锁的保护。
(可以使用原子变量进行某些线程通信,但不能仅使用原子变量使线程休眠。在您的示例中,start_scan 不断运行,占用 CPU 时间)
我有一个修改一个原子变量 (bool) 的线程和另一个想要轮询该变量的线程。我的应用程序在 thread A
中进行了少量函数调用,并开始轮询一个特定的原子变量。 Thread B
继续读取一些外部应用程序 (application on dbus
) 的状态并相应地修改几个原子变量。 Thread A
中的一个函数想要确保如果它 returns,那么一些外部应用程序已经将它的状态更改为期望的状态,它将通过这些原子标志获知。
我的申请详情:
thread A
中的函数是start_scan()
函数,它使用dbus API
开始扫描附近的BLE设备。然而,即使 start scan
调用成功但外部应用程序 (org.bluez
) 仍然需要一些时间来更新它的属性 (Property: Discovering
)。我还定义了像 isScanning
这样的函数,它查询一些变量(我的应用程序内部)以获取外部应用程序的当前状态。每当更新外部应用程序的属性时,它都会通过 dbus
上的 PropertiesChanged
信号通知其他应用程序,是的,在我收到 PropertiesChanged
信号进行扫描之前需要一些时间(不到一秒)成功调用 start_scan
。所以,我想在我从 start_scan
函数 return 之前轮询我的本地原子标志(使用我自己的超时机制),这将确保是否有人在调用 [=26= 之后查询扫描状态],那么 isScanning
将 return 一个有效状态。
我不能使用 condition_variable,因为我有很多函数和标志需要在 syn 中。
问题:
std::atomic<bool> scanning_;
// Thread A
void start_scan()
{
// Dbus methods call
while (scanning_ == false) { // With some timeout
// Timeout mechanism
}
}
// Thread B receving asyn signals from DBus
void propertyUpdate(std::string name, bool value)
{
if (name == "Discovering")
scanning_ = value;
...
}
当线程 A 将轮询 scanning_
标志时,线程 B 将收到 dbus
信号以更新 scanning_
标志。我不确定 Thread A
是否会阻塞线程 B,就好像它会不断读取标志并且我的标志是原子的一样?我想知道如果原子变量可用,等待原子变量访问的线程是如何安排的?
编辑:
我正在做这样的事情:
void setter(bool value)
{
std::lock_guard<std::mutex lock(mutex_);
member_ = value;
}
bool getter(void)
{
std::lock_guard<std::mutex lock(mutex_);
return member_;
}
// Thread A is blocking on a class member value
while (getter() == false);
// Thread B will modify the class member when required
setter(true);
我想知道由于在公共互斥锁上调度阻塞线程可能会遇到的问题。线程 A 是否有可能继续获取 mutex_ 而线程 B 将永远被阻塞。如果线程 B 未在线程 A return 中的 getter
函数之后和线程 A 再次获取 mutex_ 之前调度,则可能会发生这种情况。
如果您需要阻塞线程直到条件变为真(在您的情况下,scanning_
超时),那么您应该使用 condition variables。这样,scanning_
将只是一个普通变量,而不是原子变量,并且它将受到互斥锁的保护。
(可以使用原子变量进行某些线程通信,但不能仅使用原子变量使线程休眠。在您的示例中,start_scan 不断运行,占用 CPU 时间)