Asynchronous pin release 2026-11-05
Asynchronous pin release ends the address-stability guarantee for a pinned memory object after an operation that can continue beyond its submission call. Its central condition is that no unfinished consumer may still access the pinned address. Returning from submission is sufficient only when the operation's contract says that all access has ended. Microsoft's asynchronous native-call example stores the pin handle in callback state and disposes it during completion cleanup.[ref]
For an original event sequence, suppose an operation acquires a pin at0ms, submits at1ms, returns a pending result at2ms and finishes its last access at8ms. Completion cleanup at8ms can end the pinning lifetime; cleanup at2ms cannot. If a request to stop arrives at3ms but the operation acknowledges completion only at6ms, the request alone does not authorize release at3ms. The actual access contract, rather than the desired outcome, determines when the address may change.
An implementation needs a single owner for cleanup across all completion paths. Submission might fail before any callback is promised, complete immediately, or complete later. Each path must transfer or retain the cleanup responsibility consistently. The exactly-once pin cleanup requirement avoids both leaking a pin and releasing the same handle twice. The primary Microsoft example explicitly cleans up an exception before a callback can be invoked, and funnels immediate and deferred completion through a completion routine.[ref]
With overlapping users, releasing one operation's interest does not establish that every user has finished. A reference counting protocol can track outstanding access leases, provided starting new work and deciding that the last lease ended are synchronized. An observed zero count without protection against a simultaneous new user is not sufficient. A mutex or another appropriate synchronization mechanism can protect that transition.
The completion signal must itself describe the end of access. Microsoft's task-based buffer rule forbids a consumer from continuing to use the memory after the returned task reaches a terminal state.[ref] An API that reports cancellation before its underlying user has stopped requires another completion guarantee before pin cleanup. Retaining the pin protects the address; it does not by itself prevent concurrent data races or determine who may reuse the buffer.
Exactly-once pin cleanup 2026-11-05
Exactly-once pin cleanup gives one owner responsibility for ending a particular pinning lifetime, despite several possible completion paths. The resource must remain pinned until its consumers finish, and its cleanup must occur once after that condition is met. This combines the safety requirement of asynchronous pin release with a liveness requirement: a pin left permanently owned by nobody can obstruct later memory compaction.
A useful state machine has states “submission in progress”, “completion pending” and “released”. A submission error that guarantees no future consumer can access the address may take the first state directly to released. A pending result transfers cleanup responsibility to a completion path. Immediate completion must follow the API's stated rule about whether a callback will also arrive; it must not independently trigger two owners to dispose of the same handle. Microsoft's native-call example explicitly handles submission exceptions and funnels immediate or deferred completion into cleanup.[ref]
For an original race example, suppose a completion callback and an error-reporting path can both observe an operation as finished. A plain sequence “test flag; if clear, set flag; release pin” can race: both callers read clear before either writes set, and both release. A synchronized ownership claim, using a mutex or an appropriate compare-and-swap transition, can ensure that only one caller changes pending to released. The losing caller performs no cleanup. This is a schematic ownership protocol, not a claim that every pin API tolerates arbitrary racing callbacks.
For a count of releases on one acquired handle, the at-most-once condition is . The requirement that cleanup eventually occurs after all promised access has ended supplies at final completion, so together they give . A one-time flag alone establishes neither the end of access nor eventual execution of the winning path.
The operation's state must also stay alive while any callback can inspect it. Reference counting can protect that state independently of the pin being released. Marking a handle released does not permit another caller to access freed callback state. Keeping resource ownership, callback-state lifetime and data synchronization separate makes the protocol easier to verify. The primary task-based memory rule similarly requires all consumer access to finish by task termination.[ref]