wxgui: improve single-threaded plugin enumerator for Linux (still a bit buggy)

git-svn-id: http://pcsx2.googlecode.com/svn/branches/wxgui@1743 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2009-09-05 09:21:59 +00:00
parent 0fa673fdd2
commit 93e1d87a22
7 changed files with 546 additions and 518 deletions

View File

@ -50,6 +50,8 @@ namespace Threading
// your sister, and then cheating on her with your daughter. // your sister, and then cheating on her with your daughter.
PersistentThread::~PersistentThread() PersistentThread::~PersistentThread()
{ {
if( !m_running ) return;
wxASSERT( !IsSelf() ); // not allowed from our own thread. wxASSERT( !IsSelf() ); // not allowed from our own thread.
if( !_InterlockedExchange( &m_detached, true ) ) if( !_InterlockedExchange( &m_detached, true ) )
@ -62,9 +64,7 @@ namespace Threading
// This function should not be called from the owner thread. // This function should not be called from the owner thread.
void PersistentThread::Start() void PersistentThread::Start()
{ {
wxASSERT( !IsSelf() ); // not allowed from our own thread.
if( m_running ) return; if( m_running ) return;
if( pthread_create( &m_thread, NULL, _internal_callback, this ) != 0 ) if( pthread_create( &m_thread, NULL, _internal_callback, this ) != 0 )
throw Exception::ThreadCreationError(); throw Exception::ThreadCreationError();
@ -74,8 +74,10 @@ namespace Threading
// This function should not be called from the owner thread. // This function should not be called from the owner thread.
void PersistentThread::Detach() void PersistentThread::Detach()
{ {
wxASSERT( !IsSelf() ); // not allowed from our own thread. if( !m_running ) return;
if( _InterlockedExchange( &m_detached, true ) ) return; if( _InterlockedExchange( &m_detached, true ) ) return;
wxASSERT( !IsSelf() ); // not allowed from our own thread.
pthread_detach( m_thread ); pthread_detach( m_thread );
} }
@ -92,7 +94,6 @@ namespace Threading
// //
void PersistentThread::Cancel( bool isBlocking ) void PersistentThread::Cancel( bool isBlocking )
{ {
wxASSERT( !IsSelf() );
if( _InterlockedExchange( &m_detached, true ) ) if( _InterlockedExchange( &m_detached, true ) )
{ {
if( m_running ) if( m_running )
@ -100,6 +101,7 @@ namespace Threading
return; return;
} }
wxASSERT( !IsSelf() );
pthread_cancel( m_thread ); pthread_cancel( m_thread );
if( isBlocking ) if( isBlocking )
@ -120,8 +122,6 @@ namespace Threading
// //
sptr PersistentThread::Block() sptr PersistentThread::Block()
{ {
DevAssert( !IsSelf(), "Thread deadlock detected; Block() should never be called by the owner thread." );
if( _InterlockedExchange( &m_detached, true ) ) if( _InterlockedExchange( &m_detached, true ) )
{ {
// already detached: if we're still running then its an invalid operation // already detached: if we're still running then its an invalid operation
@ -132,6 +132,7 @@ namespace Threading
} }
else else
{ {
DevAssert( !IsSelf(), "Thread deadlock detected; Block() should never be called by the owner thread." );
pthread_join( m_thread, (void**)&m_returncode ); pthread_join( m_thread, (void**)&m_returncode );
return m_returncode; return m_returncode;
} }

View File

@ -134,8 +134,6 @@
<Unit filename="../CDVD/IsoFileFormats.h" /> <Unit filename="../CDVD/IsoFileFormats.h" />
<Unit filename="../CDVD/IsoFileTools.cpp" /> <Unit filename="../CDVD/IsoFileTools.cpp" />
<Unit filename="../CDVD/IsoFileTools.h" /> <Unit filename="../CDVD/IsoFileTools.h" />
<Unit filename="../CDVD/IsoFileTools.h.save" />
<Unit filename="../CDVD/Makefile.am" />
<Unit filename="../COP0.cpp" /> <Unit filename="../COP0.cpp" />
<Unit filename="../COP2.cpp" /> <Unit filename="../COP2.cpp" />
<Unit filename="../Cache.cpp" /> <Unit filename="../Cache.cpp" />
@ -155,11 +153,7 @@
<Unit filename="../DebugTools/DisVUops.h" /> <Unit filename="../DebugTools/DisVUops.h" />
<Unit filename="../Docs/ChangeLog.txt" /> <Unit filename="../Docs/ChangeLog.txt" />
<Unit filename="../Docs/License.txt" /> <Unit filename="../Docs/License.txt" />
<Unit filename="../Docs/PS2Edefs.txt" />
<Unit filename="../Docs/RemoteDebugging.txt" />
<Unit filename="../Docs/devblog.txt" /> <Unit filename="../Docs/devblog.txt" />
<Unit filename="../Docs/readme 0.9.4.txt" />
<Unit filename="../Docs/readme Playground.txt" />
<Unit filename="../Dump.cpp" /> <Unit filename="../Dump.cpp" />
<Unit filename="../Dump.h" /> <Unit filename="../Dump.h" />
<Unit filename="../Elfheader.cpp" /> <Unit filename="../Elfheader.cpp" />

View File

@ -22,12 +22,12 @@
#include <wx/stdpaths.h> #include <wx/stdpaths.h>
using namespace wxHelpers; using namespace wxHelpers;
using namespace Panels;
Dialogs::PickUserModeDialog::PickUserModeDialog( wxWindow* parent, int id ) : Dialogs::PickUserModeDialog::PickUserModeDialog( wxWindow* parent, int id ) :
wxDialogWithHelpers( parent, id, _("PCSX2 First Time configuration"), false ) wxDialogWithHelpers( parent, id, _("PCSX2 First Time configuration"), false )
, m_panel_usersel( new Panels::UsermodeSelectionPanel( *this, 620, false ) ) , m_panel_usersel( new UsermodeSelectionPanel( *this, 620, false ) )
, m_panel_langsel( new Panels::LanguageSelectionPanel( *this, 620 ) ) , m_panel_langsel( new LanguageSelectionPanel( *this, 620 ) )
{ {
wxBoxSizer& s_main = *new wxBoxSizer( wxVERTICAL ); wxBoxSizer& s_main = *new wxBoxSizer( wxVERTICAL );
@ -46,7 +46,7 @@ Dialogs::PickUserModeDialog::PickUserModeDialog( wxWindow* parent, int id ) :
void Dialogs::PickUserModeDialog::OnOk_Click( wxCommandEvent& evt ) void Dialogs::PickUserModeDialog::OnOk_Click( wxCommandEvent& evt )
{ {
if( Panels::g_ApplyState.ApplyAll(true) ) if( g_ApplyState.ApplyAll() )
{ {
Close(); Close();
evt.Skip(); evt.Skip();

View File

@ -406,6 +406,9 @@ namespace Panels
virtual ~EnumThread(); virtual ~EnumThread();
EnumThread( PluginSelectorPanel& master ); EnumThread( PluginSelectorPanel& master );
void Cancel(); void Cancel();
void DoNextPlugin( int evtidx );
protected:
sptr ExecuteTask(); sptr ExecuteTask();
}; };

View File

@ -26,7 +26,12 @@
#include <wx/dir.h> #include <wx/dir.h>
// Allows us to force-disable threading for debugging/troubleshooting // Allows us to force-disable threading for debugging/troubleshooting
static const bool DisableThreading = true; static const bool DisableThreading =
#ifdef __LINUX__
true; // linux appears to have threading issues with loadlibrary.
#else
false;
#endif
using namespace wxHelpers; using namespace wxHelpers;
using namespace Threading; using namespace Threading;
@ -287,12 +292,20 @@ void Panels::PluginSelectorPanel::Apply( AppConfig& conf )
void Panels::PluginSelectorPanel::CancelRefresh() void Panels::PluginSelectorPanel::CancelRefresh()
{ {
if (!DisableThreading) safe_delete( m_EnumeratorThread ); safe_delete( m_EnumeratorThread );
safe_delete( m_FileList ); safe_delete( m_FileList );
} }
void Panels::PluginSelectorPanel::DoRefresh() void Panels::PluginSelectorPanel::DoRefresh()
{ {
m_ComponentBoxes.Reset();
if( m_FileList == NULL )
{
wxCommandEvent evt;
OnEnumComplete( evt );
return;
}
// Disable all controls until enumeration is complete. // Disable all controls until enumeration is complete.
// Show status bar for plugin enumeration. // Show status bar for plugin enumeration.
@ -307,19 +320,13 @@ void Panels::PluginSelectorPanel::DoRefresh()
m_StatusPanel.Show(); m_StatusPanel.Show();
// Use a thread to load plugins. // Use a thread to load plugins.
if (!DisableThreading) safe_delete( m_EnumeratorThread ); safe_delete( m_EnumeratorThread );
m_EnumeratorThread = new EnumThread( *this ); m_EnumeratorThread = new EnumThread( *this );
if( DisableThreading ) if( DisableThreading )
{ m_EnumeratorThread->DoNextPlugin( 0 );
m_ComponentBoxes.Reset();
m_EnumeratorThread->ExecuteTask();
}
else else
{
m_EnumeratorThread->Start(); m_EnumeratorThread->Start();
m_ComponentBoxes.Reset();
}
} }
bool Panels::PluginSelectorPanel::ValidateEnumerationStatus() bool Panels::PluginSelectorPanel::ValidateEnumerationStatus()
@ -338,6 +345,12 @@ bool Panels::PluginSelectorPanel::ValidateEnumerationStatus()
if( (m_FileList == NULL) || (*pluginlist != *m_FileList) ) if( (m_FileList == NULL) || (*pluginlist != *m_FileList) )
validated = false; validated = false;
if( pluggers == 0 )
{
safe_delete( m_FileList );
return validated;
}
delete m_FileList; delete m_FileList;
m_FileList = pluginlist.release(); m_FileList = pluginlist.release();
@ -363,7 +376,7 @@ void Panels::PluginSelectorPanel::OnConfigure_Clicked( wxCommandEvent& evt )
void Panels::PluginSelectorPanel::OnEnumComplete( wxCommandEvent& evt ) void Panels::PluginSelectorPanel::OnEnumComplete( wxCommandEvent& evt )
{ {
if (!DisableThreading) safe_delete( m_EnumeratorThread ); safe_delete( m_EnumeratorThread );
// fixme: Default plugins should be picked based on the timestamp of the DLL or something? // fixme: Default plugins should be picked based on the timestamp of the DLL or something?
// (for now we just force it to selection zero if nothing's selected) // (for now we just force it to selection zero if nothing's selected)
@ -388,7 +401,20 @@ void Panels::PluginSelectorPanel::OnProgress( wxCommandEvent& evt )
{ {
if( m_FileList == NULL ) return; if( m_FileList == NULL ) return;
size_t evtidx = evt.GetExtraLong(); const size_t evtidx = evt.GetExtraLong();
if( DisableThreading )
{
const int nextidx = evtidx+1;
if( nextidx == m_FileList->Count() )
{
wxCommandEvent done( wxEVT_EnumerationFinished );
GetEventHandler()->AddPendingEvent( done );
}
else
m_EnumeratorThread->DoNextPlugin( nextidx );
}
m_StatusPanel.AdvanceProgress( (evtidx < m_FileList->Count()-1) ? m_StatusPanel.AdvanceProgress( (evtidx < m_FileList->Count()-1) ?
(*m_FileList)[evtidx + 1] : wxString(_("Completing tasks...")) (*m_FileList)[evtidx + 1] : wxString(_("Completing tasks..."))
); );
@ -449,15 +475,8 @@ void Panels::PluginSelectorPanel::EnumThread::Cancel()
PersistentThread::Cancel(); PersistentThread::Cancel();
} }
sptr Panels::PluginSelectorPanel::EnumThread::ExecuteTask() void Panels::PluginSelectorPanel::EnumThread::DoNextPlugin( int curidx )
{ {
DevCon::Status( "Plugin Enumeration Thread started..." );
wxGetApp().Ping(); // gives the gui thread some time to refresh
for( int curidx=0; curidx < m_master.FileCount(); ++curidx )
{
if( m_cancel ) return 0;
DbgCon::WriteLn( L"Enumerating Plugin: " + m_master.GetFilename( curidx ) ); DbgCon::WriteLn( L"Enumerating Plugin: " + m_master.GetFilename( curidx ) );
try try
@ -484,11 +503,22 @@ sptr Panels::PluginSelectorPanel::EnumThread::ExecuteTask()
Console::Status( ex.FormatDiagnosticMessage() ); Console::Status( ex.FormatDiagnosticMessage() );
} }
pthread_testcancel();
wxCommandEvent yay( wxEVT_EnumeratedNext ); wxCommandEvent yay( wxEVT_EnumeratedNext );
yay.SetExtraLong( curidx ); yay.SetExtraLong( curidx );
m_master.GetEventHandler()->AddPendingEvent( yay ); m_master.GetEventHandler()->AddPendingEvent( yay );
}
sptr Panels::PluginSelectorPanel::EnumThread::ExecuteTask()
{
DevCon::Status( "Plugin Enumeration Thread started..." );
wxGetApp().Ping(); // gives the gui thread some time to refresh
for( int curidx=0; curidx < m_master.FileCount(); ++curidx )
{
if( m_cancel ) return 0;
DoNextPlugin( curidx );
pthread_testcancel();
} }
wxCommandEvent done( wxEVT_EnumerationFinished ); wxCommandEvent done( wxEVT_EnumerationFinished );