/*! Fills this changelist with entries that represent the current state of the system starting at the container with the given id. Prototypes are skipped unless skipPrototypes is false. For every container a 'Create' entry and a 'Change' entry (marking all fields as modified) is added and as many 'AddReference' entries as the ref count of the container. */ void ChangeList::fillFromCurrentState(UInt32 uiFieldContainerId, bool skipPrototypes ) { this->clear(); UInt32 uiNumContainers = FieldContainerFactory::the()->getNumContainers(); if(uiNumContainers <= uiFieldContainerId) { return; } for(UInt32 i = uiFieldContainerId; i < uiNumContainers; ++i) { FieldContainer *pContainer = FieldContainerFactory::the()->getContainer(i); // skip destroyed FC if(pContainer == NULL) continue; // skip prototypes - unless requested if(skipPrototypes == true && (pContainer->getType().getPrototype() == pContainer || pContainer->getType().getPrototype() == NULL )) { continue; } this->addCreated(i, TypeTraits<BitVector>::BitsClear); for(Int32 j = 0; j < pContainer->getRefCount(); ++j) this->addAddRefd(i); ContainerChangeEntry *pEntry = this->getNewEntry(); pEntry->uiEntryDesc = ContainerChangeEntry::Change; pEntry->pFieldFlags = pContainer->getFieldFlags(); pEntry->uiContainerId = i; pEntry->whichField = FieldBits::AllFields; pEntry->pList = this; } }
void RemoteAspect::sendSync(Connection &connection, ChangeList *changeList) { FieldContainerFactoryBase *fcFactory = FieldContainerFactory::the(); if(_statistics) { _statistics->getElem(statSyncTime)->start(); } if(!changeList) { changeList = OSG::Thread::getCurrentChangeList(); } // tell my aspect id connection.putValue(_aspectId); sendIdMapping(connection); ChangeList::ChangedStoreConstIt changedIt = changeList->beginCreated(); ChangeList::ChangedStoreConstIt changedEnd = changeList->endCreated (); for(; changedIt != changedEnd; ++changedIt) { UInt32 localId = (*changedIt)->uiContainerId; FieldContainer *fcPtr = fcFactory->getContainer(localId); // fcPtr might be locally destroyed already or // cluster local, no need to transmit it if((fcPtr == NULL ) || (0x0000 == (fcPtr->getFieldFlags()->_bNamespaceMask & FCLocal::Cluster )) ) { continue; } if((*changedIt)->uiEntryDesc == ContainerChangeEntry::Create) { sendCreated(connection, fcPtr); } } changedIt = changeList->begin(); changedEnd = changeList->end (); for(; changedIt != changedEnd; ++changedIt) { UInt32 localId = (*changedIt)->uiContainerId; FieldContainer *fcPtr = fcFactory->getContainer(localId); // fcPtr might be cluster local, no need to transmit it. // but we need to transmit subrefs for locally destroyed container // so this test is different from the one above! if((fcPtr != NULL ) && (0x0000 == (fcPtr->getFieldFlags()->_bNamespaceMask & FCLocal::Cluster )) ) { continue; } if((*changedIt)->uiEntryDesc == ContainerChangeEntry::AddReference) { sendAddRefed(connection, fcPtr, localId); } else if((*changedIt)->uiEntryDesc == ContainerChangeEntry::SubReference) { sendSubRefed(connection, fcPtr, localId); } else if((*changedIt)->uiEntryDesc == ContainerChangeEntry::Change && fcPtr != NULL ) { sendChanged(connection, fcPtr, (*changedIt)->whichField); } } UInt8 cmd = SYNCENDED; connection.putValue(cmd); #ifndef OSG_REMOTE_ASPECT_SILENT SLOG << "Send SYNCENDED" << std::endl; #endif // write buffer connection.flush(); if(_statistics) { _statistics->getElem(statSyncTime)->stop(); } }
void ChangeList::doApply(bool bClear) { if(_bReadOnly == true) { FWARNING(("Read-only changelist, can not apply\n")); return; } #ifdef OSG_MT_CPTR_ASPECT FieldContainer *pSrc = NULL; FieldContainer *pDst = NULL; ChangedStoreConstIt ccIt = _createdStore.begin(); ChangedStoreConstIt ccEnd = _createdStore.end (); while(ccIt != ccEnd) { AspectStoreP pHandler = FieldContainerFactory::the()->getContainerHandler( (*ccIt)->uiContainerId); if(pHandler == NULL) { #ifndef SILENT_CPTR fprintf(stderr, "Strange handler nil %d %p\n", (*ccIt)->uiContainerId, pHandler); #endif ++ccIt; continue; } pSrc = pHandler->getPtr(_uiAspect ); pDst = pHandler->getPtr(Thread::getCurrentAspect()); if(pSrc == NULL) { #ifndef SILENT_CPTR fprintf(stderr, "Strange src nil %d %p\n", (*ccIt)->uiContainerId, pSrc); #endif ++ccIt; continue; } if(pDst == NULL) { if(0x0000 == ((*ccIt)->whichField & FCLocal::MTMask)) { pDst = pSrc->getType().createAspectCopy(pSrc, (*ccIt)->uiContainerId); Thread::getCurrentChangeList()->addCreated( (*ccIt)->uiContainerId, TypeTraits<BitVector>::BitsClear); #ifndef SILENT_CPTR fprintf(stderr, "Setup store for %d %p \n", (*ccIt)->uiContainerId, pDst); #endif if(pDst != NULL) pDst->setupAspectStore(pHandler); #ifndef SILENT_CPTR pHandler->dump(); #endif } } ++ccIt; } ChangedStoreIt cIt = _changedStore.begin(); ChangedStoreConstIt cEnd = _changedStore.end (); #ifndef SILENT_CPTR fprintf(stderr, "CL apply %u -> %u\n", _uiAspect, Thread::getCurrentAspect()); #endif BitVector syncMode = 0; AspectOffsetStore oOffsets; while(cIt != cEnd) { AspectStoreP pHandler = FieldContainerFactory::the()->getContainerHandler( (*cIt)->uiContainerId); if(pHandler == NULL) { ++cIt; continue; } pSrc = pHandler->getPtr(_uiAspect ); pDst = pHandler->getPtr(Thread::getCurrentAspect()); #ifndef SILENT_CPTR fprintf(stderr, "process changes for %d %p %s %p %s\n", (*cIt)->uiContainerId, pSrc, pSrc != NULL ? pSrc->getType().getCName() : "null", pDst, pDst != NULL ? pDst->getType().getCName() : "null"); #endif if(pDst == NULL && pSrc != NULL) { if((pSrc->getFieldFlags()->_bNamespaceMask & FCLocal::MTMask) != TypeTraits<BitVector>::BitsClear ) { pDst = pSrc->getType().createAspectCopy(pSrc, (*cIt)->uiContainerId); if(pDst != NULL) { Thread::getCurrentChangeList()->addCreated( (*cIt)->uiContainerId, TypeTraits<BitVector>::BitsClear); pDst->setupAspectStore(pHandler); } #ifndef SILENT_CPTR pHandler->dump(); #endif } else { ++cIt; continue; } } #ifndef SILENT_CPTR fprintf(stderr, "Xprocess changes for %d %p %s %p %s | %d %d %p\n", (*cIt)->uiContainerId, pSrc, pSrc != NULL ? pSrc->getType().getCName() : "null", pDst, pDst != NULL ? pDst->getType().getCName() : "null", _uiAspect, Thread::getCurrentAspect(), pHandler); #endif if((*cIt)->uiEntryDesc == ContainerChangeEntry::Change) { if(pSrc != NULL && pDst != NULL) // be safe for now { BitVector mask = ((*cIt)->whichField & pSrc->getFieldFlags()->_bThreadLocalFlags); if(mask != 0x0000) { pHandler->fillOffsetArray(oOffsets, pDst); #ifndef SILENT_CPTR for(UInt32 i = 0; i < ThreadManager::getNumAspects(); ++i) { fprintf(stderr, "offset %d %d\n", i, oOffsets[i]); } #endif UInt32 uiSInfo = /*uiSyncInfo*/ 0 | (_uiAspect << 24) | (Thread::getCurrentAspect() << 16); pDst->execSyncV(*pSrc, mask, oOffsets, syncMode, uiSInfo); } if(bClear == true) { pSrc->clearChangeEntry(*cIt); } } } else if((*cIt)->uiEntryDesc == ContainerChangeEntry::AddReference) { #ifndef SILENT_CPTR fprintf(stderr, "Execute add Ref for %d %s\n", (*cIt)->uiContainerId, pDst->getType().getCName()); #endif if(pDst != NULL) pDst->addReferenceRecorded(); } else if((*cIt)->uiEntryDesc == ContainerChangeEntry::SubReference)// || // (*cIt)->uiEntryDesc == ContainerChangeEntry::DepSubReference) { #ifndef SILENT_CPTR fprintf(stderr, "Execute sub Ref for %d %s\n", (*cIt)->uiContainerId, pDst->getType().getCName()); #endif if(pDst != NULL) { //pDst->subReferenceRecorded(); this->addDelayedSubRef<RecordedRefCountPolicy>(pDst); } } ++cIt; } commitDelayedSubRefs(); Thread::getCurrentChangeList()->commitDelayedSubRefs(); #endif }