mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-18 13:40:04 +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
@ -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…
Reference in New Issue
Block a user