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!
|
// This needs to be set from somewhere - might as well be here!
|
||||||
if (Archive::is_loading::value) {
|
if (Archive::is_loading::value) {
|
||||||
|
timing->UnlockEventQueue();
|
||||||
Service::GSP::SetGlobalModule(*this);
|
Service::GSP::SetGlobalModule(*this);
|
||||||
memory->SetDSP(*dsp_core);
|
memory->SetDSP(*dsp_core);
|
||||||
cheat_engine->Connect();
|
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,
|
void Timing::ScheduleEvent(s64 cycles_into_future, const TimingEventType* event_type, u64 userdata,
|
||||||
std::size_t core_id) {
|
std::size_t core_id) {
|
||||||
|
if (event_queue_locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(event_type != nullptr);
|
ASSERT(event_type != nullptr);
|
||||||
Timing::Timer* timer = nullptr;
|
Timing::Timer* timer = nullptr;
|
||||||
if (core_id == std::numeric_limits<std::size_t>::max()) {
|
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) {
|
void Timing::UnscheduleEvent(const TimingEventType* event_type, u64 userdata) {
|
||||||
|
if (event_queue_locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (auto timer : timers) {
|
for (auto timer : timers) {
|
||||||
auto itr = std::remove_if(
|
auto itr = std::remove_if(
|
||||||
timer->event_queue.begin(), timer->event_queue.end(),
|
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) {
|
void Timing::RemoveEvent(const TimingEventType* event_type) {
|
||||||
|
if (event_queue_locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (auto timer : timers) {
|
for (auto timer : timers) {
|
||||||
auto itr = std::remove_if(timer->event_queue.begin(), timer->event_queue.end(),
|
auto itr = std::remove_if(timer->event_queue.begin(), timer->event_queue.end(),
|
||||||
[&](const Event& e) { return e.type == event_type; });
|
[&](const Event& e) { return e.type == event_type; });
|
||||||
|
|
|
@ -280,6 +280,11 @@ public:
|
||||||
|
|
||||||
std::shared_ptr<Timer> GetTimer(std::size_t cpu_id);
|
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:
|
private:
|
||||||
// unordered_map stores each element separately as a linked list node so pointers to
|
// unordered_map stores each element separately as a linked list node so pointers to
|
||||||
// elements remain stable regardless of rehashes/resizing.
|
// elements remain stable regardless of rehashes/resizing.
|
||||||
|
@ -292,6 +297,10 @@ private:
|
||||||
// under/overclocking the guest cpu
|
// under/overclocking the guest cpu
|
||||||
double cpu_clock_scale = 1.0;
|
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>
|
template <class Archive>
|
||||||
void serialize(Archive& ar, const unsigned int file_version) {
|
void serialize(Archive& ar, const unsigned int file_version) {
|
||||||
// event_types set during initialization of other things
|
// event_types set during initialization of other things
|
||||||
|
@ -303,6 +312,9 @@ private:
|
||||||
} else {
|
} else {
|
||||||
ar& current_timer;
|
ar& current_timer;
|
||||||
}
|
}
|
||||||
|
if (Archive::is_loading::value) {
|
||||||
|
event_queue_locked = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue