///////////////////////////////////////////////////////////////////////////////
// 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;
}
Example #3
0
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;
}