Fix FOOTPRINT_PREVIEW_PANEL loader thread synchronization

This commit is contained in:
Chris Pavlina 2017-03-05 22:22:25 -05:00
parent 6f3ec438cb
commit 541b91fd15
2 changed files with 72 additions and 71 deletions

View File

@ -38,6 +38,7 @@ class KIWAY;
class IO_MGR; class IO_MGR;
class BOARD; class BOARD;
class wxStaticText; class wxStaticText;
class FP_LOADER_THREAD;
enum FOOTPRINT_STATUS { enum FOOTPRINT_STATUS {
FPS_NOT_FOUND = 0, FPS_NOT_FOUND = 0,
@ -47,6 +48,8 @@ enum FOOTPRINT_STATUS {
class FOOTPRINT_PREVIEW_PANEL : public PCB_DRAW_PANEL_GAL, public KIWAY_HOLDER class FOOTPRINT_PREVIEW_PANEL : public PCB_DRAW_PANEL_GAL, public KIWAY_HOLDER
{ {
friend class FP_LOADER_THREAD;
public: public:
@ -104,12 +107,9 @@ public:
protected: protected:
class LOADER_THREAD : public wxThread class IFACE
{ {
public: public:
LOADER_THREAD ( FOOTPRINT_PREVIEW_PANEL *aParent );
~LOADER_THREAD ();
/** /**
* Threadsafe accessor to retrieve an entry from the cache. * Threadsafe accessor to retrieve an entry from the cache.
*/ */
@ -121,10 +121,6 @@ protected:
*/ */
CACHE_ENTRY AddToQueue( LIB_ID const & aEntry ); CACHE_ENTRY AddToQueue( LIB_ID const & aEntry );
protected:
void* Entry() override;
FOOTPRINT_PREVIEW_PANEL *m_parent;
/** /**
* Threadsafe accessor to pop from the loader queue. Returns a * Threadsafe accessor to pop from the loader queue. Returns a
* cache entry or an empty option if there is none. * cache entry or an empty option if there is none.
@ -144,9 +140,9 @@ protected:
std::deque<CACHE_ENTRY> m_loaderQueue; std::deque<CACHE_ENTRY> m_loaderQueue;
std::map<LIB_ID, CACHE_ENTRY> m_cachedFootprints; std::map<LIB_ID, CACHE_ENTRY> m_cachedFootprints;
wxMutex m_loaderLock; wxMutex m_loaderLock;
}; };
FOOTPRINT_PREVIEW_PANEL( FOOTPRINT_PREVIEW_PANEL(
KIWAY* aKiway, wxWindow* aParent, KIWAY* aKiway, wxWindow* aParent,
KIGFX::GAL_DISPLAY_OPTIONS& aOpts, GAL_TYPE aGalType ); KIGFX::GAL_DISPLAY_OPTIONS& aOpts, GAL_TYPE aGalType );
@ -157,7 +153,8 @@ private:
void renderFootprint( MODULE *module ); void renderFootprint( MODULE *module );
std::unique_ptr<LOADER_THREAD> m_loader; FP_LOADER_THREAD* m_loader;
std::shared_ptr<IFACE> m_iface;
std::unique_ptr<BOARD> m_dummyBoard; std::unique_ptr<BOARD> m_dummyBoard;

View File

@ -36,22 +36,72 @@
#include <wx/stattext.h> #include <wx/stattext.h>
FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::LOADER_THREAD ( FOOTPRINT_PREVIEW_PANEL* aParent ) : class FP_LOADER_THREAD: public wxThread
wxThread ( wxTHREAD_JOINABLE ),
m_parent( aParent )
{ {
FOOTPRINT_PREVIEW_PANEL* m_parent;
std::shared_ptr<FOOTPRINT_PREVIEW_PANEL::IFACE> m_iface;
} public:
FP_LOADER_THREAD( FOOTPRINT_PREVIEW_PANEL* aParent,
std::shared_ptr<FOOTPRINT_PREVIEW_PANEL::IFACE> const& aIface ):
wxThread( wxTHREAD_DETACHED ),
m_parent( aParent ),
m_iface( aIface )
{}
~FP_LOADER_THREAD()
{}
virtual void* Entry() override
{
while(!TestDestroy())
{
auto ent = m_iface->PopFromQueue();
if( ent )
{
FP_LIB_TABLE* fptbl = m_parent->Prj().PcbFootprintLibs();
if(!fptbl)
continue;
ent->module = NULL;
try {
ent->module = fptbl->FootprintLoadWithOptionalNickname( ent->fpid );
if(ent->module == NULL)
ent->status = FPS_NOT_FOUND;
} catch( const IO_ERROR& ioe )
{
ent->status = FPS_NOT_FOUND;
}
FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::~LOADER_THREAD () if(ent->status != FPS_NOT_FOUND )
{ ent->status = FPS_READY;
} m_iface->AddToCache( *ent );
if( ent->fpid == m_parent->m_currentFPID )
{
wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, 1 );
m_parent->GetEventHandler()->AddPendingEvent ( event );
}
} else {
wxMilliSleep(100);
}
}
return NULL;
}
};
boost::optional<FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY> boost::optional<FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY>
FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::PopFromQueue() FOOTPRINT_PREVIEW_PANEL::IFACE::PopFromQueue()
{ {
wxMutexLocker lock( m_loaderLock ); wxMutexLocker lock( m_loaderLock );
@ -69,7 +119,7 @@ FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::PopFromQueue()
FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY
FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::AddToQueue( LIB_ID const & aEntry ) FOOTPRINT_PREVIEW_PANEL::IFACE::AddToQueue( LIB_ID const & aEntry )
{ {
wxMutexLocker lock( m_loaderLock ); wxMutexLocker lock( m_loaderLock );
@ -81,7 +131,7 @@ FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::AddToQueue( LIB_ID const & aEntry )
} }
void FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::AddToCache( void FOOTPRINT_PREVIEW_PANEL::IFACE::AddToCache(
FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY const & aEntry ) FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY const & aEntry )
{ {
wxMutexLocker lock( m_loaderLock ); wxMutexLocker lock( m_loaderLock );
@ -91,7 +141,7 @@ void FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::AddToCache(
boost::optional<FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY> boost::optional<FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY>
FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::GetFromCache( LIB_ID const & aFPID ) FOOTPRINT_PREVIEW_PANEL::IFACE::GetFromCache( LIB_ID const & aFPID )
{ {
wxMutexLocker lock( m_loaderLock ); wxMutexLocker lock( m_loaderLock );
auto it = m_cachedFootprints.find( aFPID ); auto it = m_cachedFootprints.find( aFPID );
@ -103,53 +153,6 @@ FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::GetFromCache( LIB_ID const & aFPID )
} }
void* FOOTPRINT_PREVIEW_PANEL::LOADER_THREAD::Entry()
{
while(!TestDestroy())
{
auto ent = PopFromQueue();
if( ent )
{
FP_LIB_TABLE* fptbl = m_parent->Prj().PcbFootprintLibs();
if(!fptbl)
continue;
ent->module = NULL;
try {
ent->module = fptbl->FootprintLoadWithOptionalNickname( ent->fpid );
if(ent->module == NULL)
ent->status = FPS_NOT_FOUND;
} catch( const IO_ERROR& ioe )
{
ent->status = FPS_NOT_FOUND;
}
if(ent->status != FPS_NOT_FOUND )
ent->status = FPS_READY;
AddToCache( *ent );
if( ent->fpid == m_parent->m_currentFPID )
{
wxCommandEvent event( wxEVT_COMMAND_TEXT_UPDATED, 1 );
m_parent->GetEventHandler()->AddPendingEvent ( event );
}
} else {
wxMilliSleep(100);
}
}
return NULL;
}
FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL( FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL(
KIWAY* aKiway, wxWindow* aParent, KIGFX::GAL_DISPLAY_OPTIONS& aOpts, GAL_TYPE aGalType ) KIWAY* aKiway, wxWindow* aParent, KIGFX::GAL_DISPLAY_OPTIONS& aOpts, GAL_TYPE aGalType )
: PCB_DRAW_PANEL_GAL ( aParent, -1, wxPoint( 0, 0 ), wxSize(200, 200), aOpts, aGalType ), : PCB_DRAW_PANEL_GAL ( aParent, -1, wxPoint( 0, 0 ), wxSize(200, 200), aOpts, aGalType ),
@ -159,7 +162,8 @@ FOOTPRINT_PREVIEW_PANEL::FOOTPRINT_PREVIEW_PANEL(
m_hidesizer( NULL ) m_hidesizer( NULL )
{ {
m_loader = std::make_unique<LOADER_THREAD>( this ); m_iface = std::make_shared<IFACE>();
m_loader = new FP_LOADER_THREAD( this, m_iface );
m_loader->Run(); m_loader->Run();
SetStealsFocus( false ); SetStealsFocus( false );
@ -189,12 +193,12 @@ FOOTPRINT_PREVIEW_PANEL::~FOOTPRINT_PREVIEW_PANEL( )
FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY FOOTPRINT_PREVIEW_PANEL::CACHE_ENTRY
FOOTPRINT_PREVIEW_PANEL::CacheFootprint ( const LIB_ID& aFPID ) FOOTPRINT_PREVIEW_PANEL::CacheFootprint ( const LIB_ID& aFPID )
{ {
auto opt_ent = m_loader->GetFromCache( aFPID ); auto opt_ent = m_iface->GetFromCache( aFPID );
if( opt_ent ) if( opt_ent )
return *opt_ent; return *opt_ent;
else else
return m_loader->AddToQueue( aFPID ); return m_iface->AddToQueue( aFPID );
} }