Specifically, `Cancel()` calls were not thread safe. Due to a series of
events, `ListPollingComponent` could call `Cancel` from a non-update
thread, leading to a race condition where both a `Success` and `Fail`
event can be fired.
This is intended to be the simplest fix possible, locking and guarding
specifically on the callbacks. Further work could be done in the future
to improve the flow surrounding `pendingFailure`, potentially reducing
redundant work and cleaning up the code, but that's not happening here.
Closes https://github.com/ppy/osu/issues/13632.
"Property testing" is heavily used, tests that generates random cases and asserting properties.
That gives high confidence of round-trip correctness of `SliderPath` conversion, for example.
A `JuiceStream` holds a legacy `SliderPath` as the representation of the path.
However, the `SliderPath` representation is difficult to work with because `SliderPath` works in 2D position, while osu!catch works in `(time, x)` coordinates.
This `JuiceStreamPath` represents the path in a more convenient way, a polyline connecting list of `(distance, x)` vertices.