Подходящее использование для boost :: shared_ptr? - PullRequest
4 голосов
/ 26 марта 2012

Вопрос о boost::shared_ptr здесь:

У меня есть 3 класса.

A - это какой-то главный класс, который отвечает за все.

B - это класс, который просто имеет функции для выполнения некоторой работы.

Dispatcher - это просто класс, который оборачивается вокруг отдельного потока, который получает работу из Instaces B, выполненную в этом потоке.

Так что это выглядит примерно так: A имеет экземпляр Dispatcher. Теперь A создает экземпляр B и передает его диспетчеру.

Важной частью является то, что B необходимо позвонить A::callback(), когда это будет сделано. Вот почему B получает ссылку на A в своем конструкторе (см. Код ниже)

A.hpp

class A : public boost::enable_shared_from_this<A>
{
public:
    A();
    void sendB();
    void callback();
private:
    Dispatcher m_Dispatcher;
};

B.hpp

class B
{
public:
    B(boost::shared_ptr<A> ptr);
    boost::shared_ptr<A> m_PointerToA;
 /* Some other functions */
};

Dispatcher.hpp

class Dispatcher
{
public:
     void run();
     void dispatch(boost::shared_ptr<B> b);
private:
     void doWork();
     boost::thread m_Thread;  
};

a.cpp

A::A()
{
    m_Dispatcher.run();
}
void A::sendB()
{
    boost::shared_ptr ptr_B;
    ptr_B.reset(new B(this->shared_from_this);
    m_Dispatcher.dispatch(ptr_B);
}

B.cpp

B::B(boost::shared_ptr<A> ptr) :
    : m_PointerToA(ptr)
{
}

main_example.cpp

int main()
{
     A instanceA;
     while(true)
     {
          instanceA.sendB();
          /* Do some other stuff */
     }
     return 0;
}

Итак, мой вопрос:

Разумно ли для этой цели использовать boost :: shared_ptr?

Я не уверен, что shared_ptr - это то, что нужно. Моя проблема в том, что я не знаю, что именно происходит, когда я вызываю конструктор из B и передаю ему указатель this. Теперь согласно shared_ptr я бы предположил, что m_PointerToA становится владельцем A. Но это будет означать, что когда работа в Dispatcher будет завершена и мой экземпляр B будет удален, он также удалит ссылку на m_PointerToA, что фактически означает, что он убивает сам объект, несмотря на фактический экземпляр A в основном цикле.

Обновление:

Добавлен код и обновлен сам вопрос, чтобы сделать его более понятным.

Ответы [ 2 ]

4 голосов
/ 26 марта 2012

В этом дизайне нет ничего особенного.Однако я бы предпочел вместо этого использовать boost::function<> & boost::bind.Это дает вам большую гибкость для обратного вызова и не привязывает B так плотно к A. Конечно, вам все равно придется варьировать обычные нити предостережения.

1 голос
/ 26 марта 2012

Да, можно просто скопировать / присвоить shared_ptr, это только увеличит счетчик ссылок.

В вашем примере shared_from_this() создаст (здесь: временный) shared_ptr из weak_ptr, который удерживается this (ref count 1), поэтому при назначении / copy-constructm_PointerToA, счетчик ссылок временно увеличится до 2, прежде чем ctor вернется, и временный объект будет уничтожен, снова уменьшив счетчик ссылок до 1 (shared_ptr «знает» об одном экземпляре в вашем B объекте).

Итак, да, если B будет удален, он уничтожит A в этом случае (так как счетчик ссылок уменьшится до 0).

Ваше беспокойство

Это будет означать, что, если мой экземпляр B будет удален, он также удалит m_PointerToA, который также убьет мой экземпляр A.Конечно, мой оригинальный экземпляр A хранится в другом месте.

показывает только то, что если вы планируете / нуждаетесь / намереваетесь сохранить указатель на экземпляр A для дальнейшего использования, вы должны сделатьтак же и с shared_ptr вместо необработанного указателя.Если у вас есть контроль над интерфейсом A, самый простой способ - использовать именованный конструктор , например:

class A : public boost::enable_shared_from_this<A> {
    public:
        static boost::shared_ptr<A> create();

        void initClassB();
        // ....
    private:
        A();
        A( const A & other );
        A& operator=( const A & rhs );

};

boost::shared_ptr<A> A::create() {
    return boost::shared_ptr<A>( new A() );
}

Тогда, даже если ваш экземпляр B удален, экземпляр A все еще выживет, потому что счетчик ссылок shared_ptr все еще (по крайней мере) 1.

...