[ glorius @ 04.08.2010. 21:51 ] @
Da li ovaj kod prouzrokuje cycle i ako da kako resiti problem ( napominjem da moram koristiti shared_ptr, mogu i weak_ptr za break cycle ali ne znam kako )

Code:


#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <list>

class SomeClass : public boost::enable_shared_from_this<SomeClass>
{
public:
    SomeClass() {}
    ~SomeClass() {}

    void setParent(boost::shared_ptr<SomeClass> pParent);

    boost::shared_ptr<SomeClass> m_pParent;
    std::list<boost::shared_ptr<SomeClass> > m_listChildren;
};

void SomeClass::setParent(boost::shared_ptr<SomeClass> pParent)
{
    m_pParent = pParent;
    m_pParent->m_listChildren.push_back(shared_from_this());
}
[ djelovic @ 05.08.2010. 07:12 ] @
Glorius,

Da, kod sadrzi cikluse. Ako zamislis slucaj da imas jednog roditelja i jedno dete u stablu, a da tvoj spoljni kod ima shared_ptr na roditelja, onda je ref count roditelja 2, a deteta 1.

Kada ti odbacis svoj shared_ptr na roditelja, ostace ti dva objekta koji pokazuju jedan na drugoga sa ref countom 1, i imaces leak.

Resenje je da ti m_listChildren sadrzi kolekciju obicnih ili weak pointera na roditelja.

Dejan

P.S. Razmisli da zamenis std::list sa std::vector u ovom slucaju. Na kesiranim arhitekturama linkovane liste imaju katastrofalne performanse.
[ glorius @ 05.08.2010. 18:44 ] @
Super! Hvala na odgovoru.
Izmenio sam tako da je sada m_pParent weak_ptr i vise nema mem leaks.

Jos jedan problem je da ja dobijam raw parent pointer u funkciji a moram da koristim weak_ptr ( kao sto smo diskutovali malopre ) da bih izbegao CR.
Moje resenje je ovo, ali nisam siguran da li je dobro.

Code:


SomeClass::bind(SomeClass * pParent)
{
         shared_ptr<SomeClass> spParent(pParent); // konstruisem shared_ptr od raw
         spParent->addChild(shared_from_this());
         m_pWeakPtrParent = spParent;
}



Da li ima elegantnijeg resenja, ako je ovo uopste neko razumno resenje?

[ Goran Arandjelovic @ 11.08.2010. 13:52 ] @
Da, u principu, od shared_ptr-a se kreira weak_ptr. E sada, jedino o čemu savetujem da vodiš računa o sledećem:

Code:

shared_ptr<int> sptr(new int(10));
weak_ptr<int> wptr(sptr);

if(int *p = wptr.get()) // linija X
{
  // korisćenje pointera p // linija Y
}


E sada, ako neki drugi thread pozove sptr.reset() posle linije X, ali pre linije Y, onda p više nije validan.
Tako da bi trebalo da kreiraš privremeni shared_ptr iz wptr-a lockovanjem...

Code:

if(shared_ptr<int> temp_ptr = wptr.lock()
{
  // bezbedno korišćenje pointera p
}


Pošto već koristiš weak_ptr, ovo je zgodno znati...
[ glorius @ 14.08.2010. 11:45 ] @
Jasno, tako sam i radio. Lock i onda proverim da li je validan.
Iako je mocan, shared_ptr je i po malo nezgodan kada se mesaju obicni i shared_ptr kao u primeru koji sam naveo:

Code:

SomeClass::bind(SomeClass * pParent)
{
         shared_ptr<SomeClass> spParent(pParent); // konstruisem shared_ptr od raw
         spParent->addChild(shared_from_this());
         m_pWeakPtrParent = spParent;
}


Kod je tako dizajniran da bind prima raw pointer. spParent ne zna sta se desava sa pointerom posle bind() funkcije, ako jos neki shared pointer preuzme pParent spParent to nece znati i pParent se moze obrisati. Srecom, u mom kodu mogu to da kontrolisem tako da sam siguran da se posle bind-a pParent ne koristi vise tako da posle mogu raditi samo sa shared_ptr.