/////////////////////////////////////////////////////////////////////////////// // Unregister - Remove a subject/observer relationsship Error ChangeManager::Unregister( ISubject* pInSubject, IObserver* pInObserver ) { Error curError = Errors::Failure; if (pInSubject && pInObserver) { SCOPED_SPIN_LOCK(m_swUpdate); u32 uID = pInSubject->getObserverId(this); if (m_subjectsList.size() <= uID || m_subjectsList[uID].m_pSubject != pInSubject) { return Errors::Failure; } ASSERT(m_subjectsList[uID].m_pSubject == pInSubject); auto& observersList = m_subjectsList[uID].m_observersList; auto itObs = std::find(observersList.begin(), observersList.end(), pInObserver); if (itObs != observersList.end()) { observersList.erase(itObs); if (observersList.empty()) { m_subjectsList[uID].m_pSubject = nullptr; m_freeIDsList.push_back(uID); pInSubject->Detach(this); } curError = Errors::Success; } } return curError; }
/////////////////////////////////////////////////////////////////////////////// // RemoveSubject - Remove a subject Error ChangeManager::RemoveSubject(ISubject* pSubject ) { Error curError = Errors::Undefined; std::vector<ObserverRequest> observersList; { SCOPED_SPIN_LOCK(m_swUpdate); u32 uID = pSubject->getObserverId(this); ASSERT(uID != ISubject::InvalidObserverID); ASSERT(m_subjectsList[uID].m_pSubject == pSubject); if (m_subjectsList.size() <= uID || m_subjectsList[uID].m_pSubject != pSubject) { return Errors::Failure; } observersList = m_subjectsList[uID].m_observersList; m_subjectsList[uID].m_pSubject = nullptr; m_freeIDsList.push_back(uID); curError = Errors::Success; } for (auto itObs = observersList.begin() ; itObs != observersList.end(); ++itObs) { pSubject->Detach(itObs->m_pObserver); } return curError; }
Error GraphicsObject::ChangeOccurred( ISubject* pSubject, System::Changes::BitMask ChangeType ) { ASSERT( m_bInitialized ); #if 0 if ( !m_pNode ) { // StaticGeom and InstancedGeom objects are abstract groupings and // are not globally attached to any scene node return Errors::Success; } if ( ChangeType & (System::Changes::Geometry::Position | System::Changes::Geometry::Orientation | System::Changes::Geometry::Scale) ) { IGeometryObject* pGeometryObject = dynamic_cast<IGeometryObject*>(pSubject); if ( NeedsLocking(m_pNode) ) { SCOPED_SPIN_LOCK(OGREGraphicsScene::m_mutex); UpdateGeometry( m_pNode, ChangeType, pGeometryObject ); } else { UpdateGeometry( m_pNode, ChangeType, pGeometryObject ); } } #endif return Errors::Success; }
/////////////////////////////////////////////////////////////////////////////// // InitThreadLocalData - Init thread specific data void ChangeManager::InitThreadLocalData(void* arg) { ASSERT(arg && "ChangeManager: No manager pointer passed to InitThreadLocalNotifyList"); ChangeManager* mgr = (ChangeManager*)arg; // Check if we have allocated a NotifyList for this thread. // The notify list is keep in tls (thread local storage). if(::TlsGetValue(mgr->m_tlsNotifyList) == nullptr) { // Reserve some reasonable space to avoid delays because of multiple reallocations auto* pList = new std::vector<Notification>(); pList->reserve(8192); ::TlsSetValue(mgr->m_tlsNotifyList, pList); // Lock out the updates and add this NotifyList to m_NotifyLists SCOPED_SPIN_LOCK(mgr->m_swUpdate); mgr->m_NotifyLists.push_back(pList); } }
/////////////////////////////////////////////////////////////////////////////// // Register - Register a new subject/observer relationsship Error ChangeManager::Register(ISubject* pInSubject, System::Changes::BitMask observerIntrestBits, IObserver* pInObserver, System::Types::BitMask observerIdBits) { Error curError = Errors::Failure; if (pInSubject && pInObserver) { // Lock out updates while we register a subjext SCOPED_SPIN_LOCK(m_swUpdate); u32 uID = pInSubject->getObserverId(this); if (uID != ISubject::InvalidObserverID) { // Subject has already been registered. Add new observer to the list SubjectInfo& si = m_subjectsList[uID]; si.m_observersList.push_back(ObserverRequest(pInObserver, observerIntrestBits, observerIdBits)); observerIntrestBits &= ~si.m_interestBits; if (observerIntrestBits) { si.m_interestBits |= observerIntrestBits; pInSubject->UpdateInterestBits(this, observerIntrestBits); } } else { // New subject if (m_freeIDsList.empty()) { // No zero ID should ever be assigned, so use pre-increment uID = ++m_lastID; ASSERT(uID == m_subjectsList.size()); m_subjectsList.resize(uID + 1); } else { uID = m_freeIDsList.back(); m_freeIDsList.pop_back(); } SubjectInfo& si = m_subjectsList[uID]; si.m_pSubject = pInSubject; si.m_observersList.push_back(ObserverRequest(pInObserver, observerIntrestBits, observerIdBits)); si.m_interestBits = observerIntrestBits; pInSubject->Attach(this, observerIntrestBits, uID); } curError = Errors::Success; } return curError; }