我遇到了一个对我来说似乎很困扰的问题。似乎我发现了一种很容易解决的情况,但是如果 a) 我在编程时注意力不集中,或者 b) 其他人开始实现我的接口并且不知道如何处理,这可能会导致问题这个情况。
这是我的基本设置:
我有一个抽象类,用作几种数据类型的通用接口。我采用了非虚拟公共接口范例(Sutter,2001)以及范围锁定来提供一些线程安全性。一个示例接口类看起来像这样(我省略了有关范围锁定和互斥锁实现的细节,因为我认为它们不相关):
class Foo
{
public:
A( )
{
ScopedLock lock( mutex );
aImp( );
}
B( )
{
ScopedLock lock( mutex );
bImp( );
}
protected:
aImp( ) = 0;
bImp( ) = 0;
}
然后由用户来实现 aImp 和 bImp,这就是问题所在。如果 aImp 执行一些使用 bImp 的操作,那么执行此操作非常容易(并且在某种意义上几乎是合乎逻辑的):
class Bar
{
protected:
aImp( )
{
...
B( );
...
}
bImp( )
{
...
}
}
僵局。当然,解决这个问题的简单方法是始终调用受保护的虚函数而不是它们的公共变体(在上面的代码片段中将 B( ) 替换为 bImp( ))。但是,如果我犯了一个错误,或者更糟的是让别人上吊自己,似乎仍然很容易上吊。
有没有人有办法阻止抽象类的实现者在编译时调用这些公共函数,或者帮助避免死锁解决方案?
只是为了踢,一些互斥锁允许操作,这将避免死锁问题。例如,如果我使用 Windows 函数 EnterCriticalSection 和 LeaveCriticalSection 来实现这一点,则没有问题。但我宁愿避免特定于平台的功能。我目前在我的作用域锁实现中使用 boost::mutex 和 boost::shared_mutex ,据我所知,它并没有试图避免死锁(我认为我几乎更喜欢)。