NGSPICE as a singleton

One cannot call ngSpice_Init() twice without unloading the dll. When calling
ngSpice_Init, we pass a pointer to a NGSPICE instance and thus it cannot be changed.
When any of the callback function is called with a stale pointer everything crashes.
This commit is contained in:
Maciej Suminski 2016-08-19 15:51:19 +02:00
parent bcfce68daa
commit 2a6b8f153b
4 changed files with 26 additions and 20 deletions

View File

@ -45,7 +45,6 @@ NGSPICE::~NGSPICE()
void NGSPICE::Init() void NGSPICE::Init()
{ {
init();
Command( "reset" ); Command( "reset" );
} }

View File

@ -109,6 +109,19 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
if( m_schematicFrame == NULL ) if( m_schematicFrame == NULL )
throw std::runtime_error( "There is no schematic window" ); throw std::runtime_error( "There is no schematic window" );
m_simulator = SPICE_SIMULATOR::CreateInstance( "ngspice" );
if( !m_simulator )
{
throw std::runtime_error( "Could not create simulator instance" );
return;
}
m_simulator->Init();
m_reporter = new SIM_THREAD_REPORTER( this );
m_simulator->SetReporter( m_reporter );
updateNetlistExporter(); updateNetlistExporter();
Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SIM_PLOT_FRAME::onClose ), NULL, this ); Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( SIM_PLOT_FRAME::onClose ), NULL, this );
@ -145,12 +158,13 @@ SIM_PLOT_FRAME::SIM_PLOT_FRAME( KIWAY* aKiway, wxWindow* aParent )
m_toolBar->Realize(); m_toolBar->Realize();
m_plotNotebook->SetPageText( 0, _( "Welcome!" ) ); m_plotNotebook->SetPageText( 0, _( "Welcome!" ) );
m_simulator.reset( SPICE_SIMULATOR::CreateInstance( "ngspice" ) );
} }
SIM_PLOT_FRAME::~SIM_PLOT_FRAME() SIM_PLOT_FRAME::~SIM_PLOT_FRAME()
{ {
delete m_simulator;
delete m_reporter;
} }
@ -159,12 +173,6 @@ void SIM_PLOT_FRAME::StartSimulation()
STRING_FORMATTER formatter; STRING_FORMATTER formatter;
SIM_PLOT_PANEL* plotPanel = CurrentPlot(); SIM_PLOT_PANEL* plotPanel = CurrentPlot();
if( !m_simulator )
{
DisplayError( this, wxT( "Could not create simulator instance" ) );
return;
}
m_simConsole->Clear(); m_simConsole->Clear();
updateNetlistExporter(); updateNetlistExporter();
@ -183,8 +191,6 @@ void SIM_PLOT_FRAME::StartSimulation()
return; return;
} }
m_simulator->SetReporter( new SIM_THREAD_REPORTER( this ) );
m_simulator->Init();
m_simulator->LoadNetlist( formatter.GetString() ); m_simulator->LoadNetlist( formatter.GetString() );
updateTuners(); updateTuners();
applyTuners(); applyTuners();
@ -194,8 +200,7 @@ void SIM_PLOT_FRAME::StartSimulation()
void SIM_PLOT_FRAME::StopSimulation() void SIM_PLOT_FRAME::StopSimulation()
{ {
if( m_simulator ) m_simulator->Stop();
m_simulator->Stop();
} }
@ -367,9 +372,6 @@ void SIM_PLOT_FRAME::updateNetlistExporter()
bool SIM_PLOT_FRAME::updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL* aPanel ) bool SIM_PLOT_FRAME::updatePlot( const TRACE_DESC& aDescriptor, SIM_PLOT_PANEL* aPanel )
{ {
if( !m_simulator )
return false;
SIM_TYPE simType = m_exporter->GetSimType(); SIM_TYPE simType = m_exporter->GetSimType();
wxString spiceVector = m_exporter->GetSpiceVector( aDescriptor.GetName(), wxString spiceVector = m_exporter->GetSpiceVector( aDescriptor.GetName(),
aDescriptor.GetType(), aDescriptor.GetParam() ); aDescriptor.GetType(), aDescriptor.GetParam() );
@ -494,6 +496,7 @@ void SIM_PLOT_FRAME::applyTuners()
/// @todo no ngspice hardcoding /// @todo no ngspice hardcoding
std::string command( "alter @" + tuner->GetSpiceName() std::string command( "alter @" + tuner->GetSpiceName()
+ "=" + tuner->GetValue().ToSpiceString() ); + "=" + tuner->GetValue().ToSpiceString() );
m_simulator->Command( command ); m_simulator->Command( command );
} }
} }
@ -1015,9 +1018,6 @@ void SIM_PLOT_FRAME::onSimFinished( wxCommandEvent& aEvent )
void SIM_PLOT_FRAME::onSimUpdate( wxCommandEvent& aEvent ) void SIM_PLOT_FRAME::onSimUpdate( wxCommandEvent& aEvent )
{ {
if( !m_simulator )
return;
if( IsSimulationRunning() ) if( IsSimulationRunning() )
StopSimulation(); StopSimulation();

View File

@ -48,6 +48,7 @@ class SCH_COMPONENT;
class SPICE_SIMULATOR; class SPICE_SIMULATOR;
class NETLIST_EXPORTER_PSPICE_SIM; class NETLIST_EXPORTER_PSPICE_SIM;
class SIM_PLOT_PANEL; class SIM_PLOT_PANEL;
class SIM_THREAD_REPORTER;
class TUNER_SLIDER; class TUNER_SLIDER;
///> Trace descriptor class ///> Trace descriptor class
@ -271,7 +272,8 @@ private:
SCH_EDIT_FRAME* m_schematicFrame; SCH_EDIT_FRAME* m_schematicFrame;
std::unique_ptr<NETLIST_EXPORTER_PSPICE_SIM> m_exporter; std::unique_ptr<NETLIST_EXPORTER_PSPICE_SIM> m_exporter;
std::unique_ptr<SPICE_SIMULATOR> m_simulator; SPICE_SIMULATOR* m_simulator;
SIM_THREAD_REPORTER* m_reporter;
typedef std::map<wxString, TRACE_DESC> TRACE_MAP; typedef std::map<wxString, TRACE_DESC> TRACE_MAP;

View File

@ -30,7 +30,12 @@ SPICE_SIMULATOR* SPICE_SIMULATOR::CreateInstance( const std::string& )
{ {
try try
{ {
return new NGSPICE; static NGSPICE* ngspiceInstance = nullptr;
if( !ngspiceInstance )
ngspiceInstance = new NGSPICE;
return ngspiceInstance;
} }
catch( std::exception& e ) catch( std::exception& e )
{ {