#endif
#include "realwx_ctrl.hxx"
-#include "tiedpropertylist.hxx"
#include "metarproperties.hxx"
#include "metarairportfilter.hxx"
#include "fgmetar.hxx"
#include <simgear/structure/exception.hxx>
#include <simgear/misc/strutils.hxx>
+#include <simgear/props/tiedpropertylist.hxx>
#include <algorithm>
#if defined(ENABLE_THREADS)
#include <OpenThreads/Thread>
#include <simgear/threads/SGQueue.hxx>
#endif
+using simgear::PropertyList;
namespace Environment {
LiveMetarProperties::~LiveMetarProperties()
{
+ _tiedProperties.Untie();
}
void LiveMetarProperties::update( double dt )
bool _enabled;
bool __enabled;
- TiedPropertyList _tiedProperties;
- ; typedef std::vector<LiveMetarProperties_ptr> MetarPropertiesList;
+ simgear::TiedPropertyList _tiedProperties;
+ typedef std::vector<LiveMetarProperties_ptr> MetarPropertiesList;
MetarPropertiesList _metarProperties;
};
NoaaMetarRealWxController( SGPropertyNode_ptr rootNode );
virtual ~NoaaMetarRealWxController();
virtual void update (bool first, double delta_time_sec);
+ virtual void shutdown ();
class MetarLoadRequest {
public:
- MetarLoadRequest( const string & stationId ) {
- _stationId = stationId;
- _proxyHost = fgGetNode("/sim/presets/proxy/host", true)->getStringValue();
- _proxyPort = fgGetNode("/sim/presets/proxy/port", true)->getStringValue();
- _proxyAuth = fgGetNode("/sim/presets/proxy/authentication", true)->getStringValue();
- }
- MetarLoadRequest( const MetarLoadRequest & other ) {
- _stationId = other._stationId;
- _proxyHost = other._proxyAuth;
- _proxyPort = other._proxyPort;
- _proxyAuth = other._proxyAuth;
- }
+ MetarLoadRequest( const string & stationId ) :
+ _stationId(stationId),
+ _proxyHost(fgGetNode("/sim/presets/proxy/host", true)->getStringValue()),
+ _proxyPort(fgGetNode("/sim/presets/proxy/port", true)->getStringValue()),
+ _proxyAuth(fgGetNode("/sim/presets/proxy/authentication", true)->getStringValue())
+ {}
+ MetarLoadRequest( const MetarLoadRequest & other ) :
+ _stationId(other._stationId),
+ _proxyHost(other._proxyAuth),
+ _proxyPort(other._proxyPort),
+ _proxyAuth(other._proxyAuth)
+ {}
string _stationId;
string _proxyHost;
string _proxyPort;
class MetarLoadThread : public OpenThreads::Thread {
public:
MetarLoadThread( long maxAge );
+ virtual ~MetarLoadThread( ) { stop(); }
void requestMetar( const MetarLoadRequest & metarRequest, bool background = true );
bool hasMetar() { return _responseQueue.size() > 0; }
MetarLoadResponse getMetar() { return _responseQueue.pop(); }
virtual void run();
+ void stop();
private:
void fetch( const MetarLoadRequest & );
long _maxAge;
long _minRequestInterval;
+ volatile bool _stop;
SGBlockingQueue <MetarLoadRequest> _requestQueue;
SGBlockingQueue <MetarLoadResponse> _responseQueue;
};
#endif
}
-NoaaMetarRealWxController::~NoaaMetarRealWxController()
+void NoaaMetarRealWxController::shutdown()
{
#if defined(ENABLE_THREADS)
if( _metarLoadThread ) {
- MetarLoadRequest request("");
- _metarLoadThread->requestMetar(request);
- _metarLoadThread->join();
delete _metarLoadThread;
+ _metarLoadThread = NULL;
}
#endif // ENABLE_THREADS
}
+NoaaMetarRealWxController::~NoaaMetarRealWxController()
+{
+}
+
void NoaaMetarRealWxController::update( bool first, double dt )
{
_positionTimeToLive -= dt;
"NoaaMetarRealWxController::update(): spawning load request for station-id '" << stationId << "'" );
MetarLoadRequest request( stationId );
- // load the metar for the neares airport in the foreground if the fdm is uninitialized
+ // load the metar for the nearest airport in the foreground if the fdm is uninitialized
// to make sure a metar is received
// before the automatic runway selection code runs. All subsequent calls
// run in the background
#if defined(ENABLE_THREADS)
NoaaMetarRealWxController::MetarLoadThread::MetarLoadThread( long maxAge ) :
_maxAge(maxAge),
- _minRequestInterval(2000)
+ _minRequestInterval(2000),
+ _stop(false)
{
}
}
}
+void NoaaMetarRealWxController::MetarLoadThread::stop()
+{
+ // set stop flag and wake up the thread with an empty request
+ _stop = true;
+ MetarLoadRequest request("");
+ requestMetar(request);
+ join();
+}
+
void NoaaMetarRealWxController::MetarLoadThread::run()
{
SGTimeStamp lastRun = SGTimeStamp::fromSec(0);
for( ;; ) {
SGTimeStamp dt = SGTimeStamp::now() - lastRun;
- if( dt.getSeconds() * 1000 < _minRequestInterval )
- microSleep( (_minRequestInterval - dt.getSeconds() * 1000 ) * 1000 );
-
- lastRun = SGTimeStamp::now();
+ long delayMs = _minRequestInterval - dt.getSeconds() * 1000;
+ while (( delayMs > 0 ) && !_stop)
+ {
+ // sleep no more than 3 seconds at a time, otherwise shutdown response is too slow
+ long sleepMs = (delayMs>3000) ? 3000 : delayMs;
+ microSleep( sleepMs * 1000 );
+ delayMs -= sleepMs;
+ }
+ if (_stop)
+ break;
+
+ lastRun = SGTimeStamp::now();
+
const MetarLoadRequest request = _requestQueue.pop();
- if( request._stationId.size() == 0 )
+ if (( request._stationId.size() == 0 ) || _stop)
break;
fetch( request );
-
}
}