Skip to content

Conversation

@bobtista
Copy link

Refactors path-following functions to use move when transferring std::vector<Coord3D> ownership

Changes:

  • Updated aiFollowExitProductionPath and aiFollowPath inline functions to accept non-const vector pointers and use std::move
  • Modified AIStateMachine::setGoalPath to move the vector instead of copying
  • Updated privateFollowPath and doQuickExit signatures to support move semantics
@bobtista bobtista marked this pull request as ready for review November 25, 2025 17:58
Copy link

@xezon xezon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you check that the passed vector is never used after it is consumed?

@xezon xezon added Minor Severity: Minor < Major < Critical < Blocker Performance Is a performance concern labels Nov 25, 2025
@bobtista
Copy link
Author

Did you check that the passed vector is never used after it is consumed?

Looking at call sites, they all pass local vectors (exitPath, path) that are not used after the function call. They go out of scope immediately, so this is safe, right?

@xezon
Copy link

xezon commented Nov 25, 2025

Yes, when the std::vector contents are not used anymore after they are now consumed by the functions then this is safe.

break;
case AICMD_FOLLOW_PATH:
privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE);
privateFollowPath(&const_cast<AICommandParms*>(parms)->m_coords, parms->m_obj, parms->m_cmdSource, FALSE);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is going on with the const_cast here? This looks dangerous. Can we get rid of it?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it can be mutable. Another option maybe we change aiDoCommand to take non-const pointer, but that changes more stuff. I set it to mutable.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is not so elegant either.

The problem looks to be that AICommandParms is passed as const to aiDoCommand functions. I suspect we need another change and pass it as non const, UNLESS there is a very good reason why we cannot consume these structures.

This would also allow to optimize this call:

m_pendingCommand.store(*parms) 

It currently creates a copy of the whole thing, instead of swapping/moving it.

Perhaps we need another change, refactoring aiDoCommand first, then optimize m_pendingCommand and this change.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1924, and I used a script to replicate to generals :)

break;
case AICMD_FOLLOW_PATH:
privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE);
privateFollowPath(&const_cast<AICommandParms*>(parms)->m_coords, parms->m_obj, parms->m_cmdSource, FALSE);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is not so elegant either.

The problem looks to be that AICommandParms is passed as const to aiDoCommand functions. I suspect we need another change and pass it as non const, UNLESS there is a very good reason why we cannot consume these structures.

This would also allow to optimize this call:

m_pendingCommand.store(*parms) 

It currently creates a copy of the whole thing, instead of swapping/moving it.

Perhaps we need another change, refactoring aiDoCommand first, then optimize m_pendingCommand and this change.

Object* m_otherObj;
const Team* m_team;
std::vector<Coord3D> m_coords;
mutable std::vector<Coord3D> m_coords;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After thinking about this more, let us do a lightweight refactor and only touch where we can easily avoid a copy without const_casts or mutables.

Then also close #1924

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so close 1924, and close this, and make another PR? Which changes do we want?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the mutable and then keep the copies where it would fail to compile.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I closed 1924 and AICommandParms::m_coords is now non-mutable again.

@bobtista bobtista force-pushed the bobtista/move-vector-instead-of-copy branch from e97db76 to 8c112de Compare December 15, 2025 15:17
}

void aiFollowExitProductionPath( const std::vector<Coord3D>* path, Object *ignoreObject, CommandSourceType cmdSource )
inline void aiFollowExitProductionPath( std::vector<Coord3D>* path, Object *ignoreObject, CommandSourceType cmdSource )
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds inline keyword. Multiple times.

m_coords = parms.m_coords;
// We intentionally const_cast here so we can move the path coordinates into storage.
// AICommandParms is treated as a transient command container that is not reused after dispatch.
std::vector<Coord3D>& coords = const_cast<std::vector<Coord3D>&>(parms.m_coords);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth it to do this? Otherwise I recommend to leave the copy. Is safer if something changes higher up.

case AICMD_FOLLOW_PATH:
privateFollowPath(&parms->m_coords, parms->m_obj, parms->m_cmdSource, FALSE);
{
// Keep AICommandParms const; use a local copy of the coordinates when following the path.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is a bit confusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Minor Severity: Minor < Major < Critical < Blocker Performance Is a performance concern

3 participants