Avoid deadlocks using non-virtual public interface and C ++ cloud blocking

I have a problem that seems unpleasant to me. It seems I found a situation that is easy enough to work with, but it can lead to problems if: a) I run out of concentration during programming or b) someone else starts implementing my interfaces and does not know how to handle this situation.

Here is my main setup:

I have an abstract class that I use as a common interface for several data types. I adopted the paradigm of a non-virtual public interface (Sutter, 2001), as well as a fixed lock to ensure thread safety. An example interface class would look something like this (I did not mention locking and implementing the mutex, since I do not think they are relevant):

class Foo
{
public:
    A( )
    {
        ScopedLock lock( mutex );
        aImp( );
    }
    B( )
    {
        ScopedLock lock( mutex );
        bImp( );
    }
protected:
    aImp( ) = 0;
    bImp( ) = 0;
}

Then the user must implement aImp and bImp in which the problem occurs. If aImp performs some operation that uses bImp, it is extremely simple (and almost logical, in a sense) for this:

class Bar
{
protected:
    aImp( )
    {
        ...
        B( );
        ...
    }
    bImp( )
    {
        ...
    }
}

. , - , ( B() bImp() ). , , , , .

- , ?

, . , , Windows EnterCriticalSection LeaveCriticalSection, . . boost:: mutex boost:: shared_mutex , , , (, -, ).

+3
3

:

class Foo
{
public:
  void A( )
    {
      ScopedLock lock( mutex );
      aImp( );
    }
  void B( )
    {
      ScopedLock lock( mutex );
      bImp( );
    }

protected:
  virtual void aImp( ) = 0;
  virtual void bImp( ) = 0;
};

class FooMiddle : private Foo
{
public:
  using Foo::aImp;
  using Foo::bImp;
};

class Bar : public FooMiddle
{
  virtual void aImpl ()
  {
    bImp ();
    B ();                   // Compile error - B is private
  }
};

Foo , FooMiddle , Bar A B. aImp bImp, FooMiddle , .

, , , - Pimpl. :

class FooImpl
{
public:
  virtual void aImp( ) = 0;
  virtual void bImp( ) = 0;
};

class Foo
{
public:
  void A( )
    {
      ScopedLock lock( mutex );
      m_impl->aImp( );
    }
  void B( )
    {
      ScopedLock lock( mutex );
      m_impl->bImp( );
    }

private:
  FooImpl * m_impl;
}

, , FooImpl, "Foo", "A" "B".

+7

. , . , , .

, :

boost::recursive_mutex

http://www.boost.org/doc/libs/1_32_0/doc/html/recursive_mutex.html

- . Win32 CRITICAL_SECTION ( Enter/LeaveCriticalSection) , .

+6

, , , , , .

, , , , .

, X . - .

A() {
   ScopedLock
   use(x)
   aImp()
   use(x)
}

aImp() {
   ScopedLock
   use(x)
}

, .

, , . , , .

A() {
   {
      ScopedLock
      use(x)
   }
   aImp()
   {
      ScopedLock
      use(x)
   }
}

.

, ( ), . , . , .

+1

Source: https://habr.com/ru/post/1707864/


All Articles