Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a note comparing against std types #58

Merged
merged 8 commits into from
Nov 14, 2023
Merged

Add a note comparing against std types #58

merged 8 commits into from
Nov 14, 2023

Conversation

notgull
Copy link
Member

@notgull notgull commented Sep 23, 2023

Closes #57

Signed-off-by: John Nunley <dev@notgull.net>
@taiki-e
Copy link
Collaborator

taiki-e commented Sep 23, 2023

async-lock will actually just use std::sync::Mutex under the hood if the std feature is enabled

For Mutex, the lock fast path is a single CAS. event-listener used in slow path uses std mutex internally, but it would be different from "just use std::sync::Mutex under the hood".

async-lock/src/mutex.rs

Lines 358 to 360 in 604d461

if this.acquire_slow.is_none() {
match this.mutex.try_lock() {
Some(guard) => return Poll::Ready(guard),

async-lock/src/mutex.rs

Lines 160 to 166 in 604d461

pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
if self
.state
.compare_exchange(0, 1, Ordering::Acquire, Ordering::Acquire)
.is_ok()
{
Some(MutexGuard(self))

Signed-off-by: John Nunley <dev@notgull.net>
@notgull
Copy link
Member Author

notgull commented Sep 24, 2023

For Mutex, the lock fast path is a single CAS. event-listener used in slow path uses std mutex internally, but it would be different from "just use std::sync::Mutex under the hood".

Good point, I've clarified this by saying that it's part of the notification mechanism.

@notgull notgull requested a review from taiki-e October 8, 2023 03:46
src/lib.rs Outdated
//!
//! ## Relationship with `std::sync`
//!
//! In general, you should prefer to use [`std::sync`] types over types from this crate.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should

Personally, I do not believe that the benefits of using std::sync or parking_lot here necessarily exceed the risk of accidentally holding the guard across the await point.

Especially when using parking_lot, it is easy to make that mistake because of the send guard. (I recently saw a colleague make that mistake and spend hours debugging.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I do not believe that the benefits of using std::sync or parking_lot here necessarily exceed the risk of accidentally holding the guard across the await point.

For standard library mutexes, there is a Clippy lint nowadays that prevents this scenario from happening. I've made the language less impactful, but I still think this isn't as large of an issue

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, I've added this

src/lib.rs Outdated Show resolved Hide resolved
notgull and others added 3 commits November 12, 2023 16:26
Co-authored-by: Jules Bertholet <julesbertholet@quoi.xyz>
Signed-off-by: John Nunley <dev@notgull.net>
Signed-off-by: John Nunley <dev@notgull.net>
src/lib.rs Outdated
Comment on lines 26 to 29
//! When using [`std::sync`], you should be careful to not hold any locks over an `.await` point.
//! In modern Rust, there is a Clippy lint called [`await_holding_lock`] that emits warnings for this
//! scenario for [`std::sync`] and some other synchronization crates. Still, when deciding to use
//! [`std::sync`] over `async-lock`, you must be careful to not hold any locks past an `.await` point.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is quite repetitive, I think we can have something much shorter. For example, you could extend the sentence on line 19 to If you already use libstd and you aren't holding locks across await points (there is a [Clippy lint](link) to check for this), you should consider std::sync instead of this crate.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amended this

@Jules-Bertholet
Copy link
Collaborator

tokio::sync have their own version of this notice, which may provide inspiration.

notgull and others added 2 commits November 13, 2023 18:01
Co-authored-by: Jules Bertholet <julesbertholet@quoi.xyz>
Signed-off-by: John Nunley <dev@notgull.net>
src/lib.rs Outdated Show resolved Hide resolved
Signed-off-by: John Nunley <dev@notgull.net>
@notgull notgull merged commit 48c091e into master Nov 14, 2023
8 checks passed
@notgull notgull deleted the notgull/std-note branch November 14, 2023 02:42
@notgull notgull mentioned this pull request Nov 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Add note explaining when you should use std locks instead of async locks
3 participants