mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 20:40:04 +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
	
	 Dan Paulat
						Dan Paulat