Hack to force GCC to invoke cancel_job() through DF's vtable

GCC appears to be optimizing the call to `cancel_job()` to use the stub in
*DFHack's* job_handler vtable, which is a no-op. Lua was unaffected because it
invokes vmethods through method pointers (without knowing the target instance at
compile time), so use a similar approach here for now.

As mentioned by @ab9rf on Discord, we should pursue an alternative like asking
Bay12 to expose the relevant code through a global `std::function` instead of a
vmethod.
develop
lethosor 2023-08-31 17:24:02 -04:00
parent 07e8e83837
commit 40bfb6b8ff
No known key found for this signature in database
GPG Key ID: 76A269552F4F58C1
1 changed files with 8 additions and 1 deletions

@ -387,7 +387,14 @@ bool DFHack::Job::removeJob(df::job* job) {
// call the job cancel vmethod graciously provided by The Toady One. // call the job cancel vmethod graciously provided by The Toady One.
// job_handler::cancel_job calls job::~job, and then deletes job (this has // job_handler::cancel_job calls job::~job, and then deletes job (this has
// been confirmed by disassembly). // been confirmed by disassembly).
world->jobs.cancel_job(job);
// HACK: GCC (starting around GCC 10 targeting C++20 as of v50.09) optimizes
// out the vmethod call here regardless of optimization level, so we need to
// invoke the vmethod manually through a pointer, as the Lua wrapper does.
// `volatile` does not seem to be necessary but is included for good
// measure.
volatile auto cancel_job_method = &df::job_handler::cancel_job;
(world->jobs.*cancel_job_method)(job);
return true; return true;
} }