Skip to content

Commit 1962cf1

Browse files
author
Stjepan Glavina
committed
Bump to v2.0.0
1 parent e70eb96 commit 1962cf1

File tree

6 files changed

+19
-348
lines changed

6 files changed

+19
-348
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Version 2.0.0
2+
3+
- Only re-export `async-mutex` and `async-rwlock`.
4+
15
# Version 1.1.5
26

37
- Replace the implementation with `async-mutex`.

Cargo.toml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "async-lock"
3-
version = "1.1.5"
3+
version = "2.0.0"
44
authors = ["Stjepan Glavina <stjepang@gmail.com>"]
55
edition = "2018"
66
description = "Reference-counted async lock"
@@ -14,7 +14,4 @@ readme = "README.md"
1414

1515
[dependencies]
1616
async-mutex = "1.1.5"
17-
18-
[dev-dependencies]
19-
smol = "0.1.18"
20-
futures = "0.3.5"
17+
async-rwlock = "1.0.1"

README.md

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,12 @@ https://crates.io/crates/async-lock)
99
[![Documentation](https://docs.rs/async-lock/badge.svg)](
1010
https://docs.rs/async-lock)
1111

12-
Reference-counted async lock.
12+
Async locking primitives.
1313

14-
The `Lock` type is similar to `std::sync::Mutex`, except locking is an async operation.
14+
This crate provides two primitives:
1515

16-
Note that `Lock` by itself acts like an `Arc` in the sense that cloning it returns just
17-
another reference to the same lock.
18-
19-
Furthermore, `LockGuard` is not tied to `Lock` by a lifetime, so you can keep guards for
20-
as long as you want. This is useful when you want to spawn a task and move a guard into its
21-
future.
22-
23-
The locking mechanism uses eventual fairness to ensure locking will be fair on average without
24-
sacrificing performance. This is done by forcing a fair lock whenever a lock operation is
25-
starved for longer than 0.5 milliseconds.
26-
27-
## Examples
28-
29-
```rust
30-
use async_lock::Lock;
31-
use smol::Task;
32-
33-
let lock = Lock::new(0);
34-
let mut tasks = vec![];
35-
36-
for _ in 0..10 {
37-
let lock = lock.clone();
38-
tasks.push(Task::spawn(async move { *lock.lock().await += 1 }));
39-
}
40-
41-
for task in tasks {
42-
task.await;
43-
}
44-
assert_eq!(*lock.lock().await, 10);
45-
```
16+
* `Mutex` - a mutual exclusion lock.
17+
* `RwLock` - a reader-writer lock, allowing any number of readers or a single writer.
4618

4719
## License
4820

examples/fairness.rs

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/lib.rs

Lines changed: 9 additions & 220 deletions
Original file line numberDiff line numberDiff line change
@@ -1,225 +1,14 @@
1-
//! Reference-counted async lock.
1+
//! Async locking primitives.
22
//!
3-
//! The [`Lock`] type is similar to [`std::sync::Mutex`], except locking is an async operation.
3+
//! This crate provides two primitives:
44
//!
5-
//! Note that [`Lock`] by itself acts like an [`Arc`] in the sense that cloning it returns just
6-
//! another reference to the same lock.
7-
//!
8-
//! Furthermore, [`LockGuard`] is not tied to [`Lock`] by a lifetime, so you can keep guards for
9-
//! as long as you want. This is useful when you want to spawn a task and move a guard into its
10-
//! future.
11-
//!
12-
//! The locking mechanism uses eventual fairness to ensure locking will be fair on average without
13-
//! sacrificing performance. This is done by forcing a fair lock whenever a lock operation is
14-
//! starved for longer than 0.5 milliseconds.
15-
//!
16-
//! # Examples
17-
//!
18-
//! ```
19-
//! # smol::run(async {
20-
//! use async_lock::Lock;
21-
//! use smol::Task;
22-
//!
23-
//! let lock = Lock::new(0);
24-
//! let mut tasks = vec![];
25-
//!
26-
//! for _ in 0..10 {
27-
//! let lock = lock.clone();
28-
//! tasks.push(Task::spawn(async move { *lock.lock().await += 1 }));
29-
//! }
30-
//!
31-
//! for task in tasks {
32-
//! task.await;
33-
//! }
34-
//! assert_eq!(*lock.lock().await, 10);
35-
//! # })
36-
//! ```
5+
//! * [`Mutex`] - a mutual exclusion lock.
6+
//! * [`RwLock`] - a reader-writer lock, allowing any number of readers or a single writer.
377
388
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
399

40-
use std::cell::UnsafeCell;
41-
use std::fmt;
42-
use std::mem;
43-
use std::ops::{Deref, DerefMut};
44-
use std::sync::Arc;
45-
46-
use async_mutex::{Mutex, MutexGuard};
47-
48-
/// An async lock.
49-
pub struct Lock<T>(Arc<Inner<T>>);
50-
51-
unsafe impl<T: Send> Send for Lock<T> {}
52-
unsafe impl<T: Send> Sync for Lock<T> {}
53-
54-
impl<T> Clone for Lock<T> {
55-
fn clone(&self) -> Lock<T> {
56-
Lock(self.0.clone())
57-
}
58-
}
59-
60-
/// Data inside [`Lock`].
61-
struct Inner<T> {
62-
/// The inner mutex.
63-
mutex: Mutex<()>,
64-
65-
/// The value inside the lock.
66-
data: UnsafeCell<T>,
67-
}
68-
69-
unsafe impl<T: Send> Send for Inner<T> {}
70-
unsafe impl<T: Send> Sync for Inner<T> {}
71-
72-
impl<T> Lock<T> {
73-
/// Creates a new async lock.
74-
///
75-
/// # Examples
76-
///
77-
/// ```
78-
/// use async_lock::Lock;
79-
///
80-
/// let lock = Lock::new(0);
81-
/// ```
82-
pub fn new(data: T) -> Lock<T> {
83-
Lock(Arc::new(Inner {
84-
mutex: Mutex::new(()),
85-
data: UnsafeCell::new(data),
86-
}))
87-
}
88-
89-
/// Acquires the lock.
90-
///
91-
/// Returns a guard that releases the lock when dropped.
92-
///
93-
/// # Examples
94-
///
95-
/// ```
96-
/// # smol::block_on(async {
97-
/// use async_lock::Lock;
98-
///
99-
/// let lock = Lock::new(10);
100-
/// let guard = lock.lock().await;
101-
/// assert_eq!(*guard, 10);
102-
/// # })
103-
/// ```
104-
#[inline]
105-
pub async fn lock(&self) -> LockGuard<T> {
106-
LockGuard::new(self.clone(), self.0.mutex.lock().await)
107-
}
108-
109-
/// Attempts to acquire the lock.
110-
///
111-
/// If the lock could not be acquired at this time, then [`None`] is returned. Otherwise, a
112-
/// guard is returned that releases the lock when dropped.
113-
///
114-
/// # Examples
115-
///
116-
/// ```
117-
/// use async_lock::Lock;
118-
///
119-
/// let lock = Lock::new(10);
120-
/// if let Some(guard) = lock.try_lock() {
121-
/// assert_eq!(*guard, 10);
122-
/// }
123-
/// # ;
124-
/// ```
125-
#[inline]
126-
pub fn try_lock(&self) -> Option<LockGuard<T>> {
127-
self.0
128-
.mutex
129-
.try_lock()
130-
.map(|guard| LockGuard::new(self.clone(), guard))
131-
}
132-
}
133-
134-
impl<T: fmt::Debug> fmt::Debug for Lock<T> {
135-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136-
struct Locked;
137-
impl fmt::Debug for Locked {
138-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139-
f.write_str("<locked>")
140-
}
141-
}
142-
143-
match self.try_lock() {
144-
None => f.debug_struct("Lock").field("data", &Locked).finish(),
145-
Some(guard) => f.debug_struct("Lock").field("data", &&*guard).finish(),
146-
}
147-
}
148-
}
149-
150-
impl<T> From<T> for Lock<T> {
151-
fn from(val: T) -> Lock<T> {
152-
Lock::new(val)
153-
}
154-
}
155-
156-
impl<T: Default> Default for Lock<T> {
157-
fn default() -> Lock<T> {
158-
Lock::new(Default::default())
159-
}
160-
}
161-
162-
/// A guard that releases the lock when dropped.
163-
pub struct LockGuard<T>(Lock<T>, MutexGuard<'static, ()>);
164-
165-
unsafe impl<T: Send> Send for LockGuard<T> {}
166-
unsafe impl<T: Sync> Sync for LockGuard<T> {}
167-
168-
impl<T> LockGuard<T> {
169-
fn new(lock: Lock<T>, inner: MutexGuard<'_, ()>) -> LockGuard<T> {
170-
let inner = unsafe { mem::transmute::<MutexGuard<'_, ()>, MutexGuard<'static, ()>>(inner) };
171-
LockGuard(lock, inner)
172-
}
173-
174-
/// Returns a reference to the lock a guard came from.
175-
///
176-
/// # Examples
177-
///
178-
/// ```
179-
/// # smol::block_on(async {
180-
/// use async_lock::{Lock, LockGuard};
181-
///
182-
/// let lock = Lock::new(10i32);
183-
/// let guard = lock.lock().await;
184-
/// dbg!(LockGuard::source(&guard));
185-
/// # })
186-
/// ```
187-
pub fn source(guard: &LockGuard<T>) -> &Lock<T> {
188-
&guard.0
189-
}
190-
}
191-
192-
impl<T: fmt::Debug> fmt::Debug for LockGuard<T> {
193-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194-
fmt::Debug::fmt(&**self, f)
195-
}
196-
}
197-
198-
impl<T: fmt::Display> fmt::Display for LockGuard<T> {
199-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200-
(**self).fmt(f)
201-
}
202-
}
203-
204-
impl<T> Deref for LockGuard<T> {
205-
type Target = T;
206-
207-
fn deref(&self) -> &T {
208-
unsafe { &*(self.0).0.data.get() }
209-
}
210-
}
211-
212-
impl<T> DerefMut for LockGuard<T> {
213-
fn deref_mut(&mut self) -> &mut T {
214-
unsafe { &mut *(self.0).0.data.get() }
215-
}
216-
}
217-
218-
/// Calls a function when dropped.
219-
struct CallOnDrop<F: Fn()>(F);
220-
221-
impl<F: Fn()> Drop for CallOnDrop<F> {
222-
fn drop(&mut self) {
223-
(self.0)();
224-
}
225-
}
10+
#[doc(inline)]
11+
pub use {
12+
async_mutex::{Mutex, MutexGuard},
13+
async_rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard},
14+
};

tests/lock.rs

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)