ts/Task: return a future for state transitions

State transitions request functions hid the synchronization
details to the caller:

- If the transition was requested from a Context, a subtask was
  added or the transition ack was not awaited if the new transition
  was requested from a running transition or an iteration function.
- If the transition was not requested from a Context, current
  thread was blocked until the ack was received.

This strategy facilitated code in elements, but it suffered from
the following shortcomings:

- The `prepare` transition request didn't comply with the above
  strategy and would always return an `Async` form. This was
  designed to accomodate the `Prepare` function for elements
  such as `ts-tcpclientsrc` which takes times due to the
  TCP socket connection delays. The idea was that the actual
  transition result would be available after calling `start`.
  This was a disadvantage for elements which would prefer to
  error immediately in the event of a preparation failure.
- Hidding the transition request synchronization to the caller
  meant that they had no options but relying on the internal
  mechanism. E.g.: it was not possible to `start` from another
  async runtime without blocking. Also it was not possible
  to request a transition and choose not to await for the
  ack.

This commit introduces a more flexible API for state
transitions requests:

- The transition request function now return a `TransitionStatus`,
  which is a Future.
- When an error occurs immediately (e.g. the transition
  request is not autorized due to current state of the Task),
  the `TransitionStatus` is resolved immediately and can be
  `check`ed for errors. This is useful for functions such as
  `pepare` in the case of `ts-tcpclientsrc` (see above).
  This is also useful for `pause`, because in current design,
  the transition is always async. Note however, that `pause` is
  forseen to adhere to the same behaviour as the other transition
  requests in the near future [1].
- If the caller chooses to await for the ack and they don't know
  if they are running on a ts Context (e.g. in `Pad{Src,Sink}`
  handlers), they can call `await_maybe_on_context`. This is mostly
  the same behaviour as the one that used to be performed internaly.
- If the caller knows for sure they can't possibly block an async
  executor, they can call `block_on` which is more explicite, but
  will nonetheless make sure no ts Context is being blocked. This
  last check was introduced as it was considered low overhead
  while it should ease preventing missues in cases where the above
  functions should be used.

[1]: https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/793#note_1464400
This commit is contained in:
François Laignel 2022-08-03 17:07:28 +02:00
parent 625fce3934
commit d4061774a4

File diff suppressed because it is too large Load diff