mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 22:30:06 +00:00
Only use condition variable synchronization for animation, not other timeline functionality
This commit is contained in:
parent
580534d396
commit
9bb4ba4d93
1 changed files with 110 additions and 111 deletions
|
|
@ -59,8 +59,11 @@ public:
|
||||||
|
|
||||||
void Pause();
|
void Pause();
|
||||||
void Play();
|
void Play();
|
||||||
void SelectTime(std::chrono::system_clock::time_point selectedTime = {});
|
void
|
||||||
void Step(Direction direction);
|
SelectTimeAsync(std::chrono::system_clock::time_point selectedTime = {});
|
||||||
|
std::pair<bool, bool>
|
||||||
|
SelectTime(std::chrono::system_clock::time_point selectedTime = {});
|
||||||
|
void StepAsync(Direction direction);
|
||||||
|
|
||||||
std::size_t mapCount_ {0};
|
std::size_t mapCount_ {0};
|
||||||
std::string radarSite_ {"?"};
|
std::string radarSite_ {"?"};
|
||||||
|
|
@ -114,7 +117,7 @@ void TimelineManager::SetRadarSite(const std::string& radarSite)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If the selected view type is archive, select using the selected time
|
// If the selected view type is archive, select using the selected time
|
||||||
p->SelectTime(p->selectedTime_);
|
p->SelectTimeAsync(p->selectedTime_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +131,7 @@ void TimelineManager::SetDateTime(
|
||||||
if (p->viewType_ == types::MapTime::Archive)
|
if (p->viewType_ == types::MapTime::Archive)
|
||||||
{
|
{
|
||||||
// Only select if the view type is archive
|
// Only select if the view type is archive
|
||||||
p->SelectTime(dateTime);
|
p->SelectTimeAsync(dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore a date/time selection if the view type is live
|
// Ignore a date/time selection if the view type is live
|
||||||
|
|
@ -148,7 +151,7 @@ void TimelineManager::SetViewType(types::MapTime viewType)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If the selected view type is archive, select using the pinned time
|
// If the selected view type is archive, select using the pinned time
|
||||||
p->SelectTime(p->pinnedTime_);
|
p->SelectTimeAsync(p->pinnedTime_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -188,12 +191,12 @@ void TimelineManager::AnimationStepBegin()
|
||||||
p->pinnedTime_ == std::chrono::system_clock::time_point {})
|
p->pinnedTime_ == std::chrono::system_clock::time_point {})
|
||||||
{
|
{
|
||||||
// If the selected view type is live, select the current products
|
// If the selected view type is live, select the current products
|
||||||
p->SelectTime(std::chrono::system_clock::now() - p->loopTime_);
|
p->SelectTimeAsync(std::chrono::system_clock::now() - p->loopTime_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If the selected view type is archive, select using the pinned time
|
// If the selected view type is archive, select using the pinned time
|
||||||
p->SelectTime(p->pinnedTime_ - p->loopTime_);
|
p->SelectTimeAsync(p->pinnedTime_ - p->loopTime_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,7 +205,7 @@ void TimelineManager::AnimationStepBack()
|
||||||
logger_->debug("AnimationStepBack");
|
logger_->debug("AnimationStepBack");
|
||||||
|
|
||||||
p->Pause();
|
p->Pause();
|
||||||
p->Step(Direction::Back);
|
p->StepAsync(Direction::Back);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineManager::AnimationPlayPause()
|
void TimelineManager::AnimationPlayPause()
|
||||||
|
|
@ -224,7 +227,7 @@ void TimelineManager::AnimationStepNext()
|
||||||
logger_->debug("AnimationStepNext");
|
logger_->debug("AnimationStepNext");
|
||||||
|
|
||||||
p->Pause();
|
p->Pause();
|
||||||
p->Step(Direction::Next);
|
p->StepAsync(Direction::Next);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineManager::AnimationStepEnd()
|
void TimelineManager::AnimationStepEnd()
|
||||||
|
|
@ -241,7 +244,7 @@ void TimelineManager::AnimationStepEnd()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If the selected view type is archive, select using the pinned time
|
// If the selected view type is archive, select using the pinned time
|
||||||
p->SelectTime(p->pinnedTime_);
|
p->SelectTimeAsync(p->pinnedTime_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -415,30 +418,50 @@ void TimelineManager::Impl::Play()
|
||||||
newTime = currentTime + 1min;
|
newTime = currentTime + 1min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unlock prior to selecting time
|
||||||
|
lock.unlock();
|
||||||
|
|
||||||
|
// Lock radar sweep monitor
|
||||||
|
std::unique_lock radarSweepMonitorLock {radarSweepMonitorMutex_};
|
||||||
|
|
||||||
|
// Reset radar sweep monitor in preparation for update
|
||||||
|
RadarSweepMonitorReset();
|
||||||
|
|
||||||
|
// Select the time
|
||||||
|
auto selectTimeStart = std::chrono::steady_clock::now();
|
||||||
|
auto [volumeTimeUpdated, selectedTimeUpdated] = SelectTime(newTime);
|
||||||
|
auto selectTimeEnd = std::chrono::steady_clock::now();
|
||||||
|
auto elapsedTime = selectTimeEnd - selectTimeStart;
|
||||||
|
|
||||||
|
if (volumeTimeUpdated)
|
||||||
|
{
|
||||||
|
// Wait for radar sweeps to update
|
||||||
|
RadarSweepMonitorWait(radarSweepMonitorLock);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Disable radar sweep monitor
|
||||||
|
RadarSweepMonitorDisable();
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate the interval until the next update, prior to selecting
|
// Calculate the interval until the next update, prior to selecting
|
||||||
std::chrono::milliseconds interval;
|
std::chrono::milliseconds interval;
|
||||||
if (newTime != endTime)
|
if (newTime != endTime)
|
||||||
{
|
{
|
||||||
// Determine repeat interval (speed of 1.0 is 1 minute per second)
|
// Determine repeat interval (speed of 1.0 is 1 minute per second)
|
||||||
interval =
|
interval = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
std::chrono::milliseconds(std::lroundl(1000.0 / loopSpeed_));
|
std::chrono::milliseconds(std::lroundl(1000.0 / loopSpeed_)) -
|
||||||
|
elapsedTime);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Pause at the end of the loop
|
// Pause at the end of the loop
|
||||||
interval = loopDelay_;
|
interval = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
loopDelay_ - elapsedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
animationTimer_.expires_after(interval);
|
|
||||||
|
|
||||||
// Unlock prior to selecting time
|
|
||||||
lock.unlock();
|
|
||||||
|
|
||||||
// Select the time
|
|
||||||
SelectTime(newTime);
|
|
||||||
|
|
||||||
std::unique_lock animationTimerLock {animationTimerMutex_};
|
std::unique_lock animationTimerLock {animationTimerMutex_};
|
||||||
|
animationTimer_.expires_after(interval);
|
||||||
animationTimer_.async_wait(
|
animationTimer_.async_wait(
|
||||||
[this](const boost::system::error_code& e)
|
[this](const boost::system::error_code& e)
|
||||||
{
|
{
|
||||||
|
|
@ -461,118 +484,94 @@ void TimelineManager::Impl::Play()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineManager::Impl::SelectTime(
|
void TimelineManager::Impl::SelectTimeAsync(
|
||||||
std::chrono::system_clock::time_point selectedTime)
|
std::chrono::system_clock::time_point selectedTime)
|
||||||
{
|
{
|
||||||
|
scwx::util::async([=, this]() { SelectTime(selectedTime); });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<bool, bool> TimelineManager::Impl::SelectTime(
|
||||||
|
std::chrono::system_clock::time_point selectedTime)
|
||||||
|
{
|
||||||
|
bool volumeTimeUpdated = false;
|
||||||
|
bool selectedTimeUpdated = false;
|
||||||
|
|
||||||
if (selectedTime_ == selectedTime && radarSite_ == previousRadarSite_)
|
if (selectedTime_ == selectedTime && radarSite_ == previousRadarSite_)
|
||||||
{
|
{
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
return;
|
return {volumeTimeUpdated, selectedTimeUpdated};
|
||||||
}
|
}
|
||||||
else if (selectedTime == std::chrono::system_clock::time_point {})
|
else if (selectedTime == std::chrono::system_clock::time_point {})
|
||||||
{
|
{
|
||||||
scwx::util::async(
|
// If a default time point is given, reset to a live view
|
||||||
[=, this]()
|
selectedTime_ = selectedTime;
|
||||||
{
|
adjustedTime_ = selectedTime;
|
||||||
// Take a lock for time selection
|
previousRadarSite_ = radarSite_;
|
||||||
std::unique_lock lock {selectTimeMutex_};
|
|
||||||
|
|
||||||
// If a default time point is given, reset to a live view
|
logger_->debug("Time updated: Live");
|
||||||
selectedTime_ = selectedTime;
|
|
||||||
adjustedTime_ = selectedTime;
|
|
||||||
|
|
||||||
logger_->debug("Time updated: Live");
|
Q_EMIT self_->LiveStateUpdated(true);
|
||||||
|
Q_EMIT self_->VolumeTimeUpdated(selectedTime);
|
||||||
|
Q_EMIT self_->SelectedTimeUpdated(selectedTime);
|
||||||
|
|
||||||
std::unique_lock radarSweepMonitorLock {radarSweepMonitorMutex_};
|
volumeTimeUpdated = true;
|
||||||
|
selectedTimeUpdated = true;
|
||||||
|
|
||||||
// Reset radar sweep monitor in preparation for update
|
return {volumeTimeUpdated, selectedTimeUpdated};
|
||||||
RadarSweepMonitorReset();
|
|
||||||
|
|
||||||
Q_EMIT self_->LiveStateUpdated(true);
|
|
||||||
Q_EMIT self_->VolumeTimeUpdated(selectedTime);
|
|
||||||
Q_EMIT self_->SelectedTimeUpdated(selectedTime);
|
|
||||||
|
|
||||||
// Wait for radar sweeps to update
|
|
||||||
RadarSweepMonitorWait(radarSweepMonitorLock);
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scwx::util::async(
|
// Take a lock for time selection
|
||||||
[=, this]()
|
std::unique_lock lock {selectTimeMutex_};
|
||||||
|
|
||||||
|
// Request active volume times
|
||||||
|
auto radarProductManager =
|
||||||
|
manager::RadarProductManager::Instance(radarSite_);
|
||||||
|
auto volumeTimes = radarProductManager->GetActiveVolumeTimes(selectedTime);
|
||||||
|
|
||||||
|
// Dynamically update maximum cached volume scans
|
||||||
|
UpdateCacheLimit(radarProductManager, volumeTimes);
|
||||||
|
|
||||||
|
// Find the best match bounded time
|
||||||
|
auto elementPtr = util::GetBoundedElementPointer(volumeTimes, selectedTime);
|
||||||
|
|
||||||
|
// The timeline is no longer live
|
||||||
|
Q_EMIT self_->LiveStateUpdated(false);
|
||||||
|
|
||||||
|
if (elementPtr != nullptr)
|
||||||
|
{
|
||||||
|
// If the adjusted time changed, or if a new radar site has been selected
|
||||||
|
if (adjustedTime_ != *elementPtr || radarSite_ != previousRadarSite_)
|
||||||
{
|
{
|
||||||
// Take a lock for time selection
|
// If the time was found, select it
|
||||||
std::unique_lock lock {selectTimeMutex_};
|
adjustedTime_ = *elementPtr;
|
||||||
|
|
||||||
// Request active volume times
|
logger_->debug("Volume time updated: {}",
|
||||||
auto radarProductManager =
|
scwx::util::TimeString(adjustedTime_));
|
||||||
manager::RadarProductManager::Instance(radarSite_);
|
|
||||||
auto volumeTimes =
|
|
||||||
radarProductManager->GetActiveVolumeTimes(selectedTime);
|
|
||||||
|
|
||||||
// Dynamically update maximum cached volume scans
|
volumeTimeUpdated = true;
|
||||||
UpdateCacheLimit(radarProductManager, volumeTimes);
|
Q_EMIT self_->VolumeTimeUpdated(adjustedTime_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No volume time was found
|
||||||
|
logger_->info("No volume scan found for {}",
|
||||||
|
scwx::util::TimeString(selectedTime));
|
||||||
|
}
|
||||||
|
|
||||||
// Find the best match bounded time
|
logger_->trace("Selected time updated: {}",
|
||||||
auto elementPtr =
|
scwx::util::TimeString(selectedTime));
|
||||||
util::GetBoundedElementPointer(volumeTimes, selectedTime);
|
|
||||||
|
|
||||||
// The timeline is no longer live
|
selectedTime_ = selectedTime;
|
||||||
Q_EMIT self_->LiveStateUpdated(false);
|
selectedTimeUpdated = true;
|
||||||
|
Q_EMIT self_->SelectedTimeUpdated(selectedTime);
|
||||||
|
|
||||||
bool volumeTimeUpdated = false;
|
previousRadarSite_ = radarSite_;
|
||||||
|
|
||||||
std::unique_lock radarSweepMonitorLock {radarSweepMonitorMutex_};
|
return {volumeTimeUpdated, selectedTimeUpdated};
|
||||||
|
|
||||||
// Reset radar sweep monitor in preparation for update
|
|
||||||
RadarSweepMonitorReset();
|
|
||||||
|
|
||||||
if (elementPtr != nullptr)
|
|
||||||
{
|
|
||||||
// If the adjusted time changed, or if a new radar site has been
|
|
||||||
// selected
|
|
||||||
if (adjustedTime_ != *elementPtr ||
|
|
||||||
radarSite_ != previousRadarSite_)
|
|
||||||
{
|
|
||||||
// If the time was found, select it
|
|
||||||
adjustedTime_ = *elementPtr;
|
|
||||||
|
|
||||||
logger_->debug("Volume time updated: {}",
|
|
||||||
scwx::util::TimeString(adjustedTime_));
|
|
||||||
|
|
||||||
volumeTimeUpdated = true;
|
|
||||||
Q_EMIT self_->VolumeTimeUpdated(adjustedTime_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// No volume time was found
|
|
||||||
logger_->info("No volume scan found for {}",
|
|
||||||
scwx::util::TimeString(selectedTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
logger_->trace("Selected time updated: {}",
|
|
||||||
scwx::util::TimeString(selectedTime));
|
|
||||||
|
|
||||||
selectedTime_ = selectedTime;
|
|
||||||
Q_EMIT self_->SelectedTimeUpdated(selectedTime);
|
|
||||||
|
|
||||||
previousRadarSite_ = radarSite_;
|
|
||||||
|
|
||||||
if (volumeTimeUpdated)
|
|
||||||
{
|
|
||||||
// Wait for radar sweeps to update
|
|
||||||
RadarSweepMonitorWait(radarSweepMonitorLock);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RadarSweepMonitorDisable();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimelineManager::Impl::Step(Direction direction)
|
void TimelineManager::Impl::StepAsync(Direction direction)
|
||||||
{
|
{
|
||||||
scwx::util::async(
|
scwx::util::async(
|
||||||
[=, this]()
|
[=, this]()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue