- JobserverExecutor can own a default-constructed Jobserver: passing no
argument creates and manages one automatically; shutdown(wait=True)
closes it. This makes JobserverExecutor very drop-in for other code.
- O(k) slot acquisition: _obtain_tokens() reuses a persistent
DefaultSelector registered once per Jobserver rather than per call,
reducing per-submission overhead at scale.
- Removed callbacks keyword from Jobserver.submit() because of above
algorithmic improvement.
- preexec_fn may return a context manager: the child function runs inside
it via ExitStack, enabling entry/exit semantics around each job.
- Jobserver.__exit__ warns on suppressed CallbackRaised: a RuntimeWarning
is emitted when __exit__ silences a CallbackRaised.
- ResourceWarning on unclosed Jobserver: __del__ emits a ResourceWarning
when an open instance is garbage-collected without being closed.
- Nesting examples generalised to all multiprocessing start methods:
ex02_nested.py now covers fork, forkserver, and spawn.