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