1
0
Fork 0

Codechange: Use EnumBitSet for SigFlags. (#13784)

pull/13787/head
Peter Nelson 2025-03-09 18:01:52 +00:00 committed by GitHub
parent 572f2801ac
commit 61aa45071a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 43 additions and 46 deletions

View File

@ -243,22 +243,19 @@ static inline bool MaybeAddToTodoSet(TileIndex t1, DiagDirection d1, TileIndex t
/** Current signal block state flags */
enum SigFlags : uint16_t {
SF_NONE = 0,
SF_TRAIN = 1 << 0, ///< train found in segment
SF_EXIT = 1 << 1, ///< exitsignal found
SF_EXIT2 = 1 << 2, ///< two or more exits found
SF_GREEN = 1 << 3, ///< green exitsignal found
SF_GREEN2 = 1 << 4, ///< two or more green exits found
SF_FULL = 1 << 5, ///< some of buffers was full, do not continue
SF_PBS = 1 << 6, ///< pbs signal found
SF_SPLIT = 1 << 7, ///< track merge/split found
SF_ENTER = 1 << 8, ///< signal entering the block found
SF_ENTER2 = 1 << 9, ///< two or more signals entering the block found
enum class SigFlag : uint8_t {
Train, ///< train found in segment
Exit, ///< exitsignal found
MultiExit, ///< two or more exits found
Green, ///< green exitsignal found
MultiGreen, ///< two or more green exits found
Full, ///< some of buffers was full, do not continue
Pbs, ///< pbs signal found
Split, ///< track merge/split found
Enter, ///< signal entering the block found
MultiEnter, ///< two or more signals entering the block found
};
DECLARE_ENUM_AS_BIT_SET(SigFlags)
using SigFlags = EnumBitSet<SigFlag, uint16_t>;
/**
* Search signal block
@ -268,7 +265,7 @@ DECLARE_ENUM_AS_BIT_SET(SigFlags)
*/
static SigFlags ExploreSegment(Owner owner)
{
SigFlags flags = SF_NONE;
SigFlags flags{};
TileIndex tile = INVALID_TILE; // Stop GCC from complaining about a possibly uninitialized variable (issue #8280).
DiagDirection enterdir = INVALID_DIAGDIR;
@ -283,13 +280,13 @@ static SigFlags ExploreSegment(Owner owner)
if (IsRailDepot(tile)) {
if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train);
exitdir = GetRailDepotDirection(tile);
tile += TileOffsByDiagDir(exitdir);
enterdir = ReverseDiagDir(exitdir);
break;
} else if (enterdir == GetRailDepotDirection(tile)) { // entered a depot
if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train);
continue;
} else {
continue;
@ -303,14 +300,14 @@ static SigFlags ExploreSegment(Owner owner)
if (tracks == TRACK_BIT_HORZ || tracks == TRACK_BIT_VERT) { // there is exactly one incidating track, no need to check
tracks = tracks_masked;
/* If no train detected yet, and there is not no train -> there is a train -> set the flag */
if (!(flags & SF_TRAIN) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags |= SF_TRAIN;
if (!flags.Test(SigFlag::Train) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags. Set(SigFlag::Train);
} else {
if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track
if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train);
}
/* Is this a track merge or split? */
if (!HasAtMostOneBit(tracks)) flags |= SF_SPLIT;
if (!HasAtMostOneBit(tracks)) flags.Set(SigFlag::Split);
if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile
Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too
@ -322,21 +319,21 @@ static SigFlags ExploreSegment(Owner owner)
* ANY conventional signal in REVERSE direction
* (if it is a presignal EXIT and it changes, it will be added to 'to-be-done' set later) */
if (HasSignalOnTrackdir(tile, reversedir)) {
if (IsPbsSignal(sig)) flags |= SF_PBS;
if (flags & SF_ENTER) flags |= SF_ENTER2;
flags |= SF_ENTER;
if (IsPbsSignal(sig)) flags.Set(SigFlag::Pbs);
if (flags.Test(SigFlag::Enter)) flags.Set(SigFlag::MultiEnter);
flags.Set(SigFlag::Enter);
if (!_tbuset.Add(tile, reversedir)) return flags | SF_FULL;
if (!_tbuset.Add(tile, reversedir)) return flags | SigFlag::Full;
}
if (HasSignalOnTrackdir(tile, trackdir) && !IsOnewaySignal(tile, track)) flags |= SF_PBS;
if (HasSignalOnTrackdir(tile, trackdir) && !IsOnewaySignal(tile, track)) flags.Set(SigFlag::Pbs);
/* if it is a presignal EXIT in OUR direction and we haven't found 2 green exits yes, do special check */
if (!(flags & SF_GREEN2) && IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit
if (flags & SF_EXIT) flags |= SF_EXIT2; // found two (or more) exits
flags |= SF_EXIT; // found at least one exit - allow for compiler optimizations
if (!flags.Test(SigFlag::MultiGreen) && IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit
if (flags.Test(SigFlag::Exit)) flags.Set(SigFlag::MultiExit); // found two (or more) exits
flags.Set(SigFlag::Exit); // found at least one exit - allow for compiler optimizations
if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN) { // found green presignal exit
if (flags & SF_GREEN) flags |= SF_GREEN2;
flags |= SF_GREEN;
if (flags.Test(SigFlag::Green)) flags.Set(SigFlag::MultiGreen);
flags.Set(SigFlag::Green);
}
}
@ -348,7 +345,7 @@ static SigFlags ExploreSegment(Owner owner)
if (dir != enterdir && (tracks & _enterdir_to_trackbits[dir])) { // any track incidating?
TileIndex newtile = tile + TileOffsByDiagDir(dir); // new tile to check
DiagDirection newdir = ReverseDiagDir(dir); // direction we are entering from
if (!MaybeAddToTodoSet(newtile, newdir, tile, dir)) return flags | SF_FULL;
if (!MaybeAddToTodoSet(newtile, newdir, tile, dir)) return flags | SigFlag::Full;
}
}
@ -361,7 +358,7 @@ static SigFlags ExploreSegment(Owner owner)
if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train);
tile += TileOffsByDiagDir(exitdir);
break;
@ -370,7 +367,7 @@ static SigFlags ExploreSegment(Owner owner)
if (GetTileOwner(tile) != owner) continue;
if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train);
tile += TileOffsByDiagDir(exitdir);
break;
@ -380,13 +377,13 @@ static SigFlags ExploreSegment(Owner owner)
DiagDirection dir = GetTunnelBridgeDirection(tile);
if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole
if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train);
enterdir = dir;
exitdir = ReverseDiagDir(dir);
tile += TileOffsByDiagDir(exitdir); // just skip to next tile
} else { // NOT incoming from the wormhole!
if (ReverseDiagDir(enterdir) != dir) continue;
if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
if (!flags.Test(SigFlag::Train) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags.Set(SigFlag::Train);
tile = GetOtherTunnelBridgeEnd(tile); // just skip to exit tile
enterdir = INVALID_DIAGDIR;
exitdir = INVALID_DIAGDIR;
@ -398,7 +395,7 @@ static SigFlags ExploreSegment(Owner owner)
continue; // continue the while() loop
}
if (!MaybeAddToTodoSet(tile, enterdir, oldtile, exitdir)) return flags | SF_FULL;
if (!MaybeAddToTodoSet(tile, enterdir, oldtile, exitdir)) return flags | SigFlag::Full;
}
return flags;
@ -426,25 +423,25 @@ static void UpdateSignalsAroundSegment(SigFlags flags)
if (IsPbsSignal(sig) && (GetRailReservationTrackBits(tile) & TrackToTrackBits(track)) != TRACK_BIT_NONE) continue;
/* determine whether the new state is red */
if (flags & SF_TRAIN) {
if (flags.Test(SigFlag::Train)) {
/* train in the segment */
newstate = SIGNAL_STATE_RED;
} else if (IsPbsSignal(sig) && (flags & (SF_SPLIT | SF_ENTER2))) {
} else if (IsPbsSignal(sig) && flags.Any({SigFlag::Split, SigFlag::MultiEnter})) {
/* Turn path signals red if the segment has a junction or more than one way in. */
newstate = SIGNAL_STATE_RED;
} else {
/* is it a bidir combo? - then do not count its other signal direction as exit */
if (sig == SIGTYPE_COMBO && HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
/* at least one more exit */
if ((flags & SF_EXIT2) &&
if (flags.Test(SigFlag::MultiExit) &&
/* no green exit */
(!(flags & SF_GREEN) ||
(!flags.Test(SigFlag::Green) ||
/* only one green exit, and it is this one - so all other exits are red */
(!(flags & SF_GREEN2) && GetSignalStateByTrackdir(tile, ReverseTrackdir(trackdir)) == SIGNAL_STATE_GREEN))) {
(!flags.Test(SigFlag::MultiGreen) && GetSignalStateByTrackdir(tile, ReverseTrackdir(trackdir)) == SIGNAL_STATE_GREEN))) {
newstate = SIGNAL_STATE_RED;
}
} else { // entry, at least one exit, no green exit
if (IsPresignalEntry(tile, TrackdirToTrack(trackdir)) && (flags & SF_EXIT) && !(flags & SF_GREEN)) newstate = SIGNAL_STATE_RED;
if (IsPresignalEntry(tile, TrackdirToTrack(trackdir)) && flags.Test(SigFlag::Exit) && !flags.Test(SigFlag::Green)) newstate = SIGNAL_STATE_RED;
}
}
@ -546,15 +543,15 @@ static SigSegState UpdateSignalsInBuffer(Owner owner)
if (first) {
first = false;
/* SIGSEG_FREE is set by default */
if (flags & SF_PBS) {
if (flags.Test(SigFlag::Pbs)) {
state = SIGSEG_PBS;
} else if ((flags & SF_TRAIN) || ((flags & SF_EXIT) && !(flags & SF_GREEN)) || (flags & SF_FULL)) {
} else if (flags.Test(SigFlag::Train) || (flags.Test(SigFlag::Exit) && !flags.Test(SigFlag::Green)) || flags.Test(SigFlag::Full)) {
state = SIGSEG_FULL;
}
}
/* do not do anything when some buffer was full */
if (flags & SF_FULL) {
if (flags.Test(SigFlag::Full)) {
ResetSets(); // free all sets
break;
}