/////////////////////////////////////////////////////////////////////////////// // Attach - Associate an observer with this subject Error CSubject::Attach(IObserver* pObserver, System::Types::BitMask inInterest, u32 uID, u32 shift) { // To make compiler happy in release builds while keeping the next assertion UNREFERENCED_PARAM (shift); // If the following assertion fails, it means that Change Control Manager (CCM) // was modified to start using "shifts". Please update the code of this class // appropriately (original version did not have any meaningful support except // shifting inInterest on entry) ASSERT (!shift && "CSubject::Attach: Interest bits are shifted. Read the comment to this assertion"); // Since the intended usage model is to use this method from CCMs only, and // their implementation provided by this framework ensures that pObs in nonzero // the following assertion should suffice. ASSERT( pObserver && "CSubject::Attach: Valid pointer to observer object must be specified" ); #if SUPPORT_CONCURRENT_ATTACH_DETACH_TO_SUBJECTS SpinWait::Lock lock(m_observerListMutex); #endif // Framework's CCM implementation ensures that the following assertion always holds ASSERT( std::find(m_observerList.begin(), m_observerList.end(), pObserver) == m_observerList.end() && "CSubject::Attach: Observer has already been attached. Use CSubject::UpdateInterestBits instead." ); // Add the observer to our list of observers m_observerList.push_back( ObserverRequest(pObserver, inInterest, uID) ); return Errors::Success; }
/////////////////////////////////////////////////////////////////////////////// // 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; }
/////////////////////////////////////////////////////////////////////////////// // Register - Register a new subject/observer relationsship Error ChangeManager::Register(ISystemObject* pInSubject, IObserver* pInObserver) { BOOST_ASSERT_MSG(pInSubject != nullptr, "Subject cannot be null"); BOOST_ASSERT_MSG(pInObserver != nullptr, "Observer cannot be null"); auto observerIntrestBits = pInObserver->GetDesiredSystemChanges(); if (pInSubject->GetPotentialSystemChanges() & observerIntrestBits) { // Lock out updates while we register a subject tbb::spin_mutex::scoped_lock _lock(m_swUpdate); unsigned int uID = pInSubject->getObserverId(this); if (uID != ISystemObject::InvalidObserverID) { // Subject has already been registered. Add new observer to the list SubjectInfo &si = m_subjectsList[uID]; si.m_observersList.push_back(ObserverRequest(pInObserver, uID, observerIntrestBits)); 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; BOOST_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, uID, observerIntrestBits)); si.m_interestBits = observerIntrestBits; pInSubject->Attach(this, observerIntrestBits, uID); } } return Errors::Success; }