[ glorius @ 12.06.2013. 17:00 ] @
Preciznije, pitanje se odnosi na updateovanje liste observera u subject-u posle brisanja nekog od observera. Naravno, brisanje se ne odvija u subject objektu vec u nekoj drugoj funkciji zaduzenoj za brisanje objekata.
Posle brisanja observer objekta (pomocu neke deleteObject funkcije koja se nalazi u ObjectManager objektu koji odrzava listu objekata), Subject jos uvek sadrzi pointer (koji vise nije validan) na obrisani observer objekat.

Malo sam istrazivao i uvideo da postoje 3 resenja za ovo ali nisam siguran koje je najbolje.

1. U destruktoru objekta koji se brise da se pozove funkcija koja obavestava Subject(e) tog objekta da je on pred brisanjem (subject->observerAboutToRemove(this)) i da se taj objekat izbaci iz liste svih subjecta koji ga sadrze kao observer.

2. Da se obrisani observeri izbrisu iz liste u Notify funkciji:

Code:


// .h
list<boost::weak_ptr<DObject> > m_observers;

// .cpp
void DObject::notify(int eventId, void *pData)
{
    // brisemo sve expired weak_ptrs
    m_observers.remove_if(bind(&boost::weak_ptr<DObject>::expired, _1));

    foreach(boost::weak_ptr<DObject> wpObj, m_observers)
    {
        if(boost::shared_ptr<DObject> obj = wpObj.lock())
        {
            obj->onNotify(shared_from_this(), eventId, pData);
        }
    }
}



3. Koriscenje 'Delayed deallocation' http://www.boost.org/doc/libs/...s/smart_ptr/sp_techniques.html ali cu onda morati da m_observers cuvam kao listu shared_ptr. Kreirao bih globalnu listu _objectsForRemoving i onda bih brisao sve objekte izjednom u nekom pogodnom trenutku za to, npr. u main loop.

Meni se najvise dopada resenje 1. ali nisam siguran da li je dobro... Mozda se desi da u nekoj tacki i subject i observer budu nevalidni ili mozda jos neki bug...
Resenje 2. je ok ali mi nije elegantno.
Resenje 3. je mozda idealno, samo da se vidi u kom trenutku je najpogodnije prazniti listu obrisanih observera.

Da li imate neka iskustva sa ovim interesantnim problemom i mozda neki savet kako je najbolje napraviti ovaj sistem?
[ Rapaic Rajko @ 12.06.2013. 21:08 ] @
Pitanje: sa koliko thread-ova ta masinerija funkcionise? Sve radi pod jednim thread-om ili svaki observer (+ObjectManager) ima svoj thread? Koji thread izvrsava destructor observera, a koji ih (observers) kreira?

Pozz ;)
[ deerbeer @ 12.06.2013. 21:17 ] @
Prva opcija je po meni najbolja ..
a ako ima vise niti u sistemu brisanje observera u ObjectManageru (tj. neka lista ili vektor) treba da bude thread-safe tj. pod nekom kriticnom sekcijom .
[ Mihajlo Cvetanović @ 13.06.2013. 09:33 ] @
Rešenje 4: svaki objekat da ima svoj brojač referenci, kao i funkcije AddRef i Release. U tim funkcijama se (pod kritičkom sekcijom) inkrementira i dekrementira brojač, a ako brojač padne na nulu onda se izvršava delete this;
[ glorius @ 13.06.2013. 23:55 ] @
Iskreno, nisam razmisljao o thread-ovima niti znam mnogo o njima.

Inace, koristim boost::shared_ptr (u kombinaciji sa weak_ptr). Oni vec u sebi sadrze reference counting tako da bi mozda uvodjenje AddRef() i Release() bilo suvisno?
Malo sam analizirao kako rade sa thread-ovima i uvideo da je shared_ptr thread safe ali objekat na koji referencira moze a i ne mora biti (verovatno to znaci da su inc/dec reference count-a pod mutexom - izvinjavam se ako mi je terminologija losa posto nisam mnogo radio sa threads).
Evo i linka gde se objasnjava thread safety za shared_ptr/weak_ptr: http://en.wikipedia.org/wiki/S...ointer#shared_ptr_and_weak_ptr

Posto nisam mnogo radio sa threadovima, definitivno cu napraviti mali test da vidim kako sve to treba da funkcionise ali nisam siguran gde bih koristio threads.
Planiram da napravim portabilan 2D engine za PC, MacOS, iOS i Android. Objekti koji bi radili sa ObjectManager bi bili Renderer, Box2D za fiziku i Lua za scripting, npr.
Meni se cini da bi samo Renderer bilo dovoljno smestiti u poseban thread i ako je verovati malopredjasnjim podacima o shared_ptr onda bi dovoljno bilo (nekako) napraviti proveru u Renderer-u da li je shared_ptr validan ili ne...
Mislim da cu definitivno pravljenje/brisanje i reparenting objekata (posto imam i parent/child sistem) uraditi u jednom threadu striktno.

Na kraju, da li mi uopste treba vise thread-ova ovde?

Sto se tice subject/observer issue-a, definitivno cu odbaciti verziju 2 posto mi nije clean.
Verzija 3. je mozda najcistija ali cu razmotriti i verziju 1.




[ deerbeer @ 17.06.2013. 09:01 ] @
Citat:

Sto se tice subject/observer issue-a, definitivno cu odbaciti verziju 2 posto mi nije clean.

Ne bih rekao . Sasvim je validno resenje kao i prvi scenario s obzirom da koristis weak_ptr pointere.
Oni garantuju da cak i ako drugi tread obrise observer objekat mozes ispitati njegovo prisustvo sa expired metodom ili lock ,
i ako je expired obrises ga iz liste sto si vec koliko mi se cini i uradio..