From 88212ab64afd2b2f87deeb073f9eef6aaaad3701 Mon Sep 17 00:00:00 2001 From: cong-or Date: Thu, 16 Jul 2026 08:43:52 +0100 Subject: [PATCH] sync: document memory ordering guarantees for Semaphore (#8119) --- tokio/src/sync/semaphore.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tokio/src/sync/semaphore.rs b/tokio/src/sync/semaphore.rs index 8af5b54e8..8b23aa396 100644 --- a/tokio/src/sync/semaphore.rs +++ b/tokio/src/sync/semaphore.rs @@ -26,6 +26,35 @@ use std::sync::Arc; /// To use the `Semaphore` in a poll function, you can use the [`PollSemaphore`] /// utility. /// +/// # Memory ordering +/// +/// If a task writes some data and then releases a permit, any task that later +/// acquires a permit is guaranteed to see that data. This makes it safe to use +/// a semaphore to hand data off between tasks through shared state. +/// +/// Stated more precisely in terms of atomic memory orderings: acquiring a +/// permit (via [`acquire`], [`acquire_many`], [`try_acquire`], +/// [`try_acquire_many`], or their `_owned` variants), releasing permits (by +/// dropping a [`SemaphorePermit`] or [`OwnedSemaphorePermit`], or by calling +/// [`add_permits`] or [`forget_permits`]), and closing the semaphore (via +/// [`close`]) are all `AcqRel` operations. They are totally ordered, and each +/// one synchronizes-with all such operations that precede it, giving the same +/// guarantees as `AcqRel` operations on a single atomic. +/// +/// A failed acquisition attempt (including [`TryAcquireError::NoPermits`] and +/// [`TryAcquireError::Closed`]), along with the [`available_permits`] and +/// [`is_closed`] methods, behave like an `Acquire` load. +/// +/// [`acquire`]: Semaphore::acquire +/// [`acquire_many`]: Semaphore::acquire_many +/// [`try_acquire`]: Semaphore::try_acquire +/// [`try_acquire_many`]: Semaphore::try_acquire_many +/// [`add_permits`]: Semaphore::add_permits +/// [`forget_permits`]: Semaphore::forget_permits +/// [`close`]: Semaphore::close +/// [`available_permits`]: Semaphore::available_permits +/// [`is_closed`]: Semaphore::is_closed +/// /// # Examples /// /// Basic usage: