Kiway: Improve performance by using IDs and clearing closed frame entries

This commit is contained in:
david-beinder 2021-07-02 21:07:26 +02:00 committed by Jon Evans
parent a5308e5f5c
commit f33ea6f997
2 changed files with 27 additions and 17 deletions

View File

@ -52,15 +52,14 @@ KIWAY::KIWAY( PGM_BASE* aProgram, int aCtlBits, wxFrame* aTop ):
{ {
SetTop( aTop ); // hook player_destroy_handler() into aTop. SetTop( aTop ); // hook player_destroy_handler() into aTop.
// Set the array of all known frame window IDs to empty = wxID_NONE,
// Prepare the room to store the frame names, once they will be created // once they are be created, they are added with FRAME_T as index to this array.
// with FRAME_T type as index in this table. // Note: A non empty entry does not mean the frame still exists.
// (note this is a list of frame names, but a non empty entry // It means only the frame was created at least once. It can be destroyed after.
// does not mean the frame still exists. It means only the frame was created // These entries are not cleared automatically on window closing. The purpose is just
// at least once. It can be destroyed after. These entries are not cleared. // to allow a call to wxWindow::FindWindowById() using a FRAME_T frame type
// the purpose is just to allow a call to wxWindow::FindWindowByName(), from for( int n = 0; n < KIWAY_PLAYER_COUNT; n++ )
// a FRAME_T frame type m_playerFrameId[n] = wxID_NONE;
m_playerFrameName.Add( wxEmptyString, KIWAY_PLAYER_COUNT );
} }
@ -361,10 +360,19 @@ KIWAY::FACE_T KIWAY::KifaceType( FRAME_T aFrameType )
KIWAY_PLAYER* KIWAY::GetPlayerFrame( FRAME_T aFrameType ) KIWAY_PLAYER* KIWAY::GetPlayerFrame( FRAME_T aFrameType )
{ {
if( m_playerFrameName[aFrameType].IsEmpty() ) wxWindowID storedId = m_playerFrameId[aFrameType];
if( storedId == wxID_NONE )
return NULL; return NULL;
return static_cast<KIWAY_PLAYER*>( wxWindow::FindWindowByName( m_playerFrameName[aFrameType] ) ); wxWindow* frame = wxWindow::FindWindowById( storedId );
// Since wxWindow::FindWindow*() is not cheap (especially if the window does not exist),
// clear invalid entries to save CPU on repeated calls that do not lead to frame creation
if( !frame )
m_playerFrameId[aFrameType].compare_exchange_strong( storedId, wxID_NONE );
return static_cast<KIWAY_PLAYER*>( frame );
} }
@ -403,7 +411,7 @@ KIWAY_PLAYER* KIWAY::Player( FRAME_T aFrameType, bool doCreate, wxTopLevelWindow
// were passed to KIFACE::OnKifaceStart() // were passed to KIFACE::OnKifaceStart()
); );
m_playerFrameName[aFrameType] = frame->GetName(); m_playerFrameId[aFrameType].store( frame->GetId() );
return frame; return frame;
} }
catch( const IO_ERROR& ioe ) catch( const IO_ERROR& ioe )

View File

@ -95,6 +95,8 @@
*/ */
#include <atomic>
#include <wx/defs.h>
#include <wx/event.h> #include <wx/event.h>
#include <import_export.h> #include <import_export.h>
#include <search_stack.h> #include <search_stack.h>
@ -424,13 +426,13 @@ private:
wxFrame* m_top; // Usually m_top is the Project manager wxFrame* m_top; // Usually m_top is the Project manager
// a string array ( size KIWAY_PLAYER_COUNT ) to Store the frame name // An array to store the window ID of PLAYER frames which were run.
// of PLAYER frames which were run.
// A non empty name means only a PLAYER was run at least one time. // A non empty name means only a PLAYER was run at least one time.
// It can be closed. Call : // Empty entries are represented by wxID_NONE.
// wxWindow::FindWindowByName( m_playerFrameName[aFrameType] ) // They can be closed, and the stored window ID may be invalid.
// Call: wxWindow::FindWindowById( m_playerFrameId[aFrameType] )
// to know if still exists (or GetPlayerFrame( FRAME_T aFrameType ) // to know if still exists (or GetPlayerFrame( FRAME_T aFrameType )
wxArrayString m_playerFrameName; std::atomic<wxWindowID> m_playerFrameId[KIWAY_PLAYER_COUNT];
}; };