Files
57eec4d015 multithreaded collision fixes (#7311)
* rename misleading variable check_again to never_check_again

The first element of collision_result means "never check again" per the
typedef comment, but was destructured as check_again (opposite meaning).
Rename to never_check_again to match the actual semantics and prevent
future confusion.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* fix data races in ship-weapon collision threading

Two thread-safety bugs in ship_weapon_check_collision, which runs on
worker threads:

1. update_danger_weapon() wrote to Ai_info[] (danger_weapon_objnum,
   danger_weapon_signature) without synchronization. Multiple weapons
   targeting the same ship would race on the same Ai_info entry.

2. Homing missile detonation logic wrote wp->lifeleft and
   wp->weapon_flags directly on the Weapons[] global array.

Fix: defer both writes to the main-thread post-processing phase via
new flags in ship_weapon_collision_data. Also convert the collision
data from a 6-element tuple to a named struct for readability.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* fix data race in ship-ship collision submodel checking

ship_ship_check_collision() toggled pmi->submodel[].collision_checked
flags on the heavy ship's polymodel_instance to selectively enable/
disable submodel collision checks. When two collision pairs shared the
same heavy ship, worker threads would race on the same pmi entries.

Fix: add a collision_checked_override pointer to mc_info that lets
callers provide a thread-local array of collision_checked values.
model_collide() uses the override when set, falling back to the
pmi->submodel[] field otherwise. ship_ship_check_collision() now
builds a local SCP_vector<char> and passes it via the override,
completely avoiding writes to shared polymodel_instance state.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Ensure threads have spun down before continuing non-threaded execution

* address review feedback for ship-weapon collision threading

- postproc flag now accumulates incrementally instead of being OR'd
  at the final return, ensuring all return paths respect it
- early return for predictive collisions now preserves the
  should_update_danger_weapon flag in the collision data
- moved nprintf detonation debug print to the main-thread process
  pass for thread safety

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* move collision_checked from pmi into mc_info for thread safety

collision_checked flags were transient per-collision-pass state that
didn't belong in the shared polymodel_instance. Now mc_info owns an
SCP_vector<char> that model_collide auto-initializes from pmi when
empty. All collision callers (ship-ship, asteroid, debris, prop)
updated to manipulate mc.collision_checked instead of pmi->submodel[].

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Convert to CV and spinup counter

* Update comment

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
Co-authored-by: BMagnu <[email protected]>
2026-04-07 11:24:32 +09:00

22 lines
736 B
C++

#pragma once
#include <cstdint>
namespace threading {
enum class WorkerThreadTask : uint8_t { EXIT, COLLISION };
//Call this to start a task on the task pool. Note that task-specific data must be set up before calling this.
void spin_up_threaded_task(WorkerThreadTask task);
//This _must_ be called on the main thread BEFORE a task completes on a thread of the task pool.
void spin_down_threaded_task();
//This should be called AFTER the command to finish a given task is given. This will block until all threads have returned into a state where they are able to listen to new commands.
void spin_down_wait_complete();
void init_task_pool();
void shut_down_task_pool();
bool is_threading();
size_t get_num_workers();
}