summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2026-08-26 21:03:22 -0400
committerMica White <botahamec@outlook.com>2026-08-26 21:03:22 -0400
commit0a6bd8f2c0a7c79d17f5dc9e64af0b4c6c745166 (patch)
tree30f115f637422040ad64da73eb5edd0552ae4bee
parent55b3a2425b242fbc5c6e471f220eeb8b949e8751 (diff)
Comments
-rw-r--r--src/context.rs12
-rw-r--r--src/context/context.rs6
-rw-r--r--src/context/iterator.rs7
-rw-r--r--src/context/tuple.rs8
4 files changed, 32 insertions, 1 deletions
diff --git a/src/context.rs b/src/context.rs
index 2f9ca64..1707022 100644
--- a/src/context.rs
+++ b/src/context.rs
@@ -66,7 +66,16 @@ pub mod tuple;
/// ```
///
/// [`OwnedLockCollection::context`]: crate::collection::OwnedLockCollection::context
+// This is only available from OwnedLockCollection because it ensures the lock
+// order is the same as the one provided by this function. Tuples may have
+// their elements re-ordered by the compiler.
+//
+// This struct is just a fancy place to hold the ThreadKey while it's being
+// borrowed by multiple other guards.
pub struct LockContext<'l, L> {
+ // Unfortunately there is no better way to get this into the context than to
+ // use an option, initialize to `None` and insert it later. If we returned a
+ // new type, that would move the thread key while it's being borrowed.
key: Option<ThreadKey>,
lockable: &'l L,
}
@@ -165,6 +174,9 @@ pub struct LockingTuple<'context, L, C, Outer = ()> {
/// [`lock`]: `crate::mutex::Mutex::lock`
/// [`try_lock`]: `crate::Mutex::try_lock`
pub struct ContextGuard<'a, Guard, Key> {
+ // The idea behind having this be a shared reference is that it allows
+ // guards to exist at once. And while these borrows exist, the thread key will
+ // not be able to be reused somewhere else.
_key: &'a Key,
guard: Guard,
}
diff --git a/src/context/context.rs b/src/context/context.rs
index adc684f..80a1881 100644
--- a/src/context/context.rs
+++ b/src/context/context.rs
@@ -7,7 +7,9 @@ use crate::{
};
impl<'l, L> LockContext<'l, L> {
- pub(crate) const fn new(lockable: &'l L) -> Self
+ /// Safety: Don't lock the locks in a different order than what the
+ /// LockContext uses
+ pub(crate) const unsafe fn new(lockable: &'l L) -> Self
where
L: OwnedLockable,
{
@@ -56,6 +58,8 @@ impl<'l, L> LockContext<'l, L> {
/// ```
///
/// [`ContextGuard`]: `crate::context::ContextGuard`
+ // The mutable reference ensures that all of the guards, which have a shared
+ // borrow to the context, must be dropped first
pub fn unlock(&mut self) -> Option<ThreadKey> {
self.key.take()
}
diff --git a/src/context/iterator.rs b/src/context/iterator.rs
index cc3bd7c..1eacaea 100644
--- a/src/context/iterator.rs
+++ b/src/context/iterator.rs
@@ -315,6 +315,7 @@ impl<'c, L: 'c + Iterator<Item = &'c I>, I: 'c + RawLock + Lockable, O> LockingI
/// let last = iter.lock_last().unwrap();
/// assert_eq!(**last, 8);
/// ```
+ // I'm honestly not sure why anyone would use this
pub fn lock_last(self) -> Option<ContextGuard<'c, <I as Lockable>::Guard<'c>, ThreadKey>> {
self.iterator.last().map(|lock| unsafe {
lock.raw_write();
@@ -542,6 +543,12 @@ impl<'c, L: 'c + Iterator<Item = &'c I>, I: 'c + RawLock + Sharable, O>
}
}
+// Most of these methods are wrappers around Iterator methods. I didn't
+// implement all of them. Some of them don't make sense for this type of
+// collection, like rposition. Many iterator methods also take closures, and I
+// wasn't sure if people would want a reference to the lock or the value inside
+// the lock. In retrospect, we can't actually allow people to see references to
+// the locks, so maybe we should just settle for values inside locks.
impl<'l, L: Iterator, O> LockingIterator<'l, L, O> {
/// Advances the iterator, without locking the next element in the iterator.
///
diff --git a/src/context/tuple.rs b/src/context/tuple.rs
index 9bca72e..d2a1b0d 100644
--- a/src/context/tuple.rs
+++ b/src/context/tuple.rs
@@ -17,6 +17,9 @@ impl<'c, A, B, O> LockingTuple<'c, A, B, O> {
}
}
+// Some day I need to invent variadic generics for Rust to make this easier for
+// myself
+
macro_rules! lock_impl {
($self: expr, $field: tt) => {
unsafe {
@@ -158,6 +161,10 @@ macro_rules! recurse_iter_impl {
};
}
+// I created these types to help reduce the complexity of the method return
+// types. But now I've added so much functionality that these types are just as
+// complicates. Oh well.
+
type LockReturn<'a, 'context, Guarded, L, C, O> = (
ContextGuard<'a, <Guarded as Lockable>::Guard<'a>, ThreadKey>,
LockingTuple<'context, L, C, O>,
@@ -185,6 +192,7 @@ type RecurseIterReturn<'context, Inner, L, C, O> = LockingIterator<
impl<T, C, Outer> LockingTuple<'_, T, C, Outer> {
/// Exit out of the current scope of the locking tuple into the parent.
+ // Luckily, this only needs one implementation
pub fn exit(self) -> Outer {
self.outer
}