Add threaded library load to symbol editor

This commit is contained in:
Jon Evans 2021-03-19 20:23:54 -04:00
parent cc9787e47a
commit 82a4cacb4f
6 changed files with 83 additions and 18 deletions

View File

@ -22,21 +22,21 @@
#include <symbol_async_loader.h>
#include <symbol_lib_table.h>
#include <symbol_tree_model_adapter.h>
#include <widgets/progress_reporter.h>
SYMBOL_ASYNC_LOADER::SYMBOL_ASYNC_LOADER( const std::vector<wxString>& aNicknames,
SYMBOL_TREE_MODEL_ADAPTER* aAdapter,
std::unordered_map<wxString, std::vector<LIB_PART*>>& aOutput,
SYMBOL_LIB_TABLE* aTable, bool aOnlyPowerSymbols,
std::unordered_map<wxString, std::vector<LIB_PART*>>* aOutput,
PROGRESS_REPORTER* aReporter ) :
m_nicknames( aNicknames ),
m_adapter( aAdapter ),
m_table( aTable ),
m_onlyPowerSymbols( aOnlyPowerSymbols ),
m_output( aOutput ),
m_reporter( aReporter )
{
m_onlyPowerSymbols = ( m_adapter->GetFilter() == LIB_TREE_MODEL_ADAPTER::CMP_FILTER_POWER );
m_threadCount = std::max<size_t>( 1, std::thread::hardware_concurrency() - 1 );
wxASSERT( m_table );
m_threadCount = std::max<size_t>( 1, std::thread::hardware_concurrency() - 1 );
m_canceled.store( false );
m_nextLibrary.store( 0 );
@ -69,10 +69,10 @@ bool SYMBOL_ASYNC_LOADER::Join()
const std::vector<LOADED_PAIR>& ret = m_returns[ii].get();
if( !ret.empty() )
if( m_output && !ret.empty() )
{
for( const LOADED_PAIR& pair : ret )
m_output[pair.first] = pair.second;
m_output->insert( pair );
}
}
@ -110,7 +110,7 @@ std::vector<SYMBOL_ASYNC_LOADER::LOADED_PAIR> SYMBOL_ASYNC_LOADER::worker()
try
{
m_adapter->m_libs->LoadSymbolLib( pair.second, nickname, onlyPower );
m_table->LoadSymbolLib( pair.second, nickname, onlyPower );
ret.emplace_back( std::move( pair ) );
}
catch( const IO_ERROR& ioe )

View File

@ -24,12 +24,14 @@
#include <atomic>
#include <future>
#include <mutex>
#include <unordered_map>
#include <vector>
#include <symbol_tree_model_adapter.h>
#include <wx/string.h>
class LIB_PART;
class PROGRESS_REPORTER;
class SYMBOL_LIB_TABLE;
class SYMBOL_ASYNC_LOADER
@ -38,13 +40,14 @@ public:
/**
* Constructs a loader for symbol libraries
* @param aNicknames is a list of library nicknames to load
* @param aAdapter is a pointer to the parent symbol tree model adapter
* @param aTable is a pointer to the symbol library table to load libraries for
* @param aOnlyPowerSymbols, if true, will only return power symbols in the output map
* @param aOutput will be filled with the loaded parts
* @param aReporter will be used to repord progress, of not null
*/
SYMBOL_ASYNC_LOADER( const std::vector<wxString>& aNicknames,
SYMBOL_TREE_MODEL_ADAPTER* aAdapter,
std::unordered_map<wxString, std::vector<LIB_PART*>>& aOutput,
SYMBOL_LIB_TABLE* aTable, bool aOnlyPowerSymbols = false,
std::unordered_map<wxString, std::vector<LIB_PART*>>* aOutput = nullptr,
PROGRESS_REPORTER* aReporter = nullptr );
~SYMBOL_ASYNC_LOADER();
@ -80,14 +83,14 @@ private:
///< list of libraries to load
std::vector<wxString> m_nicknames;
///< Handle to the adapter that owns this loader
SYMBOL_TREE_MODEL_ADAPTER* m_adapter;
///< Handle to the symbol library table being loaded into
SYMBOL_LIB_TABLE* m_table;
///< True if we are loading only power symbols
bool m_onlyPowerSymbols;
///< Handle to map that will be filled with the loaded parts per library
std::unordered_map<wxString, std::vector<LIB_PART*>>& m_output;
std::unordered_map<wxString, std::vector<LIB_PART*>>* m_output;
///< Progress reporter (may be null)
PROGRESS_REPORTER* m_reporter;

View File

@ -67,6 +67,7 @@
#include <widgets/app_progress_dialog.h>
#include <widgets/infobar.h>
#include <widgets/lib_tree.h>
#include <widgets/progress_reporter.h>
#include <widgets/symbol_tree_pane.h>
#include <wildcards_and_files_ext.h>
#include <panel_sym_lib_table.h>
@ -140,7 +141,13 @@ SYMBOL_EDIT_FRAME::SYMBOL_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
setupUIConditions();
m_libMgr = new SYMBOL_LIBRARY_MANAGER( *this );
SyncLibraries( true );
// Preload libraries before using SyncLibraries the first time, as the preload is threaded
WX_PROGRESS_REPORTER reporter( this, _( "Loading Symbol Libraries" ),
m_libMgr->GetLibraryCount(), true );
m_libMgr->Preload( reporter );
SyncLibraries( false );
m_treePane = new SYMBOL_TREE_PANE( this, m_libMgr );
ReCreateMenuBar();

View File

@ -33,7 +33,10 @@
#include <sch_io_mgr.h>
#include <sch_plugins/legacy/sch_legacy_plugin.h>
#include <symbol_lib_table.h>
#include <symbol_async_loader.h>
#include <widgets/progress_reporter.h>
#include <list>
#include <locale_io.h>
SYMBOL_LIBRARY_MANAGER::SYMBOL_LIBRARY_MANAGER( SYMBOL_EDIT_FRAME& aFrame ) :
@ -58,6 +61,40 @@ void SYMBOL_LIBRARY_MANAGER::Sync( const wxString& aForceRefresh,
}
void SYMBOL_LIBRARY_MANAGER::Preload( PROGRESS_REPORTER& aReporter )
{
const int progressIntervalMillis = 60;
SYMBOL_ASYNC_LOADER loader( symTable()->GetLogicalLibs(), symTable(), false, nullptr,
&aReporter );
LOCALE_IO toggle;
loader.Start();
while( !loader.Done() )
{
aReporter.KeepRefreshing();
wxMilliSleep( progressIntervalMillis );
}
if( aReporter.IsCancelled() )
{
loader.Abort();
}
else
{
loader.Join();
}
if( !loader.GetErrors().IsEmpty() )
{
wxLogError( loader.GetErrors() );
}
}
bool SYMBOL_LIBRARY_MANAGER::HasModifications() const
{
for( const auto& lib : m_libs )
@ -638,6 +675,12 @@ bool SYMBOL_LIBRARY_MANAGER:: HasDerivedSymbols( const wxString& aSymbolName,
}
size_t SYMBOL_LIBRARY_MANAGER::GetLibraryCount() const
{
return symTable()->GetLogicalLibs().size();
}
wxString SYMBOL_LIBRARY_MANAGER::getLibraryName( const wxString& aFilePath )
{
wxFileName fn( aFilePath );

View File

@ -39,6 +39,7 @@
class LIB_PART;
class PART_LIB;
class PROGRESS_REPORTER;
class SCH_PLUGIN;
class SYMBOL_EDIT_FRAME;
class SYMBOL_LIB_TABLE;
@ -108,6 +109,13 @@ public:
void Sync( const wxString& aForceRefresh,
std::function<void( int, int, const wxString& )> aProgressCallback );
/**
* Preloads all symbol libraries in the symbol library table using SYMBOL_ASYNC_LOADER.
* Call before the first call to Sync() to get better performance.
* @param aReporter is used to report progress of the load
*/
void Preload( PROGRESS_REPORTER& aReporter );
int GetHash() const;
bool HasModifications() const;
@ -292,6 +300,8 @@ public:
*/
bool HasDerivedSymbols( const wxString& aSymbolName, const wxString& aLibraryName );
size_t GetLibraryCount() const;
private:
///< Extract library name basing on the file name.
static wxString getLibraryName( const wxString& aFilePath );

View File

@ -71,7 +71,9 @@ void SYMBOL_TREE_MODEL_ADAPTER::AddLibraries( const std::vector<wxString>& aNick
std::unordered_map<wxString, std::vector<LIB_PART*>> loadedSymbols;
SYMBOL_ASYNC_LOADER loader( aNicknames, this, loadedSymbols, prg.get() );
SYMBOL_ASYNC_LOADER loader( aNicknames, m_libs,
GetFilter() == LIB_TREE_MODEL_ADAPTER::CMP_FILTER_POWER,
&loadedSymbols, prg.get() );
LOCALE_IO toggle;