mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-11-01 03:00:05 +00:00
Refactoring alert timer handling, don't rely on assumptions regarding the lifetime of layer objects
This commit is contained in:
parent
655fb5042f
commit
39ac115b62
1 changed files with 48 additions and 58 deletions
|
|
@ -56,7 +56,6 @@ class AlertLayerHandler : public QObject
|
||||||
Q_OBJECT public :
|
Q_OBJECT public :
|
||||||
explicit AlertLayerHandler() :
|
explicit AlertLayerHandler() :
|
||||||
alertUpdateTimer_ {util::io_context()},
|
alertUpdateTimer_ {util::io_context()},
|
||||||
alertUpdateTimerActive_ {true},
|
|
||||||
alertSourceMap_ {},
|
alertSourceMap_ {},
|
||||||
featureMap_ {}
|
featureMap_ {}
|
||||||
{
|
{
|
||||||
|
|
@ -73,24 +72,22 @@ class AlertLayerHandler : public QObject
|
||||||
&manager::TextEventManager::AlertUpdated,
|
&manager::TextEventManager::AlertUpdated,
|
||||||
this,
|
this,
|
||||||
&AlertLayerHandler::HandleAlert);
|
&AlertLayerHandler::HandleAlert);
|
||||||
|
|
||||||
ScheduleAlertUpdate();
|
|
||||||
}
|
}
|
||||||
~AlertLayerHandler() = default;
|
~AlertLayerHandler()
|
||||||
|
{
|
||||||
|
std::unique_lock lock(alertMutex_);
|
||||||
|
alertUpdateTimer_.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
static AlertLayerHandler& Instance();
|
static std::shared_ptr<AlertLayerHandler> Instance();
|
||||||
|
|
||||||
std::list<QMapLibreGL::Feature>* FeatureList(awips::Phenomenon phenomenon,
|
std::list<QMapLibreGL::Feature>* FeatureList(awips::Phenomenon phenomenon,
|
||||||
bool alertActive);
|
bool alertActive);
|
||||||
|
|
||||||
void HandleAlert(const types::TextEventKey& key, size_t messageIndex);
|
void HandleAlert(const types::TextEventKey& key, size_t messageIndex);
|
||||||
void CancelAlertTimer();
|
void UpdateAlerts();
|
||||||
void ScheduleAlertUpdate();
|
|
||||||
void UpdateAlerts(const boost::system::error_code& e = {});
|
|
||||||
|
|
||||||
boost::asio::steady_timer alertUpdateTimer_;
|
boost::asio::steady_timer alertUpdateTimer_;
|
||||||
bool alertUpdateTimerActive_;
|
|
||||||
|
|
||||||
std::unordered_map<std::pair<awips::Phenomenon, bool>,
|
std::unordered_map<std::pair<awips::Phenomenon, bool>,
|
||||||
QVariantMap,
|
QVariantMap,
|
||||||
AlertTypeHash<std::pair<awips::Phenomenon, bool>>>
|
AlertTypeHash<std::pair<awips::Phenomenon, bool>>>
|
||||||
|
|
@ -113,24 +110,19 @@ class AlertLayerImpl : public QObject
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit AlertLayerImpl(std::shared_ptr<MapContext> context) :
|
explicit AlertLayerImpl(std::shared_ptr<MapContext> context) :
|
||||||
context_ {context}
|
context_ {context}, alertLayerHandler_ {AlertLayerHandler::Instance()}
|
||||||
{
|
{
|
||||||
connect(&AlertLayerHandler::Instance(),
|
connect(alertLayerHandler_.get(),
|
||||||
&AlertLayerHandler::AlertsUpdated,
|
&AlertLayerHandler::AlertsUpdated,
|
||||||
this,
|
this,
|
||||||
&AlertLayerImpl::UpdateSource);
|
&AlertLayerImpl::UpdateSource);
|
||||||
}
|
}
|
||||||
~AlertLayerImpl()
|
~AlertLayerImpl() {};
|
||||||
{
|
|
||||||
// Alert layer should never be destructed until the end of execution, this
|
|
||||||
// allows the alert timer to be cancelled and application cleanup to
|
|
||||||
// continue
|
|
||||||
AlertLayerHandler::Instance().CancelAlertTimer();
|
|
||||||
};
|
|
||||||
|
|
||||||
void UpdateSource(awips::Phenomenon phenomenon, bool alertActive);
|
void UpdateSource(awips::Phenomenon phenomenon, bool alertActive);
|
||||||
|
|
||||||
std::shared_ptr<MapContext> context_;
|
std::shared_ptr<MapContext> context_;
|
||||||
|
std::shared_ptr<AlertLayerHandler> alertLayerHandler_;
|
||||||
};
|
};
|
||||||
|
|
||||||
AlertLayer::AlertLayer(std::shared_ptr<MapContext> context) :
|
AlertLayer::AlertLayer(std::shared_ptr<MapContext> context) :
|
||||||
|
|
@ -335,21 +327,10 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlertLayerHandler::UpdateAlerts(const boost::system::error_code& e)
|
void AlertLayerHandler::UpdateAlerts()
|
||||||
{
|
{
|
||||||
logger_->trace("UpdateAlerts");
|
logger_->trace("UpdateAlerts");
|
||||||
|
|
||||||
if (e == boost::asio::error::operation_aborted)
|
|
||||||
{
|
|
||||||
logger_->debug("Alert update timer cancelled");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (e != boost::system::errc::success)
|
|
||||||
{
|
|
||||||
logger_->warn("Alert update timer error: {}", e.message());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Take a unique lock before modifying feature lists
|
// Take a unique lock before modifying feature lists
|
||||||
std::unique_lock lock(alertMutex_);
|
std::unique_lock lock(alertMutex_);
|
||||||
|
|
||||||
|
|
@ -387,34 +368,30 @@ void AlertLayerHandler::UpdateAlerts(const boost::system::error_code& e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release the lock after completing feature list updates
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
for (auto& alert : alertsUpdated)
|
for (auto& alert : alertsUpdated)
|
||||||
{
|
{
|
||||||
// Emit signal for each updated alert type
|
// Emit signal for each updated alert type
|
||||||
emit AlertsUpdated(alert.first, alert.second);
|
emit AlertsUpdated(alert.first, alert.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alertUpdateTimerActive_)
|
|
||||||
{
|
|
||||||
ScheduleAlertUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AlertLayerHandler::ScheduleAlertUpdate()
|
|
||||||
{
|
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
alertUpdateTimer_.expires_after(15s);
|
alertUpdateTimer_.expires_after(15s);
|
||||||
alertUpdateTimer_.async_wait([=](const boost::system::error_code& e)
|
alertUpdateTimer_.async_wait(
|
||||||
{ UpdateAlerts(e); });
|
[=](const boost::system::error_code& e)
|
||||||
}
|
{
|
||||||
|
if (e == boost::asio::error::operation_aborted)
|
||||||
void AlertLayerHandler::CancelAlertTimer()
|
{
|
||||||
{
|
logger_->debug("Alert update timer cancelled");
|
||||||
alertUpdateTimerActive_ = false;
|
}
|
||||||
alertUpdateTimer_.cancel();
|
else if (e != boost::system::errc::success)
|
||||||
|
{
|
||||||
|
logger_->warn("Alert update timer error: {}", e.message());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateAlerts();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AlertLayerImpl::UpdateSource(awips::Phenomenon phenomenon,
|
void AlertLayerImpl::UpdateSource(awips::Phenomenon phenomenon,
|
||||||
|
|
@ -426,21 +403,34 @@ void AlertLayerImpl::UpdateSource(awips::Phenomenon phenomenon,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& alertLayerHandler = AlertLayerHandler::Instance();
|
|
||||||
|
|
||||||
// Take a shared lock before using feature lists
|
// Take a shared lock before using feature lists
|
||||||
std::shared_lock lock(alertLayerHandler.alertMutex_);
|
std::shared_lock lock(alertLayerHandler_->alertMutex_);
|
||||||
|
|
||||||
// Update source, relies on alert source being defined
|
// Update source, relies on alert source being defined
|
||||||
map->updateSource(
|
map->updateSource(
|
||||||
QString("alertPolygon-%1").arg(GetSuffix(phenomenon, alertActive)),
|
QString("alertPolygon-%1").arg(GetSuffix(phenomenon, alertActive)),
|
||||||
alertLayerHandler.alertSourceMap_.at(
|
alertLayerHandler_->alertSourceMap_.at(
|
||||||
std::make_pair(phenomenon, alertActive)));
|
std::make_pair(phenomenon, alertActive)));
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertLayerHandler& AlertLayerHandler::Instance()
|
std::shared_ptr<AlertLayerHandler> AlertLayerHandler::Instance()
|
||||||
{
|
{
|
||||||
static AlertLayerHandler alertLayerHandler {};
|
static std::weak_ptr<AlertLayerHandler> alertLayerHandlerReference {};
|
||||||
|
static std::mutex instanceMutex {};
|
||||||
|
|
||||||
|
std::unique_lock lock(instanceMutex);
|
||||||
|
|
||||||
|
std::shared_ptr<AlertLayerHandler> alertLayerHandler =
|
||||||
|
alertLayerHandlerReference.lock();
|
||||||
|
|
||||||
|
if (alertLayerHandler == nullptr)
|
||||||
|
{
|
||||||
|
alertLayerHandler = std::make_shared<AlertLayerHandler>();
|
||||||
|
alertLayerHandlerReference = alertLayerHandler;
|
||||||
|
|
||||||
|
alertLayerHandler->UpdateAlerts();
|
||||||
|
}
|
||||||
|
|
||||||
return alertLayerHandler;
|
return alertLayerHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue