mongodb/mongo
Executors, futures, and batons
Asynchronous work in MongoDB is built on a small set of primitives: Future<T>, Promise<T>, TaskExecutor, Baton, and the connection pool. They are used to express I/O, parallel fan-out (AsyncRequestsSender), and most background work in the server.
Futures and promises
src/mongo/util/future.h defines:
Future<T>— read end of an async result. Continuations attached with.then(),.onError(),.onCompletion()run on whichever executor completes the future, or on the executor passed to.thenRunOn(e).Promise<T>— write end. SettingsetValue/setErrorresolves the future.SemiFuture<T>— likeFuture, but with no implicit executor. Continuations must be explicit about where they run. Used for inter-component boundaries.SharedSemiFuture<T>— multi-consumer variant.
The full design rationale is in docs/futures_and_promises.md. The MongoDB types do not match std::future — they are non-blocking, support continuation chaining, and are zero-allocation in the common case.
SemiFuture<BSONObj> findDoc(OperationContext* opCtx);
findDoc(opCtx)
.thenRunOn(executor)
.then([](BSONObj doc) {
// do something with doc on `executor`
return processDoc(doc);
})
.onError([](Status s) {
return Status(ErrorCodes::InternalError, "lookup failed: " + s.reason());
});Task executors
src/mongo/executor/ defines:
| Type | Role |
|---|---|
TaskExecutor |
Abstract base. Schedules work, runs network ops via a NetworkInterface. |
ThreadPoolTaskExecutor |
The default impl. Backed by a ThreadPool and a NetworkInterface. |
NetworkInterfaceASIO / NetworkInterfaceTL |
ASIO-based outbound network drivers used by the executor. |
ConnectionPool |
Pools outbound TCP/TLS connections to other servers, reused across operations. |
RemoteCommandRequest / RemoteCommandResponse |
The unit of an outbound command sent through a TaskExecutor. |
PinnedConnectionTaskExecutor |
A wrapper that pins all work to a single connection. Used for some sharding fan-outs. |
Each major subsystem allocates its own executor instances (or shares a pool). Examples:
- Sharding has the TaskExecutorPool (
src/mongo/s/sharding_task_executor_pool*) — a fan-out of executors used bymongosand shards. - Replication uses dedicated executors for the syncer (
src/mongo/db/repl/) and the rollback machinery. - Background services schedule on the global
PeriodicRunner(src/mongo/util/periodic_runner.h).
Batons
A baton is a lightweight, single-thread-bound work queue. It lets a thread "drop into" a wait, run scheduled continuations on its own context while waiting, and resume once the wait completes. The design is in docs/baton.md. Batons are owned by OperationContext and used heavily in the transport layer to keep request handling on the originating thread.
opCtx->getBaton()->schedule([] (Status s) {
// runs on the opCtx's owning thread
});Periodic runner
src/mongo/util/periodic_runner.h is a process-wide registry of "periodic jobs" — closures invoked on a timer. The TTL monitor, FTDC collector, and many cluster-parameter refreshers are scheduled here.
Thread pools
src/mongo/util/concurrency/thread_pool.h implements a generic thread pool. The ThreadPoolTaskExecutor adapts it to the TaskExecutor interface. Pool sizes are tunable via server parameters such as taskExecutorPoolSize.
Connection pool
The egress connection pool (src/mongo/executor/connection_pool*) maintains warm connections to other servers. It's controlled by:
ConnectionPool::Options— min/max pool size, refresh interval, host timeout.- The
shardingTaskExecutorPoolMaxSize,shardingTaskExecutorPoolMaxConnecting, and similar server parameters.
Error handling
- A continuation that throws turns the result into an error future automatically.
- Network errors propagate as
Statuscodes from theErrorCodes::NetworkTimeout/HostUnreachablefamily. - The
OperationContextcarries cancellation;opCtx->getCancellationToken()can be passed into futures so they cancel when the operation is killed.
Key source files
| File | Purpose |
|---|---|
src/mongo/util/future.h / future_impl.h |
The Future/Promise family. |
src/mongo/util/baton.h / default_baton.cpp |
Single-thread work queues. |
src/mongo/executor/task_executor.h |
Abstract TaskExecutor. |
src/mongo/executor/thread_pool_task_executor.cpp |
The default thread-pool-backed executor. |
src/mongo/executor/network_interface_tl.cpp |
The transport-layer-backed network interface. |
src/mongo/executor/connection_pool.cpp |
Egress connection pool. |
src/mongo/util/periodic_runner.h |
Timer-driven periodic work. |
src/mongo/util/concurrency/thread_pool.h |
Generic thread pool. |
Integration points
- The transport layer hands incoming work to the SEP and exposes the egress reactor.
- The shard role and replication systems use task executors heavily.
- The aggregation pipeline uses futures for
$lookupand$unionWithcross-collection work.
Entry points for modification
Most code that needs to do work asynchronously should use an existing executor. Adding a new pool is rare; a new periodic job is a one-line registration with PeriodicRunner. When debugging starvation or stalls, check the connection pool stats from connPoolStats and the taskExecutorPool section of serverStatus.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.