Add threading to metar data fetching where available.
This commit is contained in:
parent
4fca15fa1d
commit
bca8c29795
2 changed files with 143 additions and 3 deletions
|
@ -320,10 +320,19 @@ FGMetarEnvironmentCtrl::FGMetarEnvironmentCtrl ()
|
||||||
update_interval_sec( 60.0 ),
|
update_interval_sec( 60.0 ),
|
||||||
elapsed( 60.0 )
|
elapsed( 60.0 )
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_THREADS
|
||||||
|
thread = new MetarThread(this);
|
||||||
|
thread->start();
|
||||||
|
#endif // ENABLE_THREADS
|
||||||
}
|
}
|
||||||
|
|
||||||
FGMetarEnvironmentCtrl::~FGMetarEnvironmentCtrl ()
|
FGMetarEnvironmentCtrl::~FGMetarEnvironmentCtrl ()
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_THREADS
|
||||||
|
thread->cancel();
|
||||||
|
thread->join();
|
||||||
|
#endif // ENABLE_THREADS
|
||||||
|
|
||||||
delete env;
|
delete env;
|
||||||
env = NULL;
|
env = NULL;
|
||||||
}
|
}
|
||||||
|
@ -411,9 +420,9 @@ FGMetarEnvironmentCtrl::reinit ()
|
||||||
void
|
void
|
||||||
FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
||||||
{
|
{
|
||||||
const SGPropertyNode *longitude
|
static const SGPropertyNode *longitude
|
||||||
= fgGetNode( "/position/longitude-deg", true );
|
= fgGetNode( "/position/longitude-deg", true );
|
||||||
const SGPropertyNode *latitude
|
static const SGPropertyNode *latitude
|
||||||
= fgGetNode( "/position/latitude-deg", true );
|
= fgGetNode( "/position/latitude-deg", true );
|
||||||
elapsed += delta_time_sec;
|
elapsed += delta_time_sec;
|
||||||
if ( elapsed > update_interval_sec ) {
|
if ( elapsed > update_interval_sec ) {
|
||||||
|
@ -434,6 +443,7 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
||||||
globals->get_airports()->no_metar( a.id );
|
globals->get_airports()->no_metar( a.id );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
env->update(delta_time_sec);
|
env->update(delta_time_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +472,26 @@ FGMetarEnvironmentCtrl::fetch_data (const string &icao)
|
||||||
station_elevation_ft = a.elevation;
|
station_elevation_ft = a.elevation;
|
||||||
|
|
||||||
// fetch current metar data
|
// fetch current metar data
|
||||||
SGMetar *m;
|
SGMetar *m = NULL;
|
||||||
|
#ifdef ENABLE_THREADS
|
||||||
|
|
||||||
|
bool valid_data = false;
|
||||||
|
if (!metar_queue.empty())
|
||||||
|
{
|
||||||
|
m = metar_queue.pop();
|
||||||
|
|
||||||
|
if (m != NULL)
|
||||||
|
valid_data = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( valid_data == false ) {
|
||||||
|
mutex.lock();
|
||||||
|
metar_cond.signal();
|
||||||
|
mutex.unlock();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
try {
|
try {
|
||||||
m = new SGMetar( _icao.c_str() );
|
m = new SGMetar( _icao.c_str() );
|
||||||
} catch (const sg_io_exception& e) {
|
} catch (const sg_io_exception& e) {
|
||||||
|
@ -470,6 +499,7 @@ FGMetarEnvironmentCtrl::fetch_data (const string &icao)
|
||||||
<< e.getFormattedMessage().c_str() );
|
<< e.getFormattedMessage().c_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif // ENABLE_THREADS
|
||||||
|
|
||||||
d = m->getMinVisibility().getVisibility_m();
|
d = m->getMinVisibility().getVisibility_m();
|
||||||
d = (d != SGMetarNaN) ? d : 10000;
|
d = (d != SGMetarNaN) ? d : 10000;
|
||||||
|
@ -576,8 +606,61 @@ FGMetarEnvironmentCtrl::fetch_data (const string &icao)
|
||||||
|
|
||||||
delete m;
|
delete m;
|
||||||
|
|
||||||
|
#ifdef ENABLE_THREADS
|
||||||
|
mutex.lock();
|
||||||
|
metar_cond.signal();
|
||||||
|
mutex.unlock();
|
||||||
|
#endif // ENABLE_THREADS
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_THREADS
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
FGMetarEnvironmentCtrl::MetarThread::run()
|
||||||
|
{
|
||||||
|
SGMetar *m = NULL;
|
||||||
|
|
||||||
|
// pthread_cleanup_push( metar_cleanup_handler, fetcher );
|
||||||
|
while ( true )
|
||||||
|
{
|
||||||
|
set_cancel( SGThread::CANCEL_DISABLE );
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cout << "Fetching ..." << endl;
|
||||||
|
// if (m != NULL) m = NULL;
|
||||||
|
m = new SGMetar( fetcher->_icao.c_str() );
|
||||||
|
|
||||||
|
} catch (const sg_io_exception& e) {
|
||||||
|
// SG_LOG( SG_GENERAL, SG_WARN, "Error fetching live weather data: "
|
||||||
|
// << e.getFormattedMessage().c_str() );
|
||||||
|
m = NULL;
|
||||||
|
}
|
||||||
|
set_cancel( SGThread::CANCEL_DEFERRED );
|
||||||
|
|
||||||
|
fetcher->metar_queue.push( m );
|
||||||
|
|
||||||
|
// Wait for the next frame signal before we fetch the next metar data
|
||||||
|
fetcher->mutex.lock();
|
||||||
|
fetcher->metar_cond.wait( fetcher->mutex );
|
||||||
|
fetcher->mutex.unlock();
|
||||||
|
}
|
||||||
|
// pthread_cleanup_pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure mutex is unlocked.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
metar_cleanup_handler( void* arg )
|
||||||
|
{
|
||||||
|
FGMetarEnvironmentCtrl* fetcher = (FGMetarEnvironmentCtrl*) arg;
|
||||||
|
fetcher->mutex.unlock();
|
||||||
|
}
|
||||||
|
#endif // ENABLE_THREADS
|
||||||
|
|
||||||
|
|
||||||
// end of environment_ctrl.cxx
|
// end of environment_ctrl.cxx
|
||||||
|
|
|
@ -27,6 +27,11 @@
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <simgear/environment/metar.hxx>
|
#include <simgear/environment/metar.hxx>
|
||||||
|
|
||||||
|
#ifdef ENABLE_THREADS
|
||||||
|
# include <simgear/threads/SGThread.hxx>
|
||||||
|
# include <simgear/threads/SGQueue.hxx>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef SG_HAVE_STD_INCLUDES
|
#ifdef SG_HAVE_STD_INCLUDES
|
||||||
# include <cmath>
|
# include <cmath>
|
||||||
#else
|
#else
|
||||||
|
@ -159,6 +164,58 @@ private:
|
||||||
float elapsed;
|
float elapsed;
|
||||||
bool fetch_data (const string &icao);
|
bool fetch_data (const string &icao);
|
||||||
void update_env_config();
|
void update_env_config();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
#ifdef ENABLE_THREADS
|
||||||
|
/**
|
||||||
|
* FIFO queue which holds a pointer to the fetched metar data.
|
||||||
|
*/
|
||||||
|
SGBlockingQueue< SGMetar * > metar_queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the thread of execution responsible for
|
||||||
|
* fetching the metar data.
|
||||||
|
*/
|
||||||
|
class MetarThread : public SGThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MetarThread( FGMetarEnvironmentCtrl* f ) : fetcher(f) {}
|
||||||
|
~MetarThread() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the tile from disk.
|
||||||
|
*/
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
FGMetarEnvironmentCtrl *fetcher;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// not implemented.
|
||||||
|
MetarThread();
|
||||||
|
MetarThread( const MetarThread& );
|
||||||
|
MetarThread& operator=( const MetarThread& );
|
||||||
|
};
|
||||||
|
|
||||||
|
friend class MetarThread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Metar data fetching thread.
|
||||||
|
*/
|
||||||
|
MetarThread* thread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lock and synchronize access to metar queue.
|
||||||
|
*/
|
||||||
|
SGMutex mutex;
|
||||||
|
SGPthreadCond metar_cond;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread cleanup handler.
|
||||||
|
*/
|
||||||
|
friend void metar_cleanup_handler( void* );
|
||||||
|
#endif // ENABLE_THREADS
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _ENVIRONMENT_CTRL_HXX
|
#endif // _ENVIRONMENT_CTRL_HXX
|
||||||
|
|
Loading…
Add table
Reference in a new issue