diff --git a/common/lib_table_base.cpp b/common/lib_table_base.cpp index c2bd8d650f..14b11b9115 100644 --- a/common/lib_table_base.cpp +++ b/common/lib_table_base.cpp @@ -193,6 +193,8 @@ LIB_TABLE_ROW* LIB_TABLE::findRow( const wxString& aNickName, bool aCheckIfEnabl { cur->ensureIndex(); + std::shared_lock lock( cur->m_nickIndexMutex ); + for( const std::pair& entry : cur->m_nickIndex ) { if( entry.first == aNickName ) @@ -303,7 +305,7 @@ bool LIB_TABLE::InsertRow( LIB_TABLE_ROW* aRow, bool doReplace ) { ensureIndex(); - std::lock_guard lock( m_nickIndexMutex ); + std::lock_guard lock( m_nickIndexMutex ); INDEX_CITER it = m_nickIndex.find( aRow->GetNickName() ); diff --git a/eeschema/dialogs/panel_sym_lib_table.cpp b/eeschema/dialogs/panel_sym_lib_table.cpp index 75344f5e51..29d525af2b 100644 --- a/eeschema/dialogs/panel_sym_lib_table.cpp +++ b/eeschema/dialogs/panel_sym_lib_table.cpp @@ -891,7 +891,7 @@ bool PANEL_SYM_LIB_TABLE::TransferDataFromWindow() m_globalTable->Clear(); m_globalTable->m_rows.transfer( m_globalTable->m_rows.end(), global_model()->m_rows.begin(), global_model()->m_rows.end(), global_model()->m_rows ); - m_globalTable->reindex(); + m_globalTable->reindex( true ); } if( project_model() && *project_model() != *m_projectTable ) @@ -901,7 +901,7 @@ bool PANEL_SYM_LIB_TABLE::TransferDataFromWindow() m_projectTable->Clear(); m_projectTable->m_rows.transfer( m_projectTable->m_rows.end(), project_model()->m_rows.begin(), project_model()->m_rows.end(), project_model()->m_rows ); - m_projectTable->reindex(); + m_projectTable->reindex( true ); } return true; diff --git a/include/lib_table_base.h b/include/lib_table_base.h index 04769543ea..41304a4a75 100644 --- a/include/lib_table_base.h +++ b/include/lib_table_base.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -329,7 +330,7 @@ public: /// Delete all rows. void Clear() { - std::lock_guard lock( m_nickIndexMutex ); + std::lock_guard lock( m_nickIndexMutex ); m_rows.clear(); m_nickIndex.clear(); @@ -454,7 +455,7 @@ public: if( *iter == *aRow ) { m_rows.erase( iter, iter + 1 ); - reindex(); + reindex( true ); return true; } } @@ -539,9 +540,21 @@ protected: */ bool migrate(); - void reindex() + /** + * Rebuilds the m_nickIndex + * + * @param aForce is to avoid rebuilding the index multiple times because multiple threads hit ensureIndex + * at the same time + */ + void reindex( bool aForce ) { - std::lock_guard lock( m_nickIndexMutex ); + std::lock_guard lock( m_nickIndexMutex ); + + if( !aForce ) + { + if( m_nickIndex.size() ) + return; + } m_nickIndex.clear(); @@ -555,7 +568,7 @@ protected: // Lazy indexing may be required. To handle lazy indexing, we must enforce // that "nickIndex" is either empty or accurate, but never inaccurate. if( !m_nickIndex.size() ) - reindex(); + reindex( false ); } private: @@ -580,7 +593,7 @@ protected: mutable int m_version; /// Mutex to protect access to the nickIndex variable - mutable std::mutex m_nickIndexMutex; + mutable std::shared_mutex m_nickIndexMutex; }; #endif // _LIB_TABLE_BASE_H_ diff --git a/pcbnew/dialogs/panel_fp_lib_table.cpp b/pcbnew/dialogs/panel_fp_lib_table.cpp index f19bb0be12..bcacb544cb 100644 --- a/pcbnew/dialogs/panel_fp_lib_table.cpp +++ b/pcbnew/dialogs/panel_fp_lib_table.cpp @@ -989,7 +989,7 @@ bool PANEL_FP_LIB_TABLE::TransferDataFromWindow() m_global->Clear(); m_global->m_rows.transfer( m_global->m_rows.end(), global_model()->m_rows.begin(), global_model()->m_rows.end(), global_model()->m_rows ); - m_global->reindex(); + m_global->reindex( true ); } if( project_model() && *project_model() != *m_project ) @@ -999,7 +999,7 @@ bool PANEL_FP_LIB_TABLE::TransferDataFromWindow() m_project->Clear(); m_project->m_rows.transfer( m_project->m_rows.end(), project_model()->m_rows.begin(), project_model()->m_rows.end(), project_model()->m_rows ); - m_project->reindex(); + m_project->reindex( true ); } return true;