Switcher behavior isn't atomic
See original GitHub issueBkCommonLib version: 1.12.2-v1
TrainCarts version: 1.12.1-v3-SNAPSHOT (#103)
Spigot version: 1.12.1
Problem or bug:
Switcher routing operations aren’t atomic. (I can’t decide if this is a bug, or a misunderstanding about the way switchers work and therefore a feature request - you be the judge!)
I have a pair of double junctions forming a branch line that leads to a station. The green line shows the paths northbound trains can take, and the blue line shows the paths southbound trains can take (please forgive the amateurish Paint job):
Northbound trains that serve the station are tagged stationN
; southbound trains that serve the station are tagged stationS
. I’ve implemented this using switchers and waiters as follows (red = waiter, yellow = switcher, orange = waiter above a switcher):
Northern junction:
Southern junction:
This setup works most of the time, but falls apart when two trains approach a switcher at the same time: here’s an example of it happening with a northbound train on the branch line and a southbound train on the main line. From what I understand, here’s what happens:
- The northbound train arrives at the 5-block waiter on the branch line, looks 5 rails ahead and sees them all clear. The train proceeds.
- The southbound train arrives at the 5-block waiter on the main line, looks 5 rails ahead and sees them all clear (because the northbound train hasn’t reached the switcher yet). The train proceeds.
- The northbound train arrives at the switcher. The logic causes the rail to switch to west-east position.
- The southbound train arrives at the switcher. The logic causes the rail to switch to north-south position.
- The northbound train, which is still passing over the switcher, splits; the back half of the train gets taken southbound down the main line.
The problem gets compounded further down the line: trains end up colliding and switching onto opposing rails, leading to a (literal) trainwreck requiring manual cleanup.
Expected behaviour:
This could (I think) be solved in one of two ways:
- Making switcher operations atomic: a train can’t pass over a switcher if another train is already being routed by it. Ideally, trains would be placed in a queue in the order in which they arrived at the switcher, would be stopped on the rail before the switcher awaiting their turn to proceed, and would then automatically proceed when allowed. (Maybe it’d be too much to retrofit this into a switcher, and a new sign type would be needed.)
- Having a way of defining a mutual exclusion zone for an arbitrary area of track: only one train can enter the mutual exclusion zone at a time, the others being queued in the same way as described above. Perhaps there could also be a way of defining priorities for trains approaching from certain directions, so (for instance) main line traffic always gets right of way over branch line traffic. I tried doing this with detectors, but there’s just not enough track space to fit in all the signs, and it wouldn’t solve the queueing problem so there’s the possibility that the same problem might still occur.
The second option seems like the most practical from the point of view of me, a user - I could define the following three mutual exclusion zones which (I think) would solve my problem:
Perhaps you, the developers, feel differently… 😃
Steps to reproduce:
Hopefully the screenshots above are sufficient for understanding how the problem can be reproduced; it’s always reproducible, given enough time for two trains to arrive at a switcher simultaneously. If not, let me know and I’ll give you access to a private server that demonstrates the problem.
Issue Analytics
- State:
- Created 6 years ago
- Comments:7 (4 by maintainers)
Top GitHub Comments
Well it took some time but I’ve gotten a first version of this ready. Went with the obvious and called it a mutex. You can define cuboid regions and ensure mutual exclusion: only one train can be in that zone at one time, new trains trying to enter will be blocked. It still has a few minor flaws to it (the obvious one being deadlocks with more than one mutex-), but for a first version it will do nicely.
https://puu.sh/xXWcL/8389881154.mp4
https://ci.mg-dev.eu/job/TrainCarts/143/
Deadlocks are tricky, and to fix that sort of stuff I will need to roll out a more advanced system. Covering multiple intersects with a single mutex solves all deadlock issues (just like actual mutexes do). If I replace the scene in the video with 4 mutex signs underneath the crossings, deadlocks happen quite quickly.
I never expected to see broken mutexes in train form! I understand the issue and I’d say it should be labeled a bug. This is the main reason waiter signs exist in the first place.