11 Commits

Author SHA1 Message Date
bors[bot]
c1ce9df8ad Merge #19
19: Add a wrapper for `std::sync::Condvar` r=bertptrs a=bertptrs

This wrapper does not do any tracing itself but supports the use of a tracing mutex guard instead of an `std::sync` one.

Co-authored-by: Bert Peters <bert@bertptrs.nl>
2022-05-17 19:50:02 +00:00
312eaa8649 Add a wrapper for std::sync::Condvar
This wrapper does not do any tracing itself but supports the use of a
tracing mutex guard instead of an `std::sync` one.
2022-05-17 21:45:25 +02:00
bors[bot]
1f7e6921aa Merge #18
18: Enable bors for nicer merging r=bertptrs a=bertptrs



Co-authored-by: Bert Peters <bert@bertptrs.nl>
2022-05-15 21:40:40 +00:00
f7048f265f Enable CI builds on staging/trying 2022-05-15 23:35:00 +02:00
64e56fdb86 Add minimal bors config 2022-05-15 23:35:00 +02:00
9ea993e737 Add missing date 2022-05-07 18:15:50 +02:00
062850fc3e Merge pull request #16 from bertptrs/docsrs_feature_docs
Fix documentation builds for features
2022-05-07 17:56:09 +02:00
0d2622d5c6 Build documentation on CI 2022-05-07 17:52:32 +02:00
d1417e0b0c Tag module docs with their required features 2022-05-07 17:52:32 +02:00
fcc64e2cef Automatically build documentation for all features 2022-05-07 17:03:45 +02:00
fd0d05307c Update README and copyright year 2022-05-07 16:54:37 +02:00
8 changed files with 181 additions and 5 deletions

View File

@@ -2,12 +2,14 @@ on:
push: push:
branches: branches:
- master - master
- staging
- trying
pull_request: pull_request:
name: Continuous integration name: Continuous integration
jobs: jobs:
ci: tests:
name: Rust project name: Rust project
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
@@ -47,3 +49,22 @@ jobs:
with: with:
command: clippy command: clippy
args: --all-features --all-targets -- -D warnings args: --all-features --all-targets -- -D warnings
docs:
name: Documentation build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
- name: Build documentation
env:
# Build the docs like docs.rs builds it
RUSTDOCFLAGS: --cfg docsrs
run: cargo doc --all-features

View File

@@ -6,7 +6,17 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## [Unreleased]
## [0.2.0] ### Added
- Build [docs.rs] documentation with all features enabled for completeness.
- Add support for `std::sync::Condvar`
### Fixed
- The `parkinglot` module is now correctly enabled by the `parkinglot` feature rather than the
`lockapi` feature.
## [0.2.0] - 2022-05-07
### Added ### Added
- Generic support for wrapping mutexes that implement the traits provided by the - Generic support for wrapping mutexes that implement the traits provided by the
@@ -61,5 +71,6 @@ Initial release.
[0.1.1]: https://github.com/bertptrs/tracing-mutex/compare/v0.1.0...v0.1.1 [0.1.1]: https://github.com/bertptrs/tracing-mutex/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/bertptrs/tracing-mutex/releases/tag/v0.1.0 [0.1.0]: https://github.com/bertptrs/tracing-mutex/releases/tag/v0.1.0
[docs.rs]: https://docs.rs/tracing-mutex/latest/tracing_mutex/
[lock_api]: https://docs.rs/lock_api/ [lock_api]: https://docs.rs/lock_api/
[parking_lot]: https://docs.rs/parking_lot/ [parking_lot]: https://docs.rs/parking_lot/

View File

@@ -11,6 +11,12 @@ description = "Ensure deadlock-free mutexes by allocating in order, or else."
readme = "README.md" readme = "README.md"
repository = "https://github.com/bertptrs/tracing-mutex" repository = "https://github.com/bertptrs/tracing-mutex"
[package.metadata.docs.rs]
# Build docs for all features so the documentation is more complete
all-features = true
# Set custom cfg so we can enable docs.rs magic
rustdoc-args = ["--cfg", "docsrs"]
[dependencies] [dependencies]
lazy_static = "1" lazy_static = "1"
lock_api = { version = "0.4", optional = true } lock_api = { version = "0.4", optional = true }

View File

@@ -1,4 +1,4 @@
Copyright © 2021 Bert Peters Copyright © 2022 Bert Peters
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the “Software”), to deal in the Software without restriction, associated documentation files (the “Software”), to deal in the Software without restriction,

View File

@@ -34,7 +34,7 @@ Add this dependency to your `Cargo.lock` file like any other:
```toml ```toml
[dependencies] [dependencies]
tracing-mutex = "0.1" tracing-mutex = "0.2"
``` ```
Then use the locks provided by this library instead of the ones you would use otherwise. Then use the locks provided by this library instead of the ones you would use otherwise.

5
bors.toml Normal file
View File

@@ -0,0 +1,5 @@
status = [
'Rust project (stable)',
'Rust project (beta)',
'Documentation build',
]

View File

@@ -45,6 +45,7 @@
//! enabled, and to the underlying mutex when they're not. //! enabled, and to the underlying mutex when they're not.
//! //!
//! [paper]: https://whileydave.com/publications/pk07_jea/ //! [paper]: https://whileydave.com/publications/pk07_jea/
#![cfg_attr(docsrs, feature(doc_cfg))]
use std::cell::RefCell; use std::cell::RefCell;
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::fmt; use std::fmt;
@@ -61,16 +62,20 @@ use std::sync::PoisonError;
use lazy_static::lazy_static; use lazy_static::lazy_static;
#[cfg(feature = "lockapi")] #[cfg(feature = "lockapi")]
#[cfg_attr(docsrs, doc(cfg(feature = "lockapi")))]
pub use lock_api; pub use lock_api;
#[cfg(feature = "parkinglot")] #[cfg(feature = "parkinglot")]
#[cfg_attr(docsrs, doc(cfg(feature = "parkinglot")))]
pub use parking_lot; pub use parking_lot;
use crate::graph::DiGraph; use crate::graph::DiGraph;
mod graph; mod graph;
#[cfg(feature = "lockapi")] #[cfg(feature = "lockapi")]
#[cfg_attr(docsrs, doc(cfg(feature = "lockapi")))]
pub mod lockapi; pub mod lockapi;
#[cfg(feature = "lockapi")] #[cfg(feature = "parkinglot")]
#[cfg_attr(docsrs, doc(cfg(feature = "parkinglot")))]
pub mod parkinglot; pub mod parkinglot;
pub mod stdsync; pub mod stdsync;

View File

@@ -16,6 +16,7 @@
use std::fmt; use std::fmt;
use std::ops::Deref; use std::ops::Deref;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::sync::Condvar;
use std::sync::LockResult; use std::sync::LockResult;
use std::sync::Mutex; use std::sync::Mutex;
use std::sync::MutexGuard; use std::sync::MutexGuard;
@@ -27,6 +28,8 @@ use std::sync::RwLockReadGuard;
use std::sync::RwLockWriteGuard; use std::sync::RwLockWriteGuard;
use std::sync::TryLockError; use std::sync::TryLockError;
use std::sync::TryLockResult; use std::sync::TryLockResult;
use std::sync::WaitTimeoutResult;
use std::time::Duration;
use crate::BorrowedMutex; use crate::BorrowedMutex;
use crate::LazyMutexId; use crate::LazyMutexId;
@@ -48,6 +51,14 @@ pub type DebugMutexGuard<'a, T> = TracingMutexGuard<'a, T>;
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
pub type DebugMutexGuard<'a, T> = MutexGuard<'a, T>; pub type DebugMutexGuard<'a, T> = MutexGuard<'a, T>;
/// Debug-only `Condvar`
///
/// Type alias that accepts the mutex guard emitted from [`DebugMutex`].
#[cfg(debug_assertions)]
pub type DebugCondvar = TracingCondvar;
#[cfg(not(debug_assertions))]
pub type DebugCondvar = Condvar;
/// Debug-only tracing `RwLock`. /// Debug-only tracing `RwLock`.
/// ///
/// Type alias that resolves to [`TracingRwLock`] when debug assertions are enabled and to /// Type alias that resolves to [`TracingRwLock`] when debug assertions are enabled and to
@@ -214,6 +225,123 @@ impl<'a, T: fmt::Display> fmt::Display for TracingMutexGuard<'a, T> {
} }
} }
/// Wrapper around [`std::sync::Condvar`].
///
/// Allows `TracingMutexGuard` to be used with a `Condvar`. Unlike other structs in this module,
/// this wrapper does not add any additional dependency tracking or other overhead on top of the
/// primitive it wraps. All dependency tracking happens through the mutexes itself.
///
/// # Panics
///
/// This struct does not add any panics over the base implementation of `Condvar`, but panics due to
/// dependency tracking may poison associated mutexes.
///
/// # Examples
///
/// ```
/// use std::sync::Arc;
/// use std::thread;
///
/// use tracing_mutex::stdsync::{TracingCondvar, TracingMutex};
///
/// let pair = Arc::new((TracingMutex::new(false), TracingCondvar::new()));
/// let pair2 = Arc::clone(&pair);
///
/// // Spawn a thread that will unlock the condvar
/// thread::spawn(move || {
/// let (lock, condvar) = &*pair2;
/// *lock.lock().unwrap() = true;
/// condvar.notify_one();
/// });
///
/// // Wait until the thread unlocks the condvar
/// let (lock, condvar) = &*pair;
/// let guard = lock.lock().unwrap();
/// let guard = condvar.wait_while(guard, |started| !*started).unwrap();
///
/// // Guard should read true now
/// assert!(*guard);
/// ```
#[derive(Debug, Default)]
pub struct TracingCondvar(Condvar);
impl TracingCondvar {
/// Creates a new condition variable which is ready to be waited on and notified.
pub fn new() -> Self {
Default::default()
}
/// Wrapper for [`std::sync::Condvar::wait`].
pub fn wait<'a, T>(
&self,
guard: TracingMutexGuard<'a, T>,
) -> LockResult<TracingMutexGuard<'a, T>> {
let TracingMutexGuard { _mutex, inner } = guard;
map_lockresult(self.0.wait(inner), |inner| TracingMutexGuard {
_mutex,
inner,
})
}
/// Wrapper for [`std::sync::Condvar::wait_while`].
pub fn wait_while<'a, T, F>(
&self,
guard: TracingMutexGuard<'a, T>,
condition: F,
) -> LockResult<TracingMutexGuard<'a, T>>
where
F: FnMut(&mut T) -> bool,
{
let TracingMutexGuard { _mutex, inner } = guard;
map_lockresult(self.0.wait_while(inner, condition), |inner| {
TracingMutexGuard { _mutex, inner }
})
}
/// Wrapper for [`std::sync::Condvar::wait_timeout`].
pub fn wait_timeout<'a, T>(
&self,
guard: TracingMutexGuard<'a, T>,
dur: Duration,
) -> LockResult<(TracingMutexGuard<'a, T>, WaitTimeoutResult)> {
let TracingMutexGuard { _mutex, inner } = guard;
map_lockresult(self.0.wait_timeout(inner, dur), |(inner, result)| {
(TracingMutexGuard { _mutex, inner }, result)
})
}
/// Wrapper for [`std::sync::Condvar::wait_timeout_while`].
pub fn wait_timeout_while<'a, T, F>(
&self,
guard: TracingMutexGuard<'a, T>,
dur: Duration,
condition: F,
) -> LockResult<(TracingMutexGuard<'a, T>, WaitTimeoutResult)>
where
F: FnMut(&mut T) -> bool,
{
let TracingMutexGuard { _mutex, inner } = guard;
map_lockresult(
self.0.wait_timeout_while(inner, dur, condition),
|(inner, result)| (TracingMutexGuard { _mutex, inner }, result),
)
}
/// Wrapper for [`std::sync::Condvar::notify_one`].
pub fn notify_one(&self) {
self.0.notify_one();
}
/// Wrapper for [`std::sync::Condvar::notify_all`].
pub fn notify_all(&self) {
self.0.notify_all();
}
}
/// Wrapper for [`std::sync::RwLock`]. /// Wrapper for [`std::sync::RwLock`].
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct TracingRwLock<T> { pub struct TracingRwLock<T> {