Как разделить одну критическую секцию между двумя классами

#c #critical-section

#c #критический раздел

Вопрос:

У меня возникли некоторые проблемы с поиском правильного проектного решения для проблемы совместного использования одного и того же объекта критической секции между двумя классами в разных иерархиях классов.

Представьте:

 class IB;
class IA { 
    public: void method_one(); 
};
class A : public IA { 
    IB* m_ib; 
};

class IB { 
    public: void method_two(); 
};
class B : public IB { 
    IA* m_ia; 
};
  

Теперь вызовы method_one() и method_two() должны быть синхронизированы. Так получилось, что я использую объект critical_section для синхронизации, но мне интересно, как мне это сделать.

Мне удалось выработать несколько идей:

  1. ПЛОХО — создайте подходящий элемент ( critical_section m_cs; ) либо A, либо B и
    а) переместите из IA в A (или из IB в B соответственно) и используйте его
    б) сделайте его статическим и вызовите A::m_cs (или B::m_cs )

  2. ЛУЧШЕ — создайте дополнительный одноэлементный объект / структуру, которая будет управлять объектом critical_section и предоставлять к нему доступ:

     class CriticalSectionProvider {
        //(...)
    public: 
        static critical_sectionamp; GetIt() { static critical_section cs; return cs; }
    }
      

К сожалению, я не доволен ни одним из них и думаю, что у кого-то может быть идея получше.

Как разделить одну критическую секцию между двумя классами в этом случае?

Комментарии:

1. Извлеките защищенный ресурс в его собственный объект и поместите туда критсект.

Ответ №1:

Самый простой подход таков: создайте экземпляр critical_section в main(), прежде чем создавать какие-либо потоки, между которыми вы хотите разделить объект.

Передайте его конструкторам классов и сохраните в качестве ссылки:

 class A : public IA { 
    IB* m_ib; 
    critical_section amp; m_cs; //reference
    public:
           A(critical_section amp; cs) : m_cs(cs) {}
};

class B : public IB { 
    IA* m_ia; 
    critical_section amp; m_cs; //reference
    public:
           B(critical_section amp; cs) : m_cs(cs) {}
};

int main()
{
    critical_section cs = /*create it*/;

    A a = cs; //call the constructor, passing the reference
    B b = cs; //call the constructor, passing the reference
}