tdf#117066 Saving ODT document with ~1500 bookmarks is slow, part 4

Individually, these don't make much difference, but they add up
to a halving the time to save on my machine.

fileaccess::TaskManager was spending lots of time iterating over it's
internal data, so flatten the structures here, to avoid cache-unfriendly
pointer chasing.

Change-Id: Ic1e2e3958d10f3266aad5ddbcbd68ef1c7285dc7
Reviewed-on: https://gerrit.libreoffice.org/70312
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/ucb/source/ucp/file/filprp.cxx b/ucb/source/ucp/file/filprp.cxx
index e0c6f55..4226832 100644
--- a/ucb/source/ucp/file/filprp.cxx
+++ b/ucb/source/ucp/file/filprp.cxx
@@ -44,7 +44,7 @@

    TaskManager::ContentMap::iterator it = m_pMyShell->m_aContent.find( aUnqPath );

    TaskManager::PropertySet& properties = *(it->second.properties);
    TaskManager::PropertySet& properties = it->second.properties;

    m_seq.realloc( properties.size() );

diff --git a/ucb/source/ucp/file/filtask.cxx b/ucb/source/ucp/file/filtask.cxx
index b55b76c..941c6d3 100644
--- a/ucb/source/ucp/file/filtask.cxx
+++ b/ucb/source/ucp/file/filtask.cxx
@@ -492,10 +492,7 @@
    ContentMap::iterator it =
        m_aContent.emplace( aUnqPath, UnqPathData() ).first;

    if( ! it->second.notifier )
        it->second.notifier.reset( new NotifierList );

    std::vector< Notifier* >& nlist = *( it->second.notifier );
    std::vector< Notifier* >& nlist = it->second.notifier;

    std::vector<Notifier*>::iterator it1 = std::find(nlist.begin(), nlist.end(), pNotifier);
    if( it1 != nlist.end() )               // Every "Notifier" only once
@@ -515,9 +512,9 @@
    if( it == m_aContent.end() )
        return;

    it->second.notifier->erase(std::remove(it->second.notifier->begin(), it->second.notifier->end(), pNotifier), it->second.notifier->end());
    it->second.notifier.erase(std::remove(it->second.notifier.begin(), it->second.notifier.end(), pNotifier), it->second.notifier.end());

    if( it->second.notifier->empty() )
    if( it->second.notifier.empty() )
        m_aContent.erase( it );
}

@@ -559,7 +556,7 @@
        // Load the XPersistentPropertySetInfo and create it, if it does not exist
        load( it,true );

        PropertySet& properties = *(it->second.properties);
        PropertySet& properties = it->second.properties;
        it1 = properties.find( newProperty );
        if( it1 != properties.end() )
            throw beans::PropertyExistException(THROW_WHERE );
@@ -588,7 +585,7 @@

    load( it,false );

    PropertySet& properties = *(it->second.properties);
    PropertySet& properties = it->second.properties;

    it1 = properties.find( oldProperty );
    if( it1 == properties.end() )
@@ -851,7 +848,7 @@
    uno::Sequence< beans::PropertyChangeEvent > seqChanged( values.getLength() );

    TaskManager::ContentMap::iterator it = m_aContent.find( aUnqPath );
    PropertySet& properties = *( it->second.properties );
    PropertySet& properties = it->second.properties;
    TaskManager::PropertySet::iterator it1;
    uno::Any aAny;

@@ -1103,7 +1100,7 @@
        commit( it,aFileStatus );

        TaskManager::PropertySet::iterator it1;
        PropertySet& propset = *(it->second.properties);
        PropertySet& propset = it->second.properties;

        for( sal_Int32 i = 0; i < seq.getLength(); ++i )
        {
@@ -1941,7 +1938,7 @@

    MyProperty ContentTProperty( ContentType );

    PropertySet& properties = *(it->second.properties);
    PropertySet& properties = it->second.properties;
    bool ContentNotDefau = properties.find( ContentTProperty ) != properties.end();

    for (auto const& defaultprop : m_aDefaultProperties)
@@ -2197,9 +2194,6 @@
void
TaskManager::load( const ContentMap::iterator& it, bool create )
{
    if( ! it->second.properties )
        it->second.properties.reset( new PropertySet );

    if( ( ! it->second.xS.is() ||
          ! it->second.xC.is() ||
          ! it->second.xA.is() )
@@ -2218,7 +2212,7 @@

            // Now put in all values in the storage in the local hash;

            PropertySet& properties = *(it->second.properties);
            PropertySet& properties = it->second.properties;
            uno::Sequence< beans::Property > seq = xS->getPropertySetInfo()->getProperties();

            for( sal_Int32 i = 0; i < seq.getLength(); ++i )
@@ -2258,13 +2252,13 @@
{
    TaskManager::PropertySet::iterator it1;

    if( it->second.properties == nullptr )
    if( it->second.properties.empty() )
    {
        OUString aPath = it->first;
        insertDefaultProperties( aPath );
    }

    PropertySet& properties = *( it->second.properties );
    PropertySet& properties = it->second.properties;

    it1 = properties.find( MyProperty( Title ) );
    if( it1 != properties.end() )
@@ -2532,7 +2526,7 @@
        commit( it,aFileStatus );

        TaskManager::PropertySet::iterator it1;
        PropertySet& propset = *(it->second.properties);
        PropertySet& propset = it->second.properties;

        for( sal_Int32 i = 0; i < seq.getLength(); ++i )
        {
@@ -2562,9 +2556,9 @@
    {
        osl::MutexGuard aGuard( m_aMutex );
        TaskManager::ContentMap::iterator it = m_aContent.find( aName );
        if( it != m_aContent.end() && it->second.notifier )
        if( it != m_aContent.end() && !it->second.notifier.empty() )
        {
            std::vector<Notifier*>& listOfNotifiers = *( it->second.notifier );
            std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
            for (auto const& pointer : listOfNotifiers)
            {
                std::unique_ptr<ContentEventNotifier> notifier = pointer->cCEL();
@@ -2584,9 +2578,9 @@
    {
        osl::MutexGuard aGuard( m_aMutex );
        TaskManager::ContentMap::iterator it = m_aContent.find( aName );
        if( it != m_aContent.end() && it->second.notifier )
        if( it != m_aContent.end() && !it->second.notifier.empty() )
        {
            std::vector<Notifier*>& listOfNotifiers = *( it->second.notifier );
            std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
            for (auto const& pointer : listOfNotifiers)
            {
                std::unique_ptr<ContentEventNotifier> notifier = pointer->cDEL();
@@ -2633,9 +2627,9 @@
    {
        osl::MutexGuard aGuard( m_aMutex );
        TaskManager::ContentMap::iterator it = m_aContent.find( aName );
        if( it != m_aContent.end() && it->second.notifier )
        if( it != m_aContent.end() && !it->second.notifier.empty() )
        {
            std::vector<Notifier*>& listOfNotifiers = *( it->second.notifier );
            std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
            for (auto const& pointer : listOfNotifiers)
            {
                std::unique_ptr<PropertySetInfoChangeNotifier> notifier = pointer->cPSL();
@@ -2720,14 +2714,15 @@
                itnew->second.properties = std::move(itold->second.properties);

                // copy existing list
                std::unique_ptr<std::vector< Notifier* >> copyList = std::move(itnew->second.notifier);
                std::vector< Notifier* > copyList;
                std::swap(copyList, itnew->second.notifier);
                itnew->second.notifier = std::move(itold->second.notifier);

                m_aContent.erase( itold );

                if( itnew != m_aContent.end() && itnew->second.notifier )
                if( itnew != m_aContent.end() && !itnew->second.notifier.empty() )
                {
                    std::vector<Notifier*>& listOfNotifiers = *( itnew->second.notifier );
                    std::vector<Notifier*>& listOfNotifiers = itnew->second.notifier;
                    for (auto const& pointer : listOfNotifiers)
                    {
                        std::unique_ptr<ContentEventNotifier> notifier = pointer->cEXC( aNewName );
@@ -2738,13 +2733,8 @@

                // Merge with preexisting notifiers
                // However, these may be in status BaseContent::Deleted
                if( copyList != nullptr )
                {
                    for( const auto& rCopyPtr : *copyList )
                    {
                        itnew->second.notifier->push_back( rCopyPtr );
                    }
                }
                for( const auto& rCopyPtr : copyList )
                    itnew->second.notifier.push_back( rCopyPtr );
            }
        }
    }
@@ -2769,9 +2759,9 @@
    {
        osl::MutexGuard aGuard( m_aMutex );
        TaskManager::ContentMap::iterator it = m_aContent.find( aName );
        if( it != m_aContent.end() && it->second.notifier )
        if( it != m_aContent.end() && !it->second.notifier.empty() )
        {
            std::vector<Notifier*>& listOfNotifiers = *( it->second.notifier );
            std::vector<Notifier*>& listOfNotifiers = it->second.notifier;
            for (auto const& pointer : listOfNotifiers)
            {
                std::unique_ptr<PropertyChangeNotifier> notifier = pointer->cPCL();
@@ -2841,7 +2831,7 @@
                it->second.xC = nullptr;
                it->second.xA = nullptr;

                it->second.properties.reset();
                it->second.properties.clear();
            }
        }

diff --git a/ucb/source/ucp/file/filtask.hxx b/ucb/source/ucp/file/filtask.hxx
index 2c20b35..996aeba 100644
--- a/ucb/source/ucp/file/filtask.hxx
+++ b/ucb/source/ucp/file/filtask.hxx
@@ -226,8 +226,8 @@
            UnqPathData(UnqPathData&&);
            ~UnqPathData();

            std::unique_ptr<PropertySet> properties;
            std::unique_ptr<NotifierList> notifier;
            PropertySet properties;
            NotifierList notifier;

            // Three views on the PersistentPropertySet
            css::uno::Reference< css::ucb::XPersistentPropertySet >   xS;