Coverage Report

Created: 2025-02-25 06:39

/rust/registry/src/index.crates.io-6f17d22bba15001f/lock_api-0.4.12/src/mutex.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2018 Amanieu d'Antras
2
//
3
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5
// http://opensource.org/licenses/MIT>, at your option. This file may not be
6
// copied, modified, or distributed except according to those terms.
7
8
use core::cell::UnsafeCell;
9
use core::fmt;
10
use core::marker::PhantomData;
11
use core::mem;
12
use core::ops::{Deref, DerefMut};
13
14
#[cfg(feature = "arc_lock")]
15
use alloc::sync::Arc;
16
#[cfg(feature = "arc_lock")]
17
use core::mem::ManuallyDrop;
18
#[cfg(feature = "arc_lock")]
19
use core::ptr;
20
21
#[cfg(feature = "owning_ref")]
22
use owning_ref::StableAddress;
23
24
#[cfg(feature = "serde")]
25
use serde::{Deserialize, Deserializer, Serialize, Serializer};
26
27
/// Basic operations for a mutex.
28
///
29
/// Types implementing this trait can be used by `Mutex` to form a safe and
30
/// fully-functioning mutex type.
31
///
32
/// # Safety
33
///
34
/// Implementations of this trait must ensure that the mutex is actually
35
/// exclusive: a lock can't be acquired while the mutex is already locked.
36
pub unsafe trait RawMutex {
37
    /// Initial value for an unlocked mutex.
38
    // A “non-constant” const item is a legacy way to supply an initialized value to downstream
39
    // static items. Can hopefully be replaced with `const fn new() -> Self` at some point.
40
    #[allow(clippy::declare_interior_mutable_const)]
41
    const INIT: Self;
42
43
    /// Marker type which determines whether a lock guard should be `Send`. Use
44
    /// one of the `GuardSend` or `GuardNoSend` helper types here.
45
    type GuardMarker;
46
47
    /// Acquires this mutex, blocking the current thread until it is able to do so.
48
    fn lock(&self);
49
50
    /// Attempts to acquire this mutex without blocking. Returns `true`
51
    /// if the lock was successfully acquired and `false` otherwise.
52
    fn try_lock(&self) -> bool;
53
54
    /// Unlocks this mutex.
55
    ///
56
    /// # Safety
57
    ///
58
    /// This method may only be called if the mutex is held in the current context, i.e. it must
59
    /// be paired with a successful call to [`lock`], [`try_lock`], [`try_lock_for`] or [`try_lock_until`].
60
    ///
61
    /// [`lock`]: RawMutex::lock
62
    /// [`try_lock`]: RawMutex::try_lock
63
    /// [`try_lock_for`]: RawMutexTimed::try_lock_for
64
    /// [`try_lock_until`]: RawMutexTimed::try_lock_until
65
    unsafe fn unlock(&self);
66
67
    /// Checks whether the mutex is currently locked.
68
    #[inline]
69
0
    fn is_locked(&self) -> bool {
70
0
        let acquired_lock = self.try_lock();
71
0
        if acquired_lock {
72
            // Safety: The lock has been successfully acquired above.
73
0
            unsafe {
74
0
                self.unlock();
75
0
            }
76
0
        }
77
0
        !acquired_lock
78
0
    }
79
}
80
81
/// Additional methods for mutexes which support fair unlocking.
82
///
83
/// Fair unlocking means that a lock is handed directly over to the next waiting
84
/// thread if there is one, without giving other threads the opportunity to
85
/// "steal" the lock in the meantime. This is typically slower than unfair
86
/// unlocking, but may be necessary in certain circumstances.
87
pub unsafe trait RawMutexFair: RawMutex {
88
    /// Unlocks this mutex using a fair unlock protocol.
89
    ///
90
    /// # Safety
91
    ///
92
    /// This method may only be called if the mutex is held in the current context, see
93
    /// the documentation of [`unlock`](RawMutex::unlock).
94
    unsafe fn unlock_fair(&self);
95
96
    /// Temporarily yields the mutex to a waiting thread if there is one.
97
    ///
98
    /// This method is functionally equivalent to calling `unlock_fair` followed
99
    /// by `lock`, however it can be much more efficient in the case where there
100
    /// are no waiting threads.
101
    ///
102
    /// # Safety
103
    ///
104
    /// This method may only be called if the mutex is held in the current context, see
105
    /// the documentation of [`unlock`](RawMutex::unlock).
106
0
    unsafe fn bump(&self) {
107
0
        self.unlock_fair();
108
0
        self.lock();
109
0
    }
110
}
111
112
/// Additional methods for mutexes which support locking with timeouts.
113
///
114
/// The `Duration` and `Instant` types are specified as associated types so that
115
/// this trait is usable even in `no_std` environments.
116
pub unsafe trait RawMutexTimed: RawMutex {
117
    /// Duration type used for `try_lock_for`.
118
    type Duration;
119
120
    /// Instant type used for `try_lock_until`.
121
    type Instant;
122
123
    /// Attempts to acquire this lock until a timeout is reached.
124
    fn try_lock_for(&self, timeout: Self::Duration) -> bool;
125
126
    /// Attempts to acquire this lock until a timeout is reached.
127
    fn try_lock_until(&self, timeout: Self::Instant) -> bool;
128
}
129
130
/// A mutual exclusion primitive useful for protecting shared data
131
///
132
/// This mutex will block threads waiting for the lock to become available. The
133
/// mutex can also be statically initialized or created via a `new`
134
/// constructor. Each mutex has a type parameter which represents the data that
135
/// it is protecting. The data can only be accessed through the RAII guards
136
/// returned from `lock` and `try_lock`, which guarantees that the data is only
137
/// ever accessed when the mutex is locked.
138
pub struct Mutex<R, T: ?Sized> {
139
    raw: R,
140
    data: UnsafeCell<T>,
141
}
142
143
unsafe impl<R: RawMutex + Send, T: ?Sized + Send> Send for Mutex<R, T> {}
144
unsafe impl<R: RawMutex + Sync, T: ?Sized + Send> Sync for Mutex<R, T> {}
145
146
impl<R: RawMutex, T> Mutex<R, T> {
147
    /// Creates a new mutex in an unlocked state ready for use.
148
    #[cfg(has_const_fn_trait_bound)]
149
    #[inline]
150
0
    pub const fn new(val: T) -> Mutex<R, T> {
151
0
        Mutex {
152
0
            raw: R::INIT,
153
0
            data: UnsafeCell::new(val),
154
0
        }
155
0
    }
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), anyhow::Error>>>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<()>>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, std::collections::hash::map::HashMap<i32, pingora_pool::connection::PoolConnection<ztunnel::proxy::pool::ConnClient>>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, lru_cache::LruCache<hickory_proto::op::query::Query, hickory_resolver::dns_lru::LruValue>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, core::option::Option<std::time::Instant>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), hickory_proto::error::ProtoError>>>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<alloc::boxed::Box<tokio::runtime::scheduler::multi_thread::worker::Core>>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, core::option::Option<alloc::collections::vec_deque::VecDeque<tokio::runtime::task::Notified<alloc::sync::Arc<tokio::task::local::Shared>>>>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::current_thread::Handle>>, tokio::runtime::task::core::Header>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::multi_thread::handle::Handle>>, tokio::runtime::task::core::Header>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::sync::notify::Waiter, tokio::sync::notify::Waiter>>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::sync::batch_semaphore::Waitlist>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::sync::barrier::BarrierState>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::time::clock::Inner>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::io::util::mem::SimplexStream>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::scheduled_io::Waiters>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::registration_set::Synced>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::time::wheel::Wheel>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::blocking::pool::Shared>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::multi_thread::worker::Synced>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::inject::synced::Synced>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, ()>>::new
Unexecuted instantiation: <lock_api::mutex::Mutex<_, _>>::new
156
157
    /// Creates a new mutex in an unlocked state ready for use.
158
    #[cfg(not(has_const_fn_trait_bound))]
159
    #[inline]
160
    pub fn new(val: T) -> Mutex<R, T> {
161
        Mutex {
162
            raw: R::INIT,
163
            data: UnsafeCell::new(val),
164
        }
165
    }
166
167
    /// Consumes this mutex, returning the underlying data.
168
    #[inline]
169
0
    pub fn into_inner(self) -> T {
170
0
        self.data.into_inner()
171
0
    }
172
}
173
174
impl<R, T> Mutex<R, T> {
175
    /// Creates a new mutex based on a pre-existing raw mutex.
176
    #[inline]
177
0
    pub const fn from_raw(raw_mutex: R, val: T) -> Mutex<R, T> {
178
0
        Mutex {
179
0
            raw: raw_mutex,
180
0
            data: UnsafeCell::new(val),
181
0
        }
182
0
    }
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::sync::notify::Waiter, tokio::sync::notify::Waiter>>>::from_raw
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::sync::batch_semaphore::Waitlist>>::from_raw
Unexecuted instantiation: <lock_api::mutex::Mutex<_, _>>::from_raw
183
184
    /// Creates a new mutex based on a pre-existing raw mutex.
185
    ///
186
    /// This allows creating a mutex in a constant context on stable Rust.
187
    ///
188
    /// This method is a legacy alias for [`from_raw`](Self::from_raw).
189
    #[inline]
190
0
    pub const fn const_new(raw_mutex: R, val: T) -> Mutex<R, T> {
191
0
        Self::from_raw(raw_mutex, val)
192
0
    }
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::sync::notify::Waiter, tokio::sync::notify::Waiter>>>::const_new
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::sync::batch_semaphore::Waitlist>>::const_new
Unexecuted instantiation: <lock_api::mutex::Mutex<_, _>>::const_new
193
}
194
195
impl<R: RawMutex, T: ?Sized> Mutex<R, T> {
196
    /// Creates a new `MutexGuard` without checking if the mutex is locked.
197
    ///
198
    /// # Safety
199
    ///
200
    /// This method must only be called if the thread logically holds the lock.
201
    ///
202
    /// Calling this function when a guard has already been produced is undefined behaviour unless
203
    /// the guard was forgotten with `mem::forget`.
204
    #[inline]
205
0
    pub unsafe fn make_guard_unchecked(&self) -> MutexGuard<'_, R, T> {
206
0
        MutexGuard {
207
0
            mutex: self,
208
0
            marker: PhantomData,
209
0
        }
210
0
    }
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), anyhow::Error>>>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, std::collections::hash::map::HashMap<i32, pingora_pool::connection::PoolConnection<ztunnel::proxy::pool::ConnClient>>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<()>>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, lru_cache::LruCache<hickory_proto::op::query::Query, hickory_resolver::dns_lru::LruValue>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, core::option::Option<std::time::Instant>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), hickory_proto::error::ProtoError>>>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<alloc::boxed::Box<tokio::runtime::scheduler::multi_thread::worker::Core>>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<std::process::Child>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, core::option::Option<tokio::sync::watch::Receiver<()>>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, core::option::Option<alloc::collections::vec_deque::VecDeque<tokio::runtime::task::Notified<alloc::sync::Arc<tokio::task::local::Shared>>>>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::current_thread::Handle>>, tokio::runtime::task::core::Header>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::multi_thread::handle::Handle>>, tokio::runtime::task::core::Header>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::sync::notify::Waiter, tokio::sync::notify::Waiter>>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::sync::batch_semaphore::Waitlist>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::time::clock::Inner>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::io::util::mem::SimplexStream>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::scheduled_io::Waiters>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::registration_set::Synced>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::time::wheel::Wheel>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::blocking::pool::Shared>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::multi_thread::worker::Synced>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::inject::synced::Synced>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, ()>>::make_guard_unchecked
Unexecuted instantiation: <lock_api::mutex::Mutex<_, _>>::make_guard_unchecked
211
212
    /// Acquires a mutex, blocking the current thread until it is able to do so.
213
    ///
214
    /// This function will block the local thread until it is available to acquire
215
    /// the mutex. Upon returning, the thread is the only thread with the mutex
216
    /// held. An RAII guard is returned to allow scoped unlock of the lock. When
217
    /// the guard goes out of scope, the mutex will be unlocked.
218
    ///
219
    /// Attempts to lock a mutex in the thread which already holds the lock will
220
    /// result in a deadlock.
221
    #[inline]
222
0
    pub fn lock(&self) -> MutexGuard<'_, R, T> {
223
0
        self.raw.lock();
224
0
        // SAFETY: The lock is held, as required.
225
0
        unsafe { self.make_guard_unchecked() }
226
0
    }
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), anyhow::Error>>>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, std::collections::hash::map::HashMap<i32, pingora_pool::connection::PoolConnection<ztunnel::proxy::pool::ConnClient>>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<()>>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, lru_cache::LruCache<hickory_proto::op::query::Query, hickory_resolver::dns_lru::LruValue>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, core::option::Option<std::time::Instant>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), hickory_proto::error::ProtoError>>>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<alloc::boxed::Box<tokio::runtime::scheduler::multi_thread::worker::Core>>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<std::process::Child>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, core::option::Option<alloc::collections::vec_deque::VecDeque<tokio::runtime::task::Notified<alloc::sync::Arc<tokio::task::local::Shared>>>>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::current_thread::Handle>>, tokio::runtime::task::core::Header>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::multi_thread::handle::Handle>>, tokio::runtime::task::core::Header>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::sync::notify::Waiter, tokio::sync::notify::Waiter>>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::sync::batch_semaphore::Waitlist>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::time::clock::Inner>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::io::util::mem::SimplexStream>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::scheduled_io::Waiters>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::registration_set::Synced>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::time::wheel::Wheel>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::blocking::pool::Shared>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::multi_thread::worker::Synced>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::inject::synced::Synced>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, ()>>::lock
Unexecuted instantiation: <lock_api::mutex::Mutex<_, _>>::lock
227
228
    /// Attempts to acquire this lock.
229
    ///
230
    /// If the lock could not be acquired at this time, then `None` is returned.
231
    /// Otherwise, an RAII guard is returned. The lock will be unlocked when the
232
    /// guard is dropped.
233
    ///
234
    /// This function does not block.
235
    #[inline]
236
0
    pub fn try_lock(&self) -> Option<MutexGuard<'_, R, T>> {
237
0
        if self.raw.try_lock() {
238
            // SAFETY: The lock is held, as required.
239
0
            Some(unsafe { self.make_guard_unchecked() })
240
        } else {
241
0
            None
242
        }
243
0
    }
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<std::process::Child>>>::try_lock
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, core::option::Option<tokio::sync::watch::Receiver<()>>>>::try_lock
Unexecuted instantiation: <lock_api::mutex::Mutex<_, _>>::try_lock
244
245
    /// Returns a mutable reference to the underlying data.
246
    ///
247
    /// Since this call borrows the `Mutex` mutably, no actual locking needs to
248
    /// take place---the mutable borrow statically guarantees no locks exist.
249
    #[inline]
250
0
    pub fn get_mut(&mut self) -> &mut T {
251
0
        unsafe { &mut *self.data.get() }
252
0
    }
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::time::wheel::Wheel>>::get_mut
Unexecuted instantiation: <lock_api::mutex::Mutex<_, _>>::get_mut
253
254
    /// Checks whether the mutex is currently locked.
255
    #[inline]
256
0
    pub fn is_locked(&self) -> bool {
257
0
        self.raw.is_locked()
258
0
    }
259
260
    /// Forcibly unlocks the mutex.
261
    ///
262
    /// This is useful when combined with `mem::forget` to hold a lock without
263
    /// the need to maintain a `MutexGuard` object alive, for example when
264
    /// dealing with FFI.
265
    ///
266
    /// # Safety
267
    ///
268
    /// This method must only be called if the current thread logically owns a
269
    /// `MutexGuard` but that guard has been discarded using `mem::forget`.
270
    /// Behavior is undefined if a mutex is unlocked when not locked.
271
    #[inline]
272
0
    pub unsafe fn force_unlock(&self) {
273
0
        self.raw.unlock();
274
0
    }
275
276
    /// Returns the underlying raw mutex object.
277
    ///
278
    /// Note that you will most likely need to import the `RawMutex` trait from
279
    /// `lock_api` to be able to call functions on the raw mutex.
280
    ///
281
    /// # Safety
282
    ///
283
    /// This method is unsafe because it allows unlocking a mutex while
284
    /// still holding a reference to a `MutexGuard`.
285
    #[inline]
286
0
    pub unsafe fn raw(&self) -> &R {
287
0
        &self.raw
288
0
    }
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, tokio::runtime::blocking::pool::Shared>>::raw
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, ()>>::raw
Unexecuted instantiation: <lock_api::mutex::Mutex<_, _>>::raw
289
290
    /// Returns a raw pointer to the underlying data.
291
    ///
292
    /// This is useful when combined with `mem::forget` to hold a lock without
293
    /// the need to maintain a `MutexGuard` object alive, for example when
294
    /// dealing with FFI.
295
    ///
296
    /// # Safety
297
    ///
298
    /// You must ensure that there are no data races when dereferencing the
299
    /// returned pointer, for example if the current thread logically owns
300
    /// a `MutexGuard` but that guard has been discarded using `mem::forget`.
301
    #[inline]
302
0
    pub fn data_ptr(&self) -> *mut T {
303
0
        self.data.get()
304
0
    }
305
306
    /// Creates a new `ArcMutexGuard` without checking if the mutex is locked.
307
    ///
308
    /// # Safety
309
    ///
310
    /// This method must only be called if the thread logically holds the lock.
311
    ///
312
    /// Calling this function when a guard has already been produced is undefined behaviour unless
313
    /// the guard was forgotten with `mem::forget`.
314
    #[cfg(feature = "arc_lock")]
315
    #[inline]
316
    unsafe fn make_arc_guard_unchecked(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
317
        ArcMutexGuard {
318
            mutex: self.clone(),
319
            marker: PhantomData,
320
        }
321
    }
322
323
    /// Acquires a lock through an `Arc`.
324
    ///
325
    /// This method is similar to the `lock` method; however, it requires the `Mutex` to be inside of an `Arc`
326
    /// and the resulting mutex guard has no lifetime requirements.
327
    #[cfg(feature = "arc_lock")]
328
    #[inline]
329
    pub fn lock_arc(self: &Arc<Self>) -> ArcMutexGuard<R, T> {
330
        self.raw.lock();
331
        // SAFETY: the locking guarantee is upheld
332
        unsafe { self.make_arc_guard_unchecked() }
333
    }
334
335
    /// Attempts to acquire a lock through an `Arc`.
336
    ///
337
    /// This method is similar to the `try_lock` method; however, it requires the `Mutex` to be inside of an
338
    /// `Arc` and the resulting mutex guard has no lifetime requirements.
339
    #[cfg(feature = "arc_lock")]
340
    #[inline]
341
    pub fn try_lock_arc(self: &Arc<Self>) -> Option<ArcMutexGuard<R, T>> {
342
        if self.raw.try_lock() {
343
            // SAFETY: locking guarantee is upheld
344
            Some(unsafe { self.make_arc_guard_unchecked() })
345
        } else {
346
            None
347
        }
348
    }
349
}
350
351
impl<R: RawMutexFair, T: ?Sized> Mutex<R, T> {
352
    /// Forcibly unlocks the mutex using a fair unlock protocol.
353
    ///
354
    /// This is useful when combined with `mem::forget` to hold a lock without
355
    /// the need to maintain a `MutexGuard` object alive, for example when
356
    /// dealing with FFI.
357
    ///
358
    /// # Safety
359
    ///
360
    /// This method must only be called if the current thread logically owns a
361
    /// `MutexGuard` but that guard has been discarded using `mem::forget`.
362
    /// Behavior is undefined if a mutex is unlocked when not locked.
363
    #[inline]
364
0
    pub unsafe fn force_unlock_fair(&self) {
365
0
        self.raw.unlock_fair();
366
0
    }
367
}
368
369
impl<R: RawMutexTimed, T: ?Sized> Mutex<R, T> {
370
    /// Attempts to acquire this lock until a timeout is reached.
371
    ///
372
    /// If the lock could not be acquired before the timeout expired, then
373
    /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
374
    /// be unlocked when the guard is dropped.
375
    #[inline]
376
0
    pub fn try_lock_for(&self, timeout: R::Duration) -> Option<MutexGuard<'_, R, T>> {
377
0
        if self.raw.try_lock_for(timeout) {
378
            // SAFETY: The lock is held, as required.
379
0
            Some(unsafe { self.make_guard_unchecked() })
380
        } else {
381
0
            None
382
        }
383
0
    }
384
385
    /// Attempts to acquire this lock until a timeout is reached.
386
    ///
387
    /// If the lock could not be acquired before the timeout expired, then
388
    /// `None` is returned. Otherwise, an RAII guard is returned. The lock will
389
    /// be unlocked when the guard is dropped.
390
    #[inline]
391
0
    pub fn try_lock_until(&self, timeout: R::Instant) -> Option<MutexGuard<'_, R, T>> {
392
0
        if self.raw.try_lock_until(timeout) {
393
            // SAFETY: The lock is held, as required.
394
0
            Some(unsafe { self.make_guard_unchecked() })
395
        } else {
396
0
            None
397
        }
398
0
    }
399
400
    /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
401
    ///
402
    /// This method is similar to the `try_lock_for` method; however, it requires the `Mutex` to be inside of an
403
    /// `Arc` and the resulting mutex guard has no lifetime requirements.
404
    #[cfg(feature = "arc_lock")]
405
    #[inline]
406
    pub fn try_lock_arc_for(self: &Arc<Self>, timeout: R::Duration) -> Option<ArcMutexGuard<R, T>> {
407
        if self.raw.try_lock_for(timeout) {
408
            // SAFETY: locking guarantee is upheld
409
            Some(unsafe { self.make_arc_guard_unchecked() })
410
        } else {
411
            None
412
        }
413
    }
414
415
    /// Attempts to acquire this lock through an `Arc` until a timeout is reached.
416
    ///
417
    /// This method is similar to the `try_lock_until` method; however, it requires the `Mutex` to be inside of
418
    /// an `Arc` and the resulting mutex guard has no lifetime requirements.
419
    #[cfg(feature = "arc_lock")]
420
    #[inline]
421
    pub fn try_lock_arc_until(
422
        self: &Arc<Self>,
423
        timeout: R::Instant,
424
    ) -> Option<ArcMutexGuard<R, T>> {
425
        if self.raw.try_lock_until(timeout) {
426
            // SAFETY: locking guarantee is upheld
427
            Some(unsafe { self.make_arc_guard_unchecked() })
428
        } else {
429
            None
430
        }
431
    }
432
}
433
434
impl<R: RawMutex, T: ?Sized + Default> Default for Mutex<R, T> {
435
    #[inline]
436
0
    fn default() -> Mutex<R, T> {
437
0
        Mutex::new(Default::default())
438
0
    }
439
}
440
441
impl<R: RawMutex, T> From<T> for Mutex<R, T> {
442
    #[inline]
443
0
    fn from(t: T) -> Mutex<R, T> {
444
0
        Mutex::new(t)
445
0
    }
446
}
447
448
impl<R: RawMutex, T: ?Sized + fmt::Debug> fmt::Debug for Mutex<R, T> {
449
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
450
0
        match self.try_lock() {
451
0
            Some(guard) => f.debug_struct("Mutex").field("data", &&*guard).finish(),
452
            None => {
453
                struct LockedPlaceholder;
454
                impl fmt::Debug for LockedPlaceholder {
455
0
                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456
0
                        f.write_str("<locked>")
457
0
                    }
458
                }
459
460
0
                f.debug_struct("Mutex")
461
0
                    .field("data", &LockedPlaceholder)
462
0
                    .finish()
463
            }
464
        }
465
0
    }
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<std::process::Child>> as core::fmt::Debug>::fmt
Unexecuted instantiation: <lock_api::mutex::Mutex<parking_lot::raw_mutex::RawMutex, core::option::Option<tokio::sync::watch::Receiver<()>>> as core::fmt::Debug>::fmt
Unexecuted instantiation: <lock_api::mutex::Mutex<_, _> as core::fmt::Debug>::fmt
466
}
467
468
// Copied and modified from serde
469
#[cfg(feature = "serde")]
470
impl<R, T> Serialize for Mutex<R, T>
471
where
472
    R: RawMutex,
473
    T: Serialize + ?Sized,
474
{
475
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
476
    where
477
        S: Serializer,
478
    {
479
        self.lock().serialize(serializer)
480
    }
481
}
482
483
#[cfg(feature = "serde")]
484
impl<'de, R, T> Deserialize<'de> for Mutex<R, T>
485
where
486
    R: RawMutex,
487
    T: Deserialize<'de> + ?Sized,
488
{
489
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
490
    where
491
        D: Deserializer<'de>,
492
    {
493
        Deserialize::deserialize(deserializer).map(Mutex::new)
494
    }
495
}
496
497
/// An RAII implementation of a "scoped lock" of a mutex. When this structure is
498
/// dropped (falls out of scope), the lock will be unlocked.
499
///
500
/// The data protected by the mutex can be accessed through this guard via its
501
/// `Deref` and `DerefMut` implementations.
502
#[clippy::has_significant_drop]
503
#[must_use = "if unused the Mutex will immediately unlock"]
504
pub struct MutexGuard<'a, R: RawMutex, T: ?Sized> {
505
    mutex: &'a Mutex<R, T>,
506
    marker: PhantomData<(&'a mut T, R::GuardMarker)>,
507
}
508
509
unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync for MutexGuard<'a, R, T> {}
510
511
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
512
    /// Returns a reference to the original `Mutex` object.
513
0
    pub fn mutex(s: &Self) -> &'a Mutex<R, T> {
514
0
        s.mutex
515
0
    }
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::blocking::pool::Shared>>::mutex
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, ()>>::mutex
Unexecuted instantiation: <lock_api::mutex::MutexGuard<_, _>>::mutex
516
517
    /// Makes a new `MappedMutexGuard` for a component of the locked data.
518
    ///
519
    /// This operation cannot fail as the `MutexGuard` passed
520
    /// in already locked the mutex.
521
    ///
522
    /// This is an associated function that needs to be
523
    /// used as `MutexGuard::map(...)`. A method would interfere with methods of
524
    /// the same name on the contents of the locked data.
525
    #[inline]
526
0
    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
527
0
    where
528
0
        F: FnOnce(&mut T) -> &mut U,
529
0
    {
530
0
        let raw = &s.mutex.raw;
531
0
        let data = f(unsafe { &mut *s.mutex.data.get() });
532
0
        mem::forget(s);
533
0
        MappedMutexGuard {
534
0
            raw,
535
0
            data,
536
0
            marker: PhantomData,
537
0
        }
538
0
    }
539
540
    /// Attempts to make a new `MappedMutexGuard` for a component of the
541
    /// locked data. The original guard is returned if the closure returns `None`.
542
    ///
543
    /// This operation cannot fail as the `MutexGuard` passed
544
    /// in already locked the mutex.
545
    ///
546
    /// This is an associated function that needs to be
547
    /// used as `MutexGuard::try_map(...)`. A method would interfere with methods of
548
    /// the same name on the contents of the locked data.
549
    #[inline]
550
0
    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
551
0
    where
552
0
        F: FnOnce(&mut T) -> Option<&mut U>,
553
0
    {
554
0
        let raw = &s.mutex.raw;
555
0
        let data = match f(unsafe { &mut *s.mutex.data.get() }) {
556
0
            Some(data) => data,
557
0
            None => return Err(s),
558
        };
559
0
        mem::forget(s);
560
0
        Ok(MappedMutexGuard {
561
0
            raw,
562
0
            data,
563
0
            marker: PhantomData,
564
0
        })
565
0
    }
566
567
    /// Temporarily unlocks the mutex to execute the given function.
568
    ///
569
    /// This is safe because `&mut` guarantees that there exist no other
570
    /// references to the data protected by the mutex.
571
    #[inline]
572
0
    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
573
0
    where
574
0
        F: FnOnce() -> U,
575
0
    {
576
0
        // Safety: A MutexGuard always holds the lock.
577
0
        unsafe {
578
0
            s.mutex.raw.unlock();
579
0
        }
580
0
        defer!(s.mutex.raw.lock());
581
0
        f()
582
0
    }
583
584
    /// Leaks the mutex guard and returns a mutable reference to the data
585
    /// protected by the mutex.
586
    ///
587
    /// This will leave the `Mutex` in a locked state.
588
    #[inline]
589
0
    pub fn leak(s: Self) -> &'a mut T {
590
0
        let r = unsafe { &mut *s.mutex.data.get() };
591
0
        mem::forget(s);
592
0
        r
593
0
    }
594
}
595
596
impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MutexGuard<'a, R, T> {
597
    /// Unlocks the mutex using a fair unlock protocol.
598
    ///
599
    /// By default, mutexes are unfair and allow the current thread to re-lock
600
    /// the mutex before another has the chance to acquire the lock, even if
601
    /// that thread has been blocked on the mutex for a long time. This is the
602
    /// default because it allows much higher throughput as it avoids forcing a
603
    /// context switch on every mutex unlock. This can result in one thread
604
    /// acquiring a mutex many more times than other threads.
605
    ///
606
    /// However in some cases it can be beneficial to ensure fairness by forcing
607
    /// the lock to pass on to a waiting thread if there is one. This is done by
608
    /// using this method instead of dropping the `MutexGuard` normally.
609
    #[inline]
610
0
    pub fn unlock_fair(s: Self) {
611
0
        // Safety: A MutexGuard always holds the lock.
612
0
        unsafe {
613
0
            s.mutex.raw.unlock_fair();
614
0
        }
615
0
        mem::forget(s);
616
0
    }
617
618
    /// Temporarily unlocks the mutex to execute the given function.
619
    ///
620
    /// The mutex is unlocked using a fair unlock protocol.
621
    ///
622
    /// This is safe because `&mut` guarantees that there exist no other
623
    /// references to the data protected by the mutex.
624
    #[inline]
625
0
    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
626
0
    where
627
0
        F: FnOnce() -> U,
628
0
    {
629
0
        // Safety: A MutexGuard always holds the lock.
630
0
        unsafe {
631
0
            s.mutex.raw.unlock_fair();
632
0
        }
633
0
        defer!(s.mutex.raw.lock());
634
0
        f()
635
0
    }
636
637
    /// Temporarily yields the mutex to a waiting thread if there is one.
638
    ///
639
    /// This method is functionally equivalent to calling `unlock_fair` followed
640
    /// by `lock`, however it can be much more efficient in the case where there
641
    /// are no waiting threads.
642
    #[inline]
643
0
    pub fn bump(s: &mut Self) {
644
0
        // Safety: A MutexGuard always holds the lock.
645
0
        unsafe {
646
0
            s.mutex.raw.bump();
647
0
        }
648
0
    }
649
}
650
651
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MutexGuard<'a, R, T> {
652
    type Target = T;
653
    #[inline]
654
0
    fn deref(&self) -> &T {
655
0
        unsafe { &*self.mutex.data.get() }
656
0
    }
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, std::collections::hash::map::HashMap<i32, pingora_pool::connection::PoolConnection<ztunnel::proxy::pool::ConnClient>>> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, core::option::Option<std::time::Instant>> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<alloc::boxed::Box<tokio::runtime::scheduler::multi_thread::worker::Core>>> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<std::process::Child>> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, core::option::Option<tokio::sync::watch::Receiver<()>>> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::sync::notify::Waiter, tokio::sync::notify::Waiter>> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::sync::batch_semaphore::Waitlist> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::time::clock::Inner> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::time::wheel::Wheel> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::blocking::pool::Shared> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::multi_thread::worker::Synced> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <lock_api::mutex::MutexGuard<_, _> as core::ops::deref::Deref>::deref
657
}
658
659
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MutexGuard<'a, R, T> {
660
    #[inline]
661
0
    fn deref_mut(&mut self) -> &mut T {
662
0
        unsafe { &mut *self.mutex.data.get() }
663
0
    }
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), anyhow::Error>>>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, std::collections::hash::map::HashMap<i32, pingora_pool::connection::PoolConnection<ztunnel::proxy::pool::ConnClient>>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<()>>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, lru_cache::LruCache<hickory_proto::op::query::Query, hickory_resolver::dns_lru::LruValue>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, core::option::Option<std::time::Instant>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), hickory_proto::error::ProtoError>>>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<alloc::boxed::Box<tokio::runtime::scheduler::multi_thread::worker::Core>>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<std::process::Child>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, core::option::Option<tokio::sync::watch::Receiver<()>>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, core::option::Option<alloc::collections::vec_deque::VecDeque<tokio::runtime::task::Notified<alloc::sync::Arc<tokio::task::local::Shared>>>>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::current_thread::Handle>>, tokio::runtime::task::core::Header>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::multi_thread::handle::Handle>>, tokio::runtime::task::core::Header>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::sync::notify::Waiter, tokio::sync::notify::Waiter>> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::sync::batch_semaphore::Waitlist> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::time::clock::Inner> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::io::util::mem::SimplexStream> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::scheduled_io::Waiters> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::registration_set::Synced> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::time::wheel::Wheel> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::blocking::pool::Shared> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::multi_thread::worker::Synced> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::inject::synced::Synced> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <lock_api::mutex::MutexGuard<_, _> as core::ops::deref::DerefMut>::deref_mut
664
}
665
666
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MutexGuard<'a, R, T> {
667
    #[inline]
668
0
    fn drop(&mut self) {
669
0
        // Safety: A MutexGuard always holds the lock.
670
0
        unsafe {
671
0
            self.mutex.raw.unlock();
672
0
        }
673
0
    }
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), anyhow::Error>>>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, std::collections::hash::map::HashMap<i32, pingora_pool::connection::PoolConnection<ztunnel::proxy::pool::ConnClient>>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<()>>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, lru_cache::LruCache<hickory_proto::op::query::Query, hickory_resolver::dns_lru::LruValue>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, core::option::Option<std::time::Instant>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::idle_notified_set::ListsInner<tokio::runtime::task::join::JoinHandle<core::result::Result<(), hickory_proto::error::ProtoError>>>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<alloc::boxed::Box<tokio::runtime::scheduler::multi_thread::worker::Core>>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, alloc::vec::Vec<std::process::Child>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, core::option::Option<tokio::sync::watch::Receiver<()>>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, core::option::Option<alloc::collections::vec_deque::VecDeque<tokio::runtime::task::Notified<alloc::sync::Arc<tokio::task::local::Shared>>>>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::current_thread::Handle>>, tokio::runtime::task::core::Header>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::runtime::task::Task<alloc::sync::Arc<tokio::runtime::scheduler::multi_thread::handle::Handle>>, tokio::runtime::task::core::Header>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::util::linked_list::LinkedList<tokio::sync::notify::Waiter, tokio::sync::notify::Waiter>> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::sync::batch_semaphore::Waitlist> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::time::clock::Inner> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::io::util::mem::SimplexStream> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::scheduled_io::Waiters> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::io::registration_set::Synced> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::time::wheel::Wheel> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::blocking::pool::Shared> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::multi_thread::worker::Synced> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, tokio::runtime::scheduler::inject::synced::Synced> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<parking_lot::raw_mutex::RawMutex, ()> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <lock_api::mutex::MutexGuard<_, _> as core::ops::drop::Drop>::drop
674
}
675
676
impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MutexGuard<'a, R, T> {
677
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
678
0
        fmt::Debug::fmt(&**self, f)
679
0
    }
680
}
681
682
impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display for MutexGuard<'a, R, T> {
683
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
684
0
        (**self).fmt(f)
685
0
    }
686
}
687
688
#[cfg(feature = "owning_ref")]
689
unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MutexGuard<'a, R, T> {}
690
691
/// An RAII mutex guard returned by the `Arc` locking operations on `Mutex`.
692
///
693
/// This is similar to the `MutexGuard` struct, except instead of using a reference to unlock the `Mutex` it
694
/// uses an `Arc<Mutex>`. This has several advantages, most notably that it has an `'static` lifetime.
695
#[cfg(feature = "arc_lock")]
696
#[clippy::has_significant_drop]
697
#[must_use = "if unused the Mutex will immediately unlock"]
698
pub struct ArcMutexGuard<R: RawMutex, T: ?Sized> {
699
    mutex: Arc<Mutex<R, T>>,
700
    marker: PhantomData<*const ()>,
701
}
702
703
#[cfg(feature = "arc_lock")]
704
unsafe impl<R: RawMutex + Send + Sync, T: Send + ?Sized> Send for ArcMutexGuard<R, T> where
705
    R::GuardMarker: Send
706
{
707
}
708
#[cfg(feature = "arc_lock")]
709
unsafe impl<R: RawMutex + Sync, T: Sync + ?Sized> Sync for ArcMutexGuard<R, T> where
710
    R::GuardMarker: Sync
711
{
712
}
713
714
#[cfg(feature = "arc_lock")]
715
impl<R: RawMutex, T: ?Sized> ArcMutexGuard<R, T> {
716
    /// Returns a reference to the `Mutex` this is guarding, contained in its `Arc`.
717
    #[inline]
718
    pub fn mutex(s: &Self) -> &Arc<Mutex<R, T>> {
719
        &s.mutex
720
    }
721
722
    /// Unlocks the mutex and returns the `Arc` that was held by the [`ArcMutexGuard`].
723
    #[inline]
724
    pub fn into_arc(s: Self) -> Arc<Mutex<R, T>> {
725
        // Safety: Skip our Drop impl and manually unlock the mutex.
726
        let arc = unsafe { ptr::read(&s.mutex) };
727
        mem::forget(s);
728
        unsafe {
729
            arc.raw.unlock();
730
        }
731
        arc
732
    }
733
734
    /// Temporarily unlocks the mutex to execute the given function.
735
    ///
736
    /// This is safe because `&mut` guarantees that there exist no other
737
    /// references to the data protected by the mutex.
738
    #[inline]
739
    pub fn unlocked<F, U>(s: &mut Self, f: F) -> U
740
    where
741
        F: FnOnce() -> U,
742
    {
743
        // Safety: A MutexGuard always holds the lock.
744
        unsafe {
745
            s.mutex.raw.unlock();
746
        }
747
        defer!(s.mutex.raw.lock());
748
        f()
749
    }
750
}
751
752
#[cfg(feature = "arc_lock")]
753
impl<R: RawMutexFair, T: ?Sized> ArcMutexGuard<R, T> {
754
    /// Unlocks the mutex using a fair unlock protocol.
755
    ///
756
    /// This is functionally identical to the `unlock_fair` method on [`MutexGuard`].
757
    #[inline]
758
    pub fn unlock_fair(s: Self) {
759
        // Safety: A MutexGuard always holds the lock.
760
        unsafe {
761
            s.mutex.raw.unlock_fair();
762
        }
763
764
        // SAFETY: make sure the Arc gets it reference decremented
765
        let mut s = ManuallyDrop::new(s);
766
        unsafe { ptr::drop_in_place(&mut s.mutex) };
767
    }
768
769
    /// Temporarily unlocks the mutex to execute the given function.
770
    ///
771
    /// This is functionally identical to the `unlocked_fair` method on [`MutexGuard`].
772
    #[inline]
773
    pub fn unlocked_fair<F, U>(s: &mut Self, f: F) -> U
774
    where
775
        F: FnOnce() -> U,
776
    {
777
        // Safety: A MutexGuard always holds the lock.
778
        unsafe {
779
            s.mutex.raw.unlock_fair();
780
        }
781
        defer!(s.mutex.raw.lock());
782
        f()
783
    }
784
785
    /// Temporarily yields the mutex to a waiting thread if there is one.
786
    ///
787
    /// This is functionally identical to the `bump` method on [`MutexGuard`].
788
    #[inline]
789
    pub fn bump(s: &mut Self) {
790
        // Safety: A MutexGuard always holds the lock.
791
        unsafe {
792
            s.mutex.raw.bump();
793
        }
794
    }
795
}
796
797
#[cfg(feature = "arc_lock")]
798
impl<R: RawMutex, T: ?Sized> Deref for ArcMutexGuard<R, T> {
799
    type Target = T;
800
    #[inline]
801
    fn deref(&self) -> &T {
802
        unsafe { &*self.mutex.data.get() }
803
    }
804
}
805
806
#[cfg(feature = "arc_lock")]
807
impl<R: RawMutex, T: ?Sized> DerefMut for ArcMutexGuard<R, T> {
808
    #[inline]
809
    fn deref_mut(&mut self) -> &mut T {
810
        unsafe { &mut *self.mutex.data.get() }
811
    }
812
}
813
814
#[cfg(feature = "arc_lock")]
815
impl<R: RawMutex, T: ?Sized> Drop for ArcMutexGuard<R, T> {
816
    #[inline]
817
    fn drop(&mut self) {
818
        // Safety: A MutexGuard always holds the lock.
819
        unsafe {
820
            self.mutex.raw.unlock();
821
        }
822
    }
823
}
824
825
/// An RAII mutex guard returned by `MutexGuard::map`, which can point to a
826
/// subfield of the protected data.
827
///
828
/// The main difference between `MappedMutexGuard` and `MutexGuard` is that the
829
/// former doesn't support temporarily unlocking and re-locking, since that
830
/// could introduce soundness issues if the locked object is modified by another
831
/// thread.
832
#[clippy::has_significant_drop]
833
#[must_use = "if unused the Mutex will immediately unlock"]
834
pub struct MappedMutexGuard<'a, R: RawMutex, T: ?Sized> {
835
    raw: &'a R,
836
    data: *mut T,
837
    marker: PhantomData<&'a mut T>,
838
}
839
840
unsafe impl<'a, R: RawMutex + Sync + 'a, T: ?Sized + Sync + 'a> Sync
841
    for MappedMutexGuard<'a, R, T>
842
{
843
}
844
unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + Send + 'a> Send for MappedMutexGuard<'a, R, T> where
845
    R::GuardMarker: Send
846
{
847
}
848
849
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
850
    /// Makes a new `MappedMutexGuard` for a component of the locked data.
851
    ///
852
    /// This operation cannot fail as the `MappedMutexGuard` passed
853
    /// in already locked the mutex.
854
    ///
855
    /// This is an associated function that needs to be
856
    /// used as `MappedMutexGuard::map(...)`. A method would interfere with methods of
857
    /// the same name on the contents of the locked data.
858
    #[inline]
859
0
    pub fn map<U: ?Sized, F>(s: Self, f: F) -> MappedMutexGuard<'a, R, U>
860
0
    where
861
0
        F: FnOnce(&mut T) -> &mut U,
862
0
    {
863
0
        let raw = s.raw;
864
0
        let data = f(unsafe { &mut *s.data });
865
0
        mem::forget(s);
866
0
        MappedMutexGuard {
867
0
            raw,
868
0
            data,
869
0
            marker: PhantomData,
870
0
        }
871
0
    }
872
873
    /// Attempts to make a new `MappedMutexGuard` for a component of the
874
    /// locked data. The original guard is returned if the closure returns `None`.
875
    ///
876
    /// This operation cannot fail as the `MappedMutexGuard` passed
877
    /// in already locked the mutex.
878
    ///
879
    /// This is an associated function that needs to be
880
    /// used as `MappedMutexGuard::try_map(...)`. A method would interfere with methods of
881
    /// the same name on the contents of the locked data.
882
    #[inline]
883
0
    pub fn try_map<U: ?Sized, F>(s: Self, f: F) -> Result<MappedMutexGuard<'a, R, U>, Self>
884
0
    where
885
0
        F: FnOnce(&mut T) -> Option<&mut U>,
886
0
    {
887
0
        let raw = s.raw;
888
0
        let data = match f(unsafe { &mut *s.data }) {
889
0
            Some(data) => data,
890
0
            None => return Err(s),
891
        };
892
0
        mem::forget(s);
893
0
        Ok(MappedMutexGuard {
894
0
            raw,
895
0
            data,
896
0
            marker: PhantomData,
897
0
        })
898
0
    }
899
}
900
901
impl<'a, R: RawMutexFair + 'a, T: ?Sized + 'a> MappedMutexGuard<'a, R, T> {
902
    /// Unlocks the mutex using a fair unlock protocol.
903
    ///
904
    /// By default, mutexes are unfair and allow the current thread to re-lock
905
    /// the mutex before another has the chance to acquire the lock, even if
906
    /// that thread has been blocked on the mutex for a long time. This is the
907
    /// default because it allows much higher throughput as it avoids forcing a
908
    /// context switch on every mutex unlock. This can result in one thread
909
    /// acquiring a mutex many more times than other threads.
910
    ///
911
    /// However in some cases it can be beneficial to ensure fairness by forcing
912
    /// the lock to pass on to a waiting thread if there is one. This is done by
913
    /// using this method instead of dropping the `MutexGuard` normally.
914
    #[inline]
915
0
    pub fn unlock_fair(s: Self) {
916
0
        // Safety: A MutexGuard always holds the lock.
917
0
        unsafe {
918
0
            s.raw.unlock_fair();
919
0
        }
920
0
        mem::forget(s);
921
0
    }
922
}
923
924
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Deref for MappedMutexGuard<'a, R, T> {
925
    type Target = T;
926
    #[inline]
927
0
    fn deref(&self) -> &T {
928
0
        unsafe { &*self.data }
929
0
    }
930
}
931
932
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> DerefMut for MappedMutexGuard<'a, R, T> {
933
    #[inline]
934
0
    fn deref_mut(&mut self) -> &mut T {
935
0
        unsafe { &mut *self.data }
936
0
    }
937
}
938
939
impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> Drop for MappedMutexGuard<'a, R, T> {
940
    #[inline]
941
0
    fn drop(&mut self) {
942
0
        // Safety: A MappedMutexGuard always holds the lock.
943
0
        unsafe {
944
0
            self.raw.unlock();
945
0
        }
946
0
    }
947
}
948
949
impl<'a, R: RawMutex + 'a, T: fmt::Debug + ?Sized + 'a> fmt::Debug for MappedMutexGuard<'a, R, T> {
950
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
951
0
        fmt::Debug::fmt(&**self, f)
952
0
    }
953
}
954
955
impl<'a, R: RawMutex + 'a, T: fmt::Display + ?Sized + 'a> fmt::Display
956
    for MappedMutexGuard<'a, R, T>
957
{
958
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
959
0
        (**self).fmt(f)
960
0
    }
961
}
962
963
#[cfg(feature = "owning_ref")]
964
unsafe impl<'a, R: RawMutex + 'a, T: ?Sized + 'a> StableAddress for MappedMutexGuard<'a, R, T> {}