mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	core_timing: Lock CoreTiming event queue while deserializing
To handle those classic asymmetric constructor/destructor side effects
This commit is contained in:
		
							parent
							
								
									b2531310b4
								
							
						
					
					
						commit
						996ca25a2e
					
				
					 3 changed files with 23 additions and 0 deletions
				
			
		|  | @ -629,6 +629,7 @@ void System::serialize(Archive& ar, const unsigned int file_version) { | |||
| 
 | ||||
|     // This needs to be set from somewhere - might as well be here!
 | ||||
|     if (Archive::is_loading::value) { | ||||
|         timing->UnlockEventQueue(); | ||||
|         Service::GSP::SetGlobalModule(*this); | ||||
|         memory->SetDSP(*dsp_core); | ||||
|         cheat_engine->Connect(); | ||||
|  |  | |||
|  | @ -49,6 +49,10 @@ TimingEventType* Timing::RegisterEvent(const std::string& name, TimedCallback ca | |||
| 
 | ||||
| void Timing::ScheduleEvent(s64 cycles_into_future, const TimingEventType* event_type, u64 userdata, | ||||
|                            std::size_t core_id) { | ||||
|     if (event_queue_locked) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     ASSERT(event_type != nullptr); | ||||
|     Timing::Timer* timer = nullptr; | ||||
|     if (core_id == std::numeric_limits<std::size_t>::max()) { | ||||
|  | @ -74,6 +78,9 @@ void Timing::ScheduleEvent(s64 cycles_into_future, const TimingEventType* event_ | |||
| } | ||||
| 
 | ||||
| void Timing::UnscheduleEvent(const TimingEventType* event_type, u64 userdata) { | ||||
|     if (event_queue_locked) { | ||||
|         return; | ||||
|     } | ||||
|     for (auto timer : timers) { | ||||
|         auto itr = std::remove_if( | ||||
|             timer->event_queue.begin(), timer->event_queue.end(), | ||||
|  | @ -89,6 +96,9 @@ void Timing::UnscheduleEvent(const TimingEventType* event_type, u64 userdata) { | |||
| } | ||||
| 
 | ||||
| void Timing::RemoveEvent(const TimingEventType* event_type) { | ||||
|     if (event_queue_locked) { | ||||
|         return; | ||||
|     } | ||||
|     for (auto timer : timers) { | ||||
|         auto itr = std::remove_if(timer->event_queue.begin(), timer->event_queue.end(), | ||||
|                                   [&](const Event& e) { return e.type == event_type; }); | ||||
|  |  | |||
|  | @ -280,6 +280,11 @@ public: | |||
| 
 | ||||
|     std::shared_ptr<Timer> GetTimer(std::size_t cpu_id); | ||||
| 
 | ||||
|     // Used after deserializing to unprotect the event queue.
 | ||||
|     void UnlockEventQueue() { | ||||
|         event_queue_locked = false; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     // unordered_map stores each element separately as a linked list node so pointers to
 | ||||
|     // elements remain stable regardless of rehashes/resizing.
 | ||||
|  | @ -292,6 +297,10 @@ private: | |||
|     // under/overclocking the guest cpu
 | ||||
|     double cpu_clock_scale = 1.0; | ||||
| 
 | ||||
|     // When true, the event queue can't be modified. Used while deserializing to workaround
 | ||||
|     // destructor side effects.
 | ||||
|     bool event_queue_locked = false; | ||||
| 
 | ||||
|     template <class Archive> | ||||
|     void serialize(Archive& ar, const unsigned int file_version) { | ||||
|         // event_types set during initialization of other things
 | ||||
|  | @ -303,6 +312,9 @@ private: | |||
|         } else { | ||||
|             ar& current_timer; | ||||
|         } | ||||
|         if (Archive::is_loading::value) { | ||||
|             event_queue_locked = true; | ||||
|         } | ||||
|     } | ||||
|     friend class boost::serialization::access; | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue