Add proper support for using elapsed() inside watchers.

One can now do things like schedule functions to execute in the future with:

@watch(lambda: elapsed(time=...))
def _(result):
    if result:
        ...

but note that using elapsed(seconds=...) inside of a watcher will result in weird behavior, so don't do it.
Only take elapsed(time=...) calls into account when re-running watches. This isn't exactly the most intuitive way of doing it, but it's the best I've come up with under the circumstances.
Write _PipeWaiter, an efficient alternative to _ThreadWaiter, and use it by default on Linux. I've done some tests on it and it appears to work flawlessly.