优雅的互斥开关开/关开关?

Elegant mutex on/off switch for functions?

本文关键字:开关      更新时间:2023-10-16

你能想到一种优雅的方式来使用可选的互斥锁创建(成员)函数吗?出于显而易见的原因,让我们忽略宏。

当然,最简单的方法是具有两个功能:

int getIndex() const    { std::lock_guard m( mtx ); return nm_getIndex(); }
int nm_getIndex() const { return _index; }

这将创建高效的代码,但它依赖于代码复制。基本上,你最终会得到两次大多数函数声明。

另一种方法是将它们转换为模板函数。布尔模板参数将用作"en-/disabler"。然后,您可以像这样调用该函数:

auto index = getIndex< NoMutex >();

每当在内部使用该函数时(否则锁定互斥锁)。这里的问题是确保即使抛出异常,互斥锁也会解锁。也就是说,你不能简单地使用类似的东西

if constexpr( MutexOn == true ) {
mutex.lock();
}
do some stuff;
if constexpr( MutexOn == true ) {
mutex.unlock();
}

我目前唯一能想到的就是围绕互斥体建立一个类,并将其放入一个联合体中。然后,该类可以"玩lock_guard"或不执行任何操作。虽然我很确定这将在发布代码中得到适当优化,但它看起来仍然很麻烦且不灵活。 因此,我想知道您是否能想到更好的东西?

谢谢!

我能想到的最简单的方法是:

  1. 创建一个 noop lock_guard类。

  2. 创建一个模板函数
  3. ,该函数始终使用指定为模板参数的类型的锁保护。

  4. 当你想要一个函数的非/阻塞版本时,你可以传入noop guard

例如:

template<typename Guard>
int getIndex<Guard>() const    { Guard m( lock ); return nm_getIndex(); }
class NoopLockGuard ; //dummy class. it does absolutely nothing
int i = getIndex<NoopLockGuard>()
int j = getIndex<std::lock_guard>()

编译器应该能够使用NoopLockGuard优化版本,以便它会产生最小或零的性能损失。