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 ),
|
||||
elapsed( 60.0 )
|
||||
{
|
||||
#ifdef ENABLE_THREADS
|
||||
thread = new MetarThread(this);
|
||||
thread->start();
|
||||
#endif // ENABLE_THREADS
|
||||
}
|
||||
|
||||
FGMetarEnvironmentCtrl::~FGMetarEnvironmentCtrl ()
|
||||
{
|
||||
#ifdef ENABLE_THREADS
|
||||
thread->cancel();
|
||||
thread->join();
|
||||
#endif // ENABLE_THREADS
|
||||
|
||||
delete env;
|
||||
env = NULL;
|
||||
}
|
||||
|
@ -411,9 +420,9 @@ FGMetarEnvironmentCtrl::reinit ()
|
|||
void
|
||||
FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
||||
{
|
||||
const SGPropertyNode *longitude
|
||||
static const SGPropertyNode *longitude
|
||||
= fgGetNode( "/position/longitude-deg", true );
|
||||
const SGPropertyNode *latitude
|
||||
static const SGPropertyNode *latitude
|
||||
= fgGetNode( "/position/latitude-deg", true );
|
||||
elapsed += delta_time_sec;
|
||||
if ( elapsed > update_interval_sec ) {
|
||||
|
@ -434,6 +443,7 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
|
|||
globals->get_airports()->no_metar( a.id );
|
||||
}
|
||||
}
|
||||
|
||||
env->update(delta_time_sec);
|
||||
}
|
||||
|
||||
|
@ -462,7 +472,26 @@ FGMetarEnvironmentCtrl::fetch_data (const string &icao)
|
|||
station_elevation_ft = a.elevation;
|
||||
|
||||
// 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 {
|
||||
m = new SGMetar( _icao.c_str() );
|
||||
} catch (const sg_io_exception& e) {
|
||||
|
@ -470,6 +499,7 @@ FGMetarEnvironmentCtrl::fetch_data (const string &icao)
|
|||
<< e.getFormattedMessage().c_str() );
|
||||
return false;
|
||||
}
|
||||
#endif // ENABLE_THREADS
|
||||
|
||||
d = m->getMinVisibility().getVisibility_m();
|
||||
d = (d != SGMetarNaN) ? d : 10000;
|
||||
|
@ -576,8 +606,61 @@ FGMetarEnvironmentCtrl::fetch_data (const string &icao)
|
|||
|
||||
delete m;
|
||||
|
||||
#ifdef ENABLE_THREADS
|
||||
mutex.lock();
|
||||
metar_cond.signal();
|
||||
mutex.unlock();
|
||||
#endif // ENABLE_THREADS
|
||||
|
||||
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
|
||||
|
|
|
@ -27,6 +27,11 @@
|
|||
#include <simgear/structure/subsystem_mgr.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
|
||||
# include <cmath>
|
||||
#else
|
||||
|
@ -159,6 +164,58 @@ private:
|
|||
float elapsed;
|
||||
bool fetch_data (const string &icao);
|
||||
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
|
||||
|
|
Loading…
Add table
Reference in a new issue