Implement shared FOOTPRINT_LIST.

While we already cache the loaded footprint files, parsing said files
into the list is also time-intensive.  Since the FOOTPRINT_LIST is
already hash-stamped against the current timestamps of the files that
make up the list, sharing a single copy of the list is quite
straight-forward.
This commit is contained in:
Jeff Young 2018-03-25 13:48:13 +01:00
parent b24b0d5dfe
commit f4ce8766e3
12 changed files with 34 additions and 29 deletions

View File

@ -109,7 +109,7 @@ void FOOTPRINT_LIST::DisplayErrors( wxTopLevelWindow* aWindow )
} }
static std::unique_ptr<FOOTPRINT_LIST> get_instance_from_id( KIWAY& aKiway, int aId ) static FOOTPRINT_LIST* get_instance_from_id( KIWAY& aKiway, int aId )
{ {
void* ptr = nullptr; void* ptr = nullptr;
@ -130,11 +130,11 @@ static std::unique_ptr<FOOTPRINT_LIST> get_instance_from_id( KIWAY& aKiway, int
return nullptr; return nullptr;
} }
return std::unique_ptr<FOOTPRINT_LIST>( (FOOTPRINT_LIST*) ( ptr ) ); return static_cast<FOOTPRINT_LIST*>( ptr );
} }
std::unique_ptr<FOOTPRINT_LIST> FOOTPRINT_LIST::GetInstance( KIWAY& aKiway ) FOOTPRINT_LIST* FOOTPRINT_LIST::GetInstance( KIWAY& aKiway )
{ {
return get_instance_from_id( aKiway, KIFACE_NEW_FOOTPRINT_LIST ); return get_instance_from_id( aKiway, KIFACE_NEW_FOOTPRINT_LIST );
} }

View File

@ -245,7 +245,6 @@ long long FP_LIB_TABLE::GenerateTimestamp( const wxString* aNickname )
} }
long long hash = 0; long long hash = 0;
for( wxString const& nickname : GetLogicalLibs() ) for( wxString const& nickname : GetLogicalLibs() )
{ {
const FP_LIB_TABLE_ROW* row = FindRow( nickname ); const FP_LIB_TABLE_ROW* row = FindRow( nickname );

View File

@ -61,7 +61,7 @@ wxDEFINE_EVENT( EVT_FOOTPRINT_SELECTED, wxCommandEvent );
FOOTPRINT_SELECT_WIDGET::FOOTPRINT_SELECT_WIDGET( wxWindow* aParent, FOOTPRINT_SELECT_WIDGET::FOOTPRINT_SELECT_WIDGET( wxWindow* aParent,
FOOTPRINT_ASYNC_LOADER& aLoader, std::unique_ptr<FOOTPRINT_LIST>& aFpList, bool aUpdate, FOOTPRINT_LIST* aFpList, bool aUpdate,
int aMaxItems ) int aMaxItems )
: wxPanel( aParent ), : wxPanel( aParent ),
m_kiway( nullptr ), m_kiway( nullptr ),
@ -69,7 +69,6 @@ FOOTPRINT_SELECT_WIDGET::FOOTPRINT_SELECT_WIDGET( wxWindow* aParent,
m_finished_loading( false ), m_finished_loading( false ),
m_max_items( aMaxItems ), m_max_items( aMaxItems ),
m_last_item( 0 ), m_last_item( 0 ),
m_fp_loader( aLoader ),
m_fp_list( aFpList ) m_fp_list( aFpList )
{ {
m_zero_filter = true; m_zero_filter = true;

View File

@ -73,7 +73,8 @@ class CVPCB_MAINFRAME : public KIWAY_PLAYER
public: public:
wxArrayString m_ModuleLibNames; wxArrayString m_ModuleLibNames;
wxArrayString m_EquFilesNames; wxArrayString m_EquFilesNames;
std::unique_ptr<FOOTPRINT_LIST> m_FootprintsList;
FOOTPRINT_LIST* m_FootprintsList;
protected: protected:
int m_undefinedComponentCnt; int m_undefinedComponentCnt;

View File

@ -45,9 +45,6 @@
#include <widgets/footprint_select_widget.h> #include <widgets/footprint_select_widget.h>
FOOTPRINT_ASYNC_LOADER DIALOG_CHOOSE_COMPONENT::m_fp_loader;
std::unique_ptr<FOOTPRINT_LIST> DIALOG_CHOOSE_COMPONENT::m_fp_list;
wxSize DIALOG_CHOOSE_COMPONENT::m_last_dlg_size( -1, -1 ); wxSize DIALOG_CHOOSE_COMPONENT::m_last_dlg_size( -1, -1 );
int DIALOG_CHOOSE_COMPONENT::m_tree_canvas_sash_position = 0; int DIALOG_CHOOSE_COMPONENT::m_tree_canvas_sash_position = 0;
@ -66,6 +63,8 @@ DIALOG_CHOOSE_COMPONENT::DIALOG_CHOOSE_COMPONENT( SCH_BASE_FRAME* aParent, const
{ {
wxBusyCursor busy_while_loading; wxBusyCursor busy_while_loading;
m_fp_list = FOOTPRINT_LIST::GetInstance( Kiway() );
auto sizer = new wxBoxSizer( wxVERTICAL ); auto sizer = new wxBoxSizer( wxVERTICAL );
// Use a slightly different layout, with a details pane spanning the entire window, // Use a slightly different layout, with a details pane spanning the entire window,
@ -161,7 +160,7 @@ wxPanel* DIALOG_CHOOSE_COMPONENT::ConstructRightPanel( wxWindow* aParent )
if( m_show_footprints ) if( m_show_footprints )
{ {
if( m_allow_field_edits ) if( m_allow_field_edits )
m_fp_sel_ctrl = new FOOTPRINT_SELECT_WIDGET( panel, m_fp_loader, m_fp_list, true ); m_fp_sel_ctrl = new FOOTPRINT_SELECT_WIDGET( panel, m_fp_list, true );
m_fp_view_ctrl = new FOOTPRINT_PREVIEW_WIDGET( panel, Kiway() ); m_fp_view_ctrl = new FOOTPRINT_PREVIEW_WIDGET( panel, Kiway() );

View File

@ -208,9 +208,8 @@ protected:
bool m_external_browser_requested; bool m_external_browser_requested;
wxString m_fp_override; wxString m_fp_override;
static FOOTPRINT_ASYNC_LOADER m_fp_loader; FOOTPRINT_LIST* m_fp_list;
static std::unique_ptr<FOOTPRINT_LIST> m_fp_list; std::vector<std::pair<int, wxString>> m_field_edits;
std::vector<std::pair<int, wxString>> m_field_edits;
// Remember the dialog size during a session // Remember the dialog size during a session
static wxSize m_last_dlg_size; static wxSize m_last_dlg_size;

View File

@ -265,12 +265,12 @@ public:
} }
/** /**
* Factory function to return a new FOOTPRINT_LIST via Kiway. NOT guaranteed * Factory function to return a FOOTPRINT_LIST via Kiway. NOT guaranteed
* to succeed; will return null if the kiface is not available. * to succeed; will return null if the kiface is not available.
* *
* @param aKiway - active kiway instance * @param aKiway - active kiway instance
*/ */
static std::unique_ptr<FOOTPRINT_LIST> GetInstance( KIWAY& aKiway ); static FOOTPRINT_LIST* GetInstance( KIWAY& aKiway );
protected: protected:
/** /**

View File

@ -59,14 +59,13 @@ public:
* loaded more than once. * loaded more than once.
* *
* @param aParent - parent window * @param aParent - parent window
* @param aLoader - FOOTPRINT_ASYNC_LOADER instance
* @param aFpList - FOOTPRINT_LIST container * @param aFpList - FOOTPRINT_LIST container
* @param aUpdate - whether to call UpdateList() automatically when finished loading * @param aUpdate - whether to call UpdateList() automatically when finished loading
* @param aMaxItems - maximum number of filter items to display, in addition to * @param aMaxItems - maximum number of filter items to display, in addition to
* Default and Other * Default and Other
*/ */
FOOTPRINT_SELECT_WIDGET( wxWindow* aParent, FOOTPRINT_ASYNC_LOADER& aLoader, FOOTPRINT_SELECT_WIDGET( wxWindow* aParent, FOOTPRINT_LIST* aFpList,
std::unique_ptr<FOOTPRINT_LIST>& aFpList, bool aUpdate = true, int aMaxItems = 400 ); bool aUpdate = true, int aMaxItems = 400 );
virtual ~FOOTPRINT_SELECT_WIDGET() virtual ~FOOTPRINT_SELECT_WIDGET()
{ {
@ -145,10 +144,10 @@ private:
wxString m_other_footprint; wxString m_other_footprint;
int m_last_item; int m_last_item;
FOOTPRINT_ASYNC_LOADER& m_fp_loader; FOOTPRINT_ASYNC_LOADER m_fp_loader;
std::unique_ptr<FOOTPRINT_LIST>& m_fp_list; FOOTPRINT_LIST* m_fp_list;
FOOTPRINT_FILTER m_fp_filter; FOOTPRINT_FILTER m_fp_filter;
bool m_zero_filter; bool m_zero_filter;
void OnProgressTimer( wxTimerEvent& aEvent ); void OnProgressTimer( wxTimerEvent& aEvent );
void OnComboBox( wxCommandEvent& aEvent ); void OnComboBox( wxCommandEvent& aEvent );

View File

@ -118,8 +118,7 @@ void FOOTPRINT_LIST_IMPL::loader_job()
bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname, bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname,
WX_PROGRESS_REPORTER* aProgressReporter ) WX_PROGRESS_REPORTER* aProgressReporter )
{ {
long long libraryTimestamp = aTable->GenerateTimestamp( aNickname ); if( m_list_timestamp == aTable->GenerateTimestamp( aNickname ) )
if( m_list_timestamp == libraryTimestamp )
return true; return true;
m_progress_reporter = aProgressReporter; m_progress_reporter = aProgressReporter;
@ -167,7 +166,7 @@ bool FOOTPRINT_LIST_IMPL::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxStri
( _( "Loading incomplete; cancelled by user." ), nullptr, nullptr, 0 ) ); ( _( "Loading incomplete; cancelled by user." ), nullptr, nullptr, 0 ) );
} }
m_list_timestamp = libraryTimestamp; m_list_timestamp = aTable->GenerateTimestamp( aNickname );;
m_progress_reporter = nullptr; m_progress_reporter = nullptr;
return m_errors.empty(); return m_errors.empty();

View File

@ -93,4 +93,7 @@ public:
WX_PROGRESS_REPORTER* aProgressReporter = nullptr ) override; WX_PROGRESS_REPORTER* aProgressReporter = nullptr ) override;
}; };
extern FOOTPRINT_LIST_IMPL GFootprintList; // KIFACE scope.
#endif // FOOTPRINT_INFO_IMPL_H #endif // FOOTPRINT_INFO_IMPL_H

View File

@ -405,7 +405,7 @@ void FOOTPRINT_VIEWER_FRAME::ReCreateFootprintList()
return; return;
} }
auto fp_info_list( FOOTPRINT_LIST::GetInstance( Kiway() ) ); auto fp_info_list = FOOTPRINT_LIST::GetInstance( Kiway() );
wxString nickname = getCurNickname(); wxString nickname = getCurNickname();

View File

@ -89,6 +89,7 @@ wxString g_DocModulesFileName = wxT( "footprints_doc/footprints.pdf" );
DLIST<TRACK> g_CurrentTrackList; DLIST<TRACK> g_CurrentTrackList;
namespace PCB { namespace PCB {
static struct IFACE : public KIFACE_I static struct IFACE : public KIFACE_I
@ -167,7 +168,7 @@ static struct IFACE : public KIFACE_I
switch( aDataId ) switch( aDataId )
{ {
case KIFACE_NEW_FOOTPRINT_LIST: case KIFACE_NEW_FOOTPRINT_LIST:
return (void*) static_cast<FOOTPRINT_LIST*>( new FOOTPRINT_LIST_IMPL() ); return (void*) &GFootprintList;
case KIFACE_G_FOOTPRINT_TABLE: case KIFACE_G_FOOTPRINT_TABLE:
return (void*) new FP_LIB_TABLE( &GFootprintTable ); return (void*) new FP_LIB_TABLE( &GFootprintTable );
@ -309,7 +310,13 @@ void PythonPluginsReloadBase()
/// The global footprint library table. This is not dynamically allocated because /// The global footprint library table. This is not dynamically allocated because
/// in a multiple project environment we must keep its address constant (since it is /// in a multiple project environment we must keep its address constant (since it is
/// the fallback table for multiple projects). /// the fallback table for multiple projects).
FP_LIB_TABLE GFootprintTable; FP_LIB_TABLE GFootprintTable;
/// The global footprint info table. This is performance-intensive to build so we
/// keep a hash-stamped global version. Any deviation from the request vs. stored
/// hash will result in it being rebuilt.
FOOTPRINT_LIST_IMPL GFootprintList;
bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits ) bool IFACE::OnKifaceStart( PGM_BASE* aProgram, int aCtlBits )