command: add infrastructure for async commands

This enables two types of command behavior:

1. Plain async behavior, like "loadfile" not completing until the file
   is fully loaded.
2. Running parts of the command on worker threads, e.g. for I/O, such as
   "sub-add" doing network accesses on a thread while the core
   continues.

Both have no implementation yet, and most new code is actually inactive.
The plan is to implement a number of useful cases in the following
commits.

The most tricky part is handling internal keybindings (input.conf) and
the multi-command feature (concatenating commands with ";"). It requires
a bunch of roundabout code to make it do the expected thing in
combination with async commands.

There is the question how commands should be handled that come in at a
higher rate than what can be handled by the core. Currently, it will
simply queue up input.conf commands as long as memory lasts. The client
API is limited by the size of the reply queue per client. For commands
which require a worker thread, the thread pool is limited to 30 threads,
and then will queue up work in memory. The number is completely
arbitrary.
This commit is contained in:
wm4
2018-05-06 18:27:18 +02:00
parent a1ed1f8be0
commit b440f6dfb3
10 changed files with 329 additions and 47 deletions

View File

@@ -870,11 +870,45 @@ prefixes can be specified. They are separated by whitespace.
are asynchronous by default (or rather, their effects might manifest
after completion of the command). The semantics of this flag might change
in the future. Set it only if you don't rely on the effects of this command
being fully realized when it returns.
being fully realized when it returns. See `Synchronous vs. Asynchronous`_.
``sync``
Allow synchronous execution (if possible). Normally, all commands are
synchronous by default, but some are asynchronous by default for
compatibility with older behavior.
All of the osd prefixes are still overridden by the global ``--osd-level``
settings.
Synchronous vs. Asynchronous
----------------------------
The ``async`` and ``sync`` prefix matter only for how the issuer of the command
waits on the completion of the command. Normally it does not affect how the
command behaves by itself. There are the following cases:
- Normal input.conf commands are always run asynchronously. Slow running
commands are queued up or run in parallel.
- "Multi" input.conf commands (1 key binding, concatenated with ``;``) will be
executed in order, except for commands that are async (either prefixed with
``async``, or async by default for some commands). The async commands are
run in a detached manner, possibly in parallel to the remaining sync commands
in the list.
- Normal Lua and libmpv commands (e.g. ``mpv_command()``) are run in a blocking
manner, unless the ``async`` prefix is used, or the command is async by
default. This means in the sync case the caller will block, even if the core
continues playback. Async mode runs the command in a detached manner.
- Async libmpv command API (e.g. ``mpv_command_async()``) never blocks the
caller, and always notify their completion with a message. The ``sync`` and
``async`` prefixes make no difference.
- In all cases, async mode can still run commands in a synchronous manner, even
in detached mode. This can for example happen in cases when a command does not
have an asynchronous implementation. The async libmpv API still never blocks
the caller in these cases.
The only exception is the current legacy behavior with screenshot commands,
which will be fixed later. Using the ``async`` prefix makes them run the file
saving code in a detached manner.
Input Sections
--------------