void ObjectFactorySystem::ProtectedObjectSwapper::ProtectedFunc() { m_ProtectedPhase = PHASE_SERIALIZEOUT; // serialize all out if( m_pLogger ) m_pLogger->LogInfo( "Serializing out from %d old constructors...", (int)m_ConstructorsOld.size()); // use a temporary serializer in case there is an exception, so preserving any old state (if there is any) m_Serializer.SetIsLoading( false ); for( size_t i = 0; i < m_ConstructorsOld.size(); ++i ) { IObjectConstructor* pOldConstructor = m_ConstructorsOld[i]; size_t numObjects = pOldConstructor->GetNumberConstructedObjects(); for( size_t j = 0; j < numObjects; ++j ) { IObject* pOldObject = pOldConstructor->GetConstructedObject( j ); if (pOldObject) { m_Serializer.Serialize( pOldObject ); } } } // swap serializer if( m_pLogger ) m_pLogger->LogInfo( "Swapping in and creating objects for %d new constructors...", (int)m_ConstructorsToAdd.size()); m_ProtectedPhase = PHASE_CONSTRUCTNEW; TConstructors& constructorsNew = m_pObjectFactorySystem->m_Constructors; std::vector<IObject*> old_objects; //swap old constructors with new ones and create new objects for( size_t i = 0; i < m_ConstructorsToAdd.size(); ++i ) { IObjectConstructor* pConstructor = m_ConstructorsToAdd[i]; //replace constructor, but if one exists then replace objects IObjectConstructor* pOldConstructor = m_pObjectFactorySystem->GetConstructor( pConstructor->GetName() ); if( pOldConstructor == pConstructor ) { // don't add constructor if it's already in existance continue; } // Reconstruct objects, starting at end to reduce overhead in factory container if( pOldConstructor ) { // replace and construct pConstructor->SetConstructorId( pOldConstructor->GetConstructorId() ); constructorsNew[ pConstructor->GetConstructorId() ] = pConstructor; for( PerTypeObjectId objId = 0; objId < pOldConstructor->GetNumberConstructedObjects(); ++ objId ) { // create new object if(IObject* old_object = pOldConstructor->GetConstructedObject( objId ) ) { old_objects.push_back(old_object); auto state = pOldConstructor->GetState(objId); pConstructor->Construct(state); } else { pConstructor->ConstructNull(); } } m_ConstructorsReplaced.push_back( pOldConstructor ); } else { ConstructorId id = constructorsNew.size(); m_pObjectFactorySystem->m_ConstructorIds[ pConstructor->GetName() ] = id; constructorsNew.push_back( pConstructor ); pConstructor->SetConstructorId( id ); } } if( m_pLogger ) m_pLogger->LogInfo( "Serialising in..."); //serialize back m_ProtectedPhase = PHASE_SERIALIZEIN; m_Serializer.SetIsLoading( true ); for( size_t i = 0; i < constructorsNew.size(); ++i ) { IObjectConstructor* pConstructor = constructorsNew[i]; for( PerTypeObjectId objId = 0; objId < pConstructor->GetNumberConstructedObjects(); ++ objId ) { // Serialize new object IObject* pObject = pConstructor->GetConstructedObject( objId ); if (pObject) { m_Serializer.Serialize( pObject ); } } } // auto construct singletons // now in 2 phases - construct then init m_ProtectedPhase = PHASE_AUTOCONSTRUCTSINGLETONS; std::vector<bool> bSingletonConstructed( constructorsNew.size(), false ); if( m_pLogger ) m_pLogger->LogInfo( "Auto Constructing Singletons..."); for( size_t i = 0; i < constructorsNew.size(); ++i ) { IObjectConstructor* pConstructor = constructorsNew[i]; if( pConstructor->GetIsAutoConstructSingleton() ) { if( 0 == pConstructor->GetNumberConstructedObjects() ) { pConstructor->GetSingleton(); bSingletonConstructed[i] = true; } } } // Do a second pass, initializing objects now that they've all been serialized // and testing serialization if required m_ProtectedPhase = PHASE_INITANDSERIALIZEOUTTEST; if( m_bTestSerialization ) { if( m_pLogger ) m_pLogger->LogInfo( "Initialising and testing new serialisation..."); } else { if( m_pLogger ) m_pLogger->LogInfo( "Initialising..."); } for( size_t i = 0; i < constructorsNew.size(); ++i ) { IObjectConstructor* pConstructor = constructorsNew[i]; for( PerTypeObjectId objId = 0; objId < pConstructor->GetNumberConstructedObjects(); ++ objId ) { IObject* pObject = pConstructor->GetConstructedObject( objId ); if (pObject) { // if a singleton was newly constructed in earlier phase, pass true to init. pObject->Init( bSingletonConstructed[i] ); if( m_bTestSerialization && ( m_ConstructorsOld.size() <= i || m_ConstructorsOld[ i ] != constructorsNew[ i ] ) ) { //test serialize out for all new objects, we assume old objects are OK. SimpleSerializer tempSerializer; tempSerializer.SetIsLoading( false ); tempSerializer.Serialize( pObject ); } } } } m_ProtectedPhase = PHASE_DELETEOLD; //delete old objects which have been replaced for(auto pOldObject: old_objects) { pOldObject->_isRuntimeDelete = true; delete pOldObject; } }