Как разделить один критический раздел между двумя классами - PullRequest
1 голос
/ 18 апреля 2011

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

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

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 () должны быть синхронизированы. Я случайно использую объект crit_section для синхронизации, но удивляюсь, как мне это сделать.

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

  1. BAD - создать подходящий элемент (critical_section m_cs;) из A или B и
    a) понижать с IA до A (или с IB до B соответственно) и использовать его
    б) сделать его статическим и вызвать A::m_cs (или B::m_cs)

  2. BETTER - создать дополнительный одноэлементный объект / структуру, который будет управлять объектом критической_секции и предоставлять к нему доступ:

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

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

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

1 Ответ

2 голосов
/ 18 апреля 2011

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

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

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

class B : public IB { 
    IA* m_ia; 
    critical_section & m_cs; //reference
    public:
           B(critical_section & 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
}
...