1use ::core::borrow::Borrow;
2use ::core::fmt::Debug;
3use ::core::iter::FusedIterator;
4use ::core::marker::PhantomData;
5use ::core::ops::{Bound, RangeBounds};
6use ::core::sync::atomic::{AtomicPtr, AtomicU64, Ordering};
7use alloc::boxed::Box;
8use alloc::collections::BTreeMap;
9use alloc::sync::Arc;
10use alloc::vec;
11use alloc::vec::Vec;
12use parking_lot::{
13 ArcRwLockReadGuard, ArcRwLockWriteGuard, Mutex, MutexGuard, RawRwLock, RwLock, RwLockReadGuard, RwLockWriteGuard,
14};
15
16use crate::cdc::change::ChangeEvent;
17use crate::concurrent::operation::*;
18use crate::core::constants::DEFAULT_INNER_SIZE;
19use crate::core::node::*;
20
21use super::r#ref::Ref;
22
23#[inline]
29fn yield_now() {
30 #[cfg(feature = "std")]
31 std::thread::yield_now();
32 #[cfg(not(feature = "std"))]
33 ::core::hint::spin_loop();
34}
35
36const ROOT_PUBLICATION_SPIN_LIMIT: usize = 16;
37const STABLE_READ_BLOCKING_FALLBACK_AFTER: usize = 2;
38const PUBLICATION_BACKLOG_DRAIN_THRESHOLD: usize = 64;
39
40type NodeIndex<T, Node> = BTreeMap<T, Arc<RwLock<Node>>>;
41
42const PUBLISHED_ROUTES_PER_CHUNK: usize = 128;
47const PUBLISHED_REBUILD_ROUTES_PER_CHUNK: usize = PUBLISHED_ROUTES_PER_CHUNK * 2 / 3;
50const PUBLISHED_ROUTE_MERGE_THRESHOLD: usize = PUBLISHED_ROUTES_PER_CHUNK * 3 / 4;
51
52struct PublishedChunk<T, Node> {
53 entries: Vec<(T, Arc<RwLock<Node>>)>,
54}
55
56impl<T: Clone, Node> Clone for PublishedChunk<T, Node> {
57 fn clone(&self) -> Self {
58 Self {
59 entries: self.entries.clone(),
60 }
61 }
62}
63
64struct PublishedNodeIndex<T, Node> {
65 chunks: Vec<Arc<PublishedChunk<T, Node>>>,
66 len: usize,
67}
68
69impl<T, Node> Clone for PublishedNodeIndex<T, Node> {
70 fn clone(&self) -> Self {
71 Self {
72 chunks: self.chunks.clone(),
73 len: self.len,
74 }
75 }
76}
77
78impl<T, Node> PublishedNodeIndex<T, Node>
79where
80 T: Ord + Clone,
81{
82 fn from_canonical(index: &NodeIndex<T, Node>) -> Self {
83 let mut chunks = Vec::with_capacity(index.len().div_ceil(PUBLISHED_REBUILD_ROUTES_PER_CHUNK));
84 let mut entries = Vec::with_capacity(PUBLISHED_REBUILD_ROUTES_PER_CHUNK);
85
86 for (key, node) in index {
87 entries.push((key.clone(), node.clone()));
88 if entries.len() == PUBLISHED_REBUILD_ROUTES_PER_CHUNK {
89 chunks.push(Arc::new(PublishedChunk { entries }));
90 entries = Vec::with_capacity(PUBLISHED_REBUILD_ROUTES_PER_CHUNK);
91 }
92 }
93 if !entries.is_empty() {
94 chunks.push(Arc::new(PublishedChunk { entries }));
95 }
96
97 Self {
98 chunks,
99 len: index.len(),
100 }
101 }
102
103 fn iter(&self) -> impl Iterator<Item = (&T, &Arc<RwLock<Node>>)> {
104 self.chunks
105 .iter()
106 .flat_map(|chunk| chunk.entries.iter().map(|(key, node)| (key, node)))
107 }
108
109 fn first_key_value(&self) -> Option<(&T, &Arc<RwLock<Node>>)> {
110 self.chunks.first()?.entries.first().map(|(key, node)| (key, node))
111 }
112
113 fn last_key_value(&self) -> Option<(&T, &Arc<RwLock<Node>>)> {
114 self.chunks.last()?.entries.last().map(|(key, node)| (key, node))
115 }
116
117 fn chunk_for<Q>(&self, key: &Q) -> usize
118 where
119 T: Borrow<Q>,
120 Q: Ord + ?Sized,
121 {
122 self.chunks.partition_point(|chunk| {
123 let max = &chunk.entries.last().expect("published chunks are non-empty").0;
124 <T as Borrow<Q>>::borrow(max) < key
125 })
126 }
127
128 fn first_for_bound<Q>(&self, bound: Bound<&Q>) -> Option<(&T, &Arc<RwLock<Node>>)>
129 where
130 T: Borrow<Q>,
131 Q: Ord + ?Sized,
132 {
133 let key = match bound {
134 Bound::Included(key) | Bound::Excluded(key) => key,
135 Bound::Unbounded => return self.first_key_value(),
136 };
137 let mut chunk_index = self.chunk_for(key);
138 while let Some(chunk) = self.chunks.get(chunk_index) {
139 let entry_index = chunk.entries.partition_point(|(candidate, _)| match bound {
140 Bound::Included(_) => <T as Borrow<Q>>::borrow(candidate) < key,
141 Bound::Excluded(_) => <T as Borrow<Q>>::borrow(candidate) <= key,
142 Bound::Unbounded => false,
143 });
144 if let Some((found, node)) = chunk.entries.get(entry_index) {
145 return Some((found, node));
146 }
147 chunk_index += 1;
148 }
149 None
150 }
151
152 fn insert(&mut self, key: T, node: Arc<RwLock<Node>>) -> Option<Arc<RwLock<Node>>> {
153 if self.chunks.is_empty() {
154 self.chunks.push(Arc::new(PublishedChunk {
155 entries: vec![(key, node)],
156 }));
157 self.len = 1;
158 return None;
159 }
160
161 let mut chunk_index = self.chunk_for(&key);
162 if chunk_index == self.chunks.len() {
163 chunk_index -= 1;
164 }
165 let chunk = Arc::make_mut(&mut self.chunks[chunk_index]);
166 match chunk.entries.binary_search_by(|(candidate, _)| candidate.cmp(&key)) {
167 Ok(index) => Some(::core::mem::replace(&mut chunk.entries[index].1, node)),
168 Err(index) => {
169 chunk.entries.insert(index, (key, node));
170 self.len += 1;
171 if chunk.entries.len() > PUBLISHED_ROUTES_PER_CHUNK {
172 let right = chunk.entries.split_off(chunk.entries.len() / 2);
173 self.chunks
174 .insert(chunk_index + 1, Arc::new(PublishedChunk { entries: right }));
175 }
176 None
177 }
178 }
179 }
180
181 fn remove<Q>(&mut self, key: &Q) -> Option<Arc<RwLock<Node>>>
182 where
183 T: Borrow<Q>,
184 Q: Ord + ?Sized,
185 {
186 let chunk_index = self.chunk_for(key);
187 let entry_index = self
188 .chunks
189 .get(chunk_index)?
190 .entries
191 .binary_search_by(|(candidate, _)| <T as Borrow<Q>>::borrow(candidate).cmp(key))
192 .ok()?;
193 let chunk = Arc::make_mut(&mut self.chunks[chunk_index]);
194 let (_, removed) = chunk.entries.remove(entry_index);
195 self.len -= 1;
196
197 if chunk.entries.is_empty() {
198 self.chunks.remove(chunk_index);
199 } else if chunk_index > 0
200 && self.chunks[chunk_index - 1].entries.len() + self.chunks[chunk_index].entries.len()
201 <= PUBLISHED_ROUTE_MERGE_THRESHOLD
202 {
203 let right = self.chunks.remove(chunk_index);
204 Arc::make_mut(&mut self.chunks[chunk_index - 1])
205 .entries
206 .extend(right.entries.iter().cloned());
207 } else if chunk_index + 1 < self.chunks.len()
208 && self.chunks[chunk_index].entries.len() + self.chunks[chunk_index + 1].entries.len()
209 <= PUBLISHED_ROUTE_MERGE_THRESHOLD
210 {
211 let right = self.chunks.remove(chunk_index + 1);
212 Arc::make_mut(&mut self.chunks[chunk_index])
213 .entries
214 .extend(right.entries.iter().cloned());
215 }
216
217 Some(removed)
218 }
219}
220
221#[inline]
222fn node_identity<Node>(node: &Arc<RwLock<Node>>) -> usize {
223 Arc::as_ptr(node) as usize
227}
228
229struct RetiredIndex<T, Node>(*mut PublishedNodeIndex<T, Node>);
230
231unsafe impl<T: Send, Node: Send> Send for RetiredIndex<T, Node> {}
239
240impl<T, Node> Drop for RetiredIndex<T, Node> {
241 fn drop(&mut self) {
242 unsafe { drop(Box::from_raw(self.0)) }
245 }
246}
247
248struct PublishedIndex<T, Node> {
249 current: AtomicPtr<PublishedNodeIndex<T, Node>>,
250 domain: ps_reclaim::Domain,
251}
252
253impl<T, Node> PublishedIndex<T, Node> {
254 fn new() -> Self {
255 Self {
256 current: AtomicPtr::new(Box::into_raw(Box::new(PublishedNodeIndex {
257 chunks: Vec::new(),
258 len: 0,
259 }))),
260 domain: ps_reclaim::Domain::new(),
261 }
262 }
263}
264
265impl<T, Node> PublishedIndex<T, Node>
266where
267 T: Ord + Clone + Send + 'static,
268 Node: Send + 'static,
269{
270 fn snapshot(&self) -> PublishedNodeIndex<T, Node> {
271 let current = self.current.load(Ordering::Acquire);
272 unsafe { (&*current).clone() }
275 }
276
277 fn replace(&self, replacement: PublishedNodeIndex<T, Node>) -> RetiredIndex<T, Node> {
278 let replacement = Box::into_raw(Box::new(replacement));
281 let retired = self.current.swap(replacement, Ordering::AcqRel);
282 RetiredIndex(retired)
283 }
284
285 fn retire(&self, retired: RetiredIndex<T, Node>) {
286 self.domain.retire(move || drop(retired));
289 }
290
291 fn advance(&self) {
292 if self.domain.pending() >= PUBLICATION_BACKLOG_DRAIN_THRESHOLD {
299 self.domain.advance();
300 }
301 }
302}
303
304impl<T, Node> Drop for PublishedIndex<T, Node> {
305 fn drop(&mut self) {
306 let current = *self.current.get_mut();
307 unsafe { drop(Box::from_raw(current)) }
310 }
311}
312
313pub(crate) struct Topology<T, Node> {
322 index: RwLock<NodeIndex<T, Node>>,
323 published_keys: Mutex<BTreeMap<usize, T>>,
327 published: PublishedIndex<T, Node>,
328 generation: AtomicU64,
331}
332
333impl<T, Node> Debug for Topology<T, Node> {
334 fn fmt(&self, formatter: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
335 formatter
336 .debug_struct("Topology")
337 .field("nodes", &self.index.read().len())
338 .field("generation", &self.generation.load(Ordering::Relaxed))
339 .finish()
340 }
341}
342
343impl<T, Node> Topology<T, Node> {
344 fn new() -> Self {
345 Self {
346 index: RwLock::new(BTreeMap::new()),
347 published_keys: Mutex::new(BTreeMap::new()),
348 published: PublishedIndex::new(),
349 generation: AtomicU64::new(0),
350 }
351 }
352
353 #[inline]
354 pub(crate) fn read(&self) -> RwLockReadGuard<'_, NodeIndex<T, Node>> {
355 self.index.read()
356 }
357}
358
359impl<T, Node> Topology<T, Node>
360where
361 T: Ord + Clone + Send + 'static,
362 Node: Send + 'static,
363{
364 #[inline]
365 fn write(&self) -> TopologyWriteGuard<'_, T, Node> {
366 let index = self.index.write();
367 self.generation.fetch_add(1, Ordering::AcqRel);
368 TopologyWriteGuard {
369 topology: self,
370 index: Some(index),
371 published: None,
372 published_keys: None,
373 publish: true,
374 dirty: false,
375 }
376 }
377
378 #[inline]
386 fn write_rekey(&self) -> TopologyWriteGuard<'_, T, Node> {
387 let index = self.index.write();
388 TopologyWriteGuard {
389 topology: self,
390 index: Some(index),
391 published: None,
392 published_keys: None,
393 publish: false,
394 dirty: false,
395 }
396 }
397
398 #[inline]
399 fn try_write(&self) -> Option<TopologyWriteGuard<'_, T, Node>> {
400 let index = self.index.try_write()?;
401 self.generation.fetch_add(1, Ordering::AcqRel);
402 Some(TopologyWriteGuard {
403 topology: self,
404 index: Some(index),
405 published: None,
406 published_keys: None,
407 publish: true,
408 dirty: false,
409 })
410 }
411}
412
413pub(crate) struct TopologyWriteGuard<'a, T, Node>
414where
415 T: Ord + Clone + Send + 'static,
416 Node: Send + 'static,
417{
418 topology: &'a Topology<T, Node>,
419 index: Option<RwLockWriteGuard<'a, NodeIndex<T, Node>>>,
422 published: Option<PublishedNodeIndex<T, Node>>,
423 published_keys: Option<MutexGuard<'a, BTreeMap<usize, T>>>,
424 publish: bool,
425 dirty: bool,
426}
427
428impl<T, Node> ::core::ops::Deref for TopologyWriteGuard<'_, T, Node>
429where
430 T: Ord + Clone + Send + 'static,
431 Node: Send + 'static,
432{
433 type Target = NodeIndex<T, Node>;
434
435 fn deref(&self) -> &Self::Target {
436 self.index.as_deref().expect("topology guard already released")
437 }
438}
439
440impl<'a, T, Node> TopologyWriteGuard<'a, T, Node>
441where
442 T: Ord + Clone + Send + 'static,
443 Node: Send + 'static,
444{
445 pub(crate) fn enable_publication(&mut self) {
446 if self.publish {
447 return;
448 }
449 debug_assert!(
450 !self.dirty,
451 "publication must be enabled before mutating an opt-out topology guard"
452 );
453 self.topology.generation.fetch_add(1, Ordering::AcqRel);
458 self.publish = true;
459 }
460
461 fn ensure_publication_snapshot(&mut self) {
462 if self.published.is_none() {
463 self.published_keys = Some(self.topology.published_keys.lock());
464 self.published = Some(self.topology.published.snapshot());
465 }
466 }
467
468 fn rebuild_publication(&mut self) {
475 if self.published_keys.is_none() {
476 self.published_keys = Some(self.topology.published_keys.lock());
477 }
478 let canonical = self.index.as_deref().expect("topology guard already released");
479 let rebuilt = PublishedNodeIndex::from_canonical(canonical);
480 let rebuilt_keys = canonical
481 .iter()
482 .map(|(key, node)| (node_identity(node), key.clone()))
483 .collect();
484 **self
485 .published_keys
486 .as_mut()
487 .expect("publication identity lock was initialized") = rebuilt_keys;
488 self.published = Some(rebuilt);
489 self.dirty = true;
490 }
491
492 pub(crate) fn is_last_node(&self, node: &Arc<RwLock<Node>>) -> bool {
493 self.index
494 .as_deref()
495 .and_then(BTreeMap::last_key_value)
496 .is_some_and(|(_, candidate)| Arc::ptr_eq(candidate, node))
497 }
498
499 pub(crate) fn rekey_last_node(&mut self, old_key: &T, new_key: T, node: Arc<RwLock<Node>>) {
507 debug_assert!(!self.publish, "last-node rekey must use the opt-out guard");
508 debug_assert!(
509 !self.dirty,
510 "an opt-out guard may perform only one explicit last-node rekey"
511 );
512 debug_assert!(
513 self.is_last_node(&node),
514 "only the canonical last node may skip publication"
515 );
516
517 let index = self.index.as_deref_mut().expect("topology guard already released");
518 let removed = index.remove(old_key);
519 debug_assert!(
520 removed.as_ref().is_some_and(|removed| Arc::ptr_eq(removed, &node)),
521 "last-node rekey must remove its expected canonical route"
522 );
523 let replaced = index.insert(new_key, node);
524 debug_assert!(
525 replaced.is_none(),
526 "last-node rekey must not collide with another canonical route"
527 );
528 self.dirty = true;
529 }
530
531 fn repair_last_route_before_attach(&mut self) {
535 debug_assert!(self.publish, "attachment repair requires publication");
536 let Some((canonical_key, last_node)) = self
537 .index
538 .as_deref()
539 .expect("topology guard already released")
540 .last_key_value()
541 .map(|(key, node)| (key.clone(), node.clone()))
542 else {
543 return;
544 };
545
546 self.ensure_publication_snapshot();
547 let published_key = self
548 .published_keys
549 .as_ref()
550 .expect("publication identity map initialized")
551 .get(&node_identity(&last_node))
552 .cloned();
553 let Some(published_key) = published_key else {
554 self.rebuild_publication();
555 return;
556 };
557 if published_key == canonical_key {
558 return;
559 }
560
561 let repaired_consistently = {
562 let published = self.published.as_mut().expect("publication snapshot initialized");
563 let published_keys = self
564 .published_keys
565 .as_mut()
566 .expect("publication identity map initialized");
567 let removed = published.remove(&published_key);
568 let displaced = published.insert(canonical_key.clone(), last_node.clone());
569 published_keys.insert(node_identity(&last_node), canonical_key);
570 removed.is_some_and(|old_node| Arc::ptr_eq(&old_node, &last_node)) && displaced.is_none()
571 };
572 if !repaired_consistently {
573 self.rebuild_publication();
574 } else {
575 self.dirty = true;
576 }
577 }
578
579 pub(crate) fn insert(&mut self, key: T, node: Arc<RwLock<Node>>) -> Option<Arc<RwLock<Node>>> {
580 debug_assert!(self.publish, "generic topology insertion requires publication");
581 let replaced = self
582 .index
583 .as_deref_mut()
584 .expect("topology guard already released")
585 .insert(key.clone(), node.clone());
586 self.dirty = true;
587
588 if self.publish {
589 self.ensure_publication_snapshot();
590 if let Some(replaced) = &replaced {
591 let removed_consistently = {
592 let published = self.published.as_mut().expect("publication snapshot initialized");
593 let published_keys = self
594 .published_keys
595 .as_mut()
596 .expect("publication identity map initialized");
597 published_keys
598 .remove(&node_identity(replaced))
599 .and_then(|old_key| published.remove(&old_key))
600 .is_some_and(|old_node| Arc::ptr_eq(&old_node, replaced))
601 };
602 if !removed_consistently {
603 self.rebuild_publication();
604 return Some(replaced.clone());
605 }
606 }
607
608 let displaced = self
609 .published
610 .as_mut()
611 .expect("publication snapshot initialized")
612 .insert(key.clone(), node.clone());
613 self.published_keys
614 .as_mut()
615 .expect("publication identity map initialized")
616 .insert(node_identity(&node), key);
617 if displaced.is_some_and(|old_node| !Arc::ptr_eq(&old_node, &node)) {
618 self.rebuild_publication();
623 }
624 }
625
626 replaced
627 }
628
629 pub(crate) fn remove<Q>(&mut self, key: &Q) -> Option<Arc<RwLock<Node>>>
630 where
631 T: Borrow<Q>,
632 Q: Ord + ?Sized,
633 {
634 debug_assert!(self.publish, "generic topology removal requires publication");
635 let removed = self
636 .index
637 .as_deref_mut()
638 .expect("topology guard already released")
639 .remove(key)?;
640 self.dirty = true;
641
642 if self.publish {
643 self.ensure_publication_snapshot();
644 let removed_consistently = {
645 let published = self.published.as_mut().expect("publication snapshot initialized");
646 let published_keys = self
647 .published_keys
648 .as_mut()
649 .expect("publication identity map initialized");
650 published_keys
651 .remove(&node_identity(&removed))
652 .and_then(|route_key| published.remove::<T>(&route_key))
653 .is_some_and(|route_node| Arc::ptr_eq(&route_node, &removed))
654 };
655 if !removed_consistently {
656 self.rebuild_publication();
657 }
658 }
659
660 Some(removed)
661 }
662}
663
664impl<T, Node> Drop for TopologyWriteGuard<'_, T, Node>
665where
666 T: Ord + Clone + Send + 'static,
667 Node: Send + 'static,
668{
669 fn drop(&mut self) {
670 #[cfg(debug_assertions)]
671 if self.publish && self.dirty {
672 let canonical = self.index.as_deref().expect("topology guard exists while validating");
673 let published = self.published.as_ref().expect("publishing guard carries snapshot");
674 let published_keys = self
675 .published_keys
676 .as_deref()
677 .expect("publishing guard carries identity map");
678 debug_assert_eq!(
679 canonical.len(),
680 published.len,
681 "canonical and published node counts diverged"
682 );
683 debug_assert_eq!(
684 canonical.len(),
685 published_keys.len(),
686 "canonical and published identity counts diverged"
687 );
688 for ((_, canonical_node), (route_key, route_node)) in canonical.iter().zip(published.iter()) {
689 debug_assert!(
690 Arc::ptr_eq(route_node, canonical_node),
691 "canonical and published node order diverged"
692 );
693 debug_assert!(
694 published_keys.get(&node_identity(canonical_node)) == Some(route_key),
695 "published identity key does not match the route index"
696 );
697 }
698 }
699
700 if !self.publish {
701 drop(self.published_keys.take());
702 drop(self.index.take());
703 return;
704 }
705 if !self.dirty {
706 self.topology.generation.fetch_add(1, Ordering::Release);
707 drop(self.published_keys.take());
708 drop(self.index.take());
709 return;
710 }
711 let retired = self.topology.published.replace(
712 self.published
713 .take()
714 .expect("publishing guard must carry a read snapshot"),
715 );
716 self.topology.generation.fetch_add(1, Ordering::Release);
720 self.topology.published.retire(retired);
721 drop(self.published_keys.take());
722 drop(self.index.take());
723 self.topology.published.advance();
724 }
725}
726
727pub(crate) fn no_identity_adoption<T>(_stored: &T, _incoming: &mut T) {}
731
732fn first_for_borrowed_bound<'a, T, Q, V>(
739 index: &'a BTreeMap<T, V>,
740 bound: Bound<&Q>,
741 borrow_order_matches: bool,
742) -> Option<(&'a T, &'a V)>
743where
744 T: Ord + Borrow<Q>,
745 Q: Ord + ?Sized,
746{
747 if borrow_order_matches {
748 return index.range::<Q, _>((bound, Bound::Unbounded)).next();
749 }
750
751 index.iter().find(|(key, _)| match bound {
752 Bound::Included(value) => <T as Borrow<Q>>::borrow(key) >= value,
753 Bound::Excluded(value) => <T as Borrow<Q>>::borrow(key) > value,
754 Bound::Unbounded => true,
755 })
756}
757
758fn first_published_for_borrowed_bound<'a, T, Q, V>(
759 index: &'a PublishedNodeIndex<T, V>,
760 bound: Bound<&Q>,
761 borrow_order_matches: bool,
762) -> Option<(&'a T, &'a Arc<RwLock<V>>)>
763where
764 T: Ord + Clone + Borrow<Q>,
765 Q: Ord + ?Sized,
766{
767 if borrow_order_matches {
768 return index.first_for_bound(bound);
769 }
770
771 index.iter().find(|(key, _)| match bound {
772 Bound::Included(value) => <T as Borrow<Q>>::borrow(key) >= value,
773 Bound::Excluded(value) => <T as Borrow<Q>>::borrow(key) > value,
774 Bound::Unbounded => true,
775 })
776}
777
778fn node_for_borrowed_end<'a, T, Q, V>(
779 index: &'a BTreeMap<T, V>,
780 end: &Q,
781 borrow_order_matches: bool,
782) -> Option<(&'a T, &'a V)>
783where
784 T: Ord + Borrow<Q>,
785 Q: Ord + ?Sized,
786{
787 if borrow_order_matches {
788 return index
789 .range::<Q, _>((Bound::Included(end), Bound::Unbounded))
790 .next()
791 .or_else(|| index.last_key_value());
792 }
793
794 let mut last_equal = None;
795 for entry @ (key, _) in index {
796 match <T as Borrow<Q>>::borrow(key).cmp(end) {
797 ::core::cmp::Ordering::Less => {}
798 ::core::cmp::Ordering::Equal => last_equal = Some(entry),
799 ::core::cmp::Ordering::Greater => return Some(entry),
803 }
804 }
805 last_equal.or_else(|| index.last_key_value())
806}
807
808#[derive(Debug)]
864pub struct BTreeSet<T, Node = Vec<T>>
865where
866 T: Ord + Clone + 'static,
867 Node: NodeLike<T>,
868{
869 pub(crate) index: Topology<T, Node>,
875 node_capacity: usize,
876 borrow_order_matches: bool,
880 #[cfg(feature = "cdc")]
881 event_id: AtomicU64,
885}
886impl<T: Ord + Clone + 'static, Node: NodeLike<T>> Default for BTreeSet<T, Node> {
887 fn default() -> Self {
888 Self {
889 index: Topology::new(),
890 node_capacity: DEFAULT_INNER_SIZE,
891 borrow_order_matches: true,
892 #[cfg(feature = "cdc")]
893 event_id: AtomicU64::new(0),
894 }
895 }
896}
897
898impl<T, Node> BTreeSet<T, Node>
899where
900 T: Debug + Ord + Clone + Send,
901 Node: NodeLike<T> + Send + 'static,
902{
903 pub fn new() -> Self {
904 Self::default()
905 }
906 pub fn with_maximum_node_size(node_capacity: usize) -> Self {
916 Self {
917 index: Topology::new(),
918 node_capacity,
919 borrow_order_matches: true,
920 #[cfg(feature = "cdc")]
921 event_id: AtomicU64::new(0),
922 }
923 }
924 pub(crate) fn with_grouped_borrow_routing(mut self) -> Self {
925 self.borrow_order_matches = false;
926 self
927 }
928 pub fn attach_node(&self, node: Node) {
929 self.attach_nodes(::core::iter::once(node));
930 }
931
932 pub fn attach_nodes(&self, nodes: impl IntoIterator<Item = Node>) {
939 let mut nodes = nodes.into_iter().peekable();
940 if nodes.peek().is_none() {
941 return;
942 }
943
944 let mut index = self.index.write();
945 index.repair_last_route_before_attach();
946 for node in nodes {
947 let node_id = node
948 .max()
949 .cloned()
950 .expect("node should contain at least one value to be correct node");
951 index.insert(node_id, Arc::new(RwLock::new(node)));
952 }
953 }
954
955 #[cfg(feature = "cdc")]
956 pub(crate) fn export_topology(&self) -> (usize, Vec<Vec<T>>) {
957 let index = self.index.read();
958 let nodes = index
959 .values()
960 .map(|node| node.read().iter().cloned().collect())
961 .collect();
962 (self.node_capacity, nodes)
963 }
964
965 #[allow(clippy::type_complexity)]
966 fn put_checked_inner<const EMIT_CDC: bool>(
969 &self,
970 value: T,
971 adopt: fn(&T, &mut T),
972 ) -> Result<(Option<T>, Vec<ChangeEvent<T>>), (ArcRwLockWriteGuard<RawRwLock, Node>, usize, T)> {
973 loop {
974 let mut cdc = vec![];
975 let index = self.index.read();
976 let target_node_entry = match index.range(value.clone()..).next() {
977 Some(entry) => entry,
978 None => {
979 if let Some(last) = index.last_key_value() {
980 last
981 } else {
982 drop(index);
983 let mut spins = 0;
984 let mut index = loop {
985 if let Some(guard) = self.index.try_write() {
986 break guard;
987 }
988 if spins >= ROOT_PUBLICATION_SPIN_LIMIT {
989 break self.index.write();
993 }
994 spins += 1;
995 ::core::hint::spin_loop();
996 };
997 if !index.is_empty() {
1000 continue;
1001 }
1002
1003 let mut first_node = Node::with_capacity(self.node_capacity);
1004 first_node.insert(value.clone());
1005
1006 #[cfg(feature = "cdc")]
1007 if EMIT_CDC {
1008 let node_insertion = ChangeEvent::CreateNode {
1009 event_id: self.event_id.fetch_add(1, Ordering::Relaxed).into(),
1012 max_value: value.clone(),
1013 };
1014 cdc.push(node_insertion);
1015 }
1016
1017 index.insert(value, Arc::new(RwLock::new(first_node)));
1018
1019 return Ok((None, cdc));
1020 }
1021 }
1022 };
1023
1024 let mut node_guard = target_node_entry.1.clone().write_arc();
1025
1026 #[allow(unused_assignments)]
1027 let mut operation = None;
1028 if !node_guard.need_to_split(self.node_capacity, &value) {
1029 let old_max = node_guard.max().cloned();
1030 let (inserted, idx) = NodeLike::insert(&mut *node_guard, value.clone());
1031 if inserted {
1032 #[cfg(feature = "cdc")]
1033 if EMIT_CDC {
1034 let node_element_insertion = ChangeEvent::InsertAt {
1035 event_id: self.event_id.fetch_add(1, Ordering::Relaxed).into(),
1038 max_value: old_max.clone().unwrap_or(value.clone()),
1039 value: value.clone(),
1040 index: idx,
1041 };
1042 cdc.push(node_element_insertion);
1043 }
1044
1045 if node_guard.max().cloned() == old_max {
1046 return Ok((None, cdc));
1047 }
1048
1049 operation = Some(Operation::UpdateMax(
1061 target_node_entry.1.clone(),
1062 target_node_entry.0.clone(),
1063 ));
1064 } else {
1065 return Err((node_guard, idx, old_max.unwrap()));
1066 }
1067 } else {
1068 operation = Some(Operation::Split(
1069 target_node_entry.1.clone(),
1070 target_node_entry.0.clone(),
1071 value.clone(),
1072 ));
1073 }
1074
1075 drop(node_guard);
1076 drop(index);
1077
1078 let op = operation.unwrap();
1079 let mut index = match &op {
1080 Operation::UpdateMax(_, _) => self.index.write_rekey(),
1081 Operation::Split(_, _, _) | Operation::MakeUnreachable(_, _) => self.index.write(),
1082 };
1083 match &op {
1084 Operation::Split(_, _, _) => {
1085 if let Ok((value, value_cdc)) = op.commit::<EMIT_CDC>(&mut index, adopt) {
1086 #[cfg(feature = "cdc")]
1087 if EMIT_CDC {
1088 for unassigned_event in value_cdc {
1089 let event_id = self.event_id.fetch_add(1, Ordering::Relaxed).into();
1090 cdc.push(unassigned_event.assign_id(event_id));
1091 }
1092 }
1093 return Ok((value, cdc));
1094 } else {
1095 continue;
1096 }
1097 }
1098 Operation::UpdateMax(_, _) => {
1099 return if let Ok((value, value_cdc)) = op.commit::<EMIT_CDC>(&mut index, adopt) {
1100 #[cfg(feature = "cdc")]
1101 if EMIT_CDC {
1102 for unassigned_event in value_cdc {
1103 let event_id = self.event_id.fetch_add(1, Ordering::Relaxed).into();
1104 cdc.push(unassigned_event.assign_id(event_id));
1105 }
1106 }
1107 Ok((value, cdc))
1108 } else {
1109 Ok((None, cdc))
1110 }
1111 }
1112 Operation::MakeUnreachable(_, _) => unreachable!(),
1113 }
1114 }
1115 }
1116 fn put_inner<const EMIT_CDC: bool>(&self, value: T, adopt: fn(&T, &mut T)) -> (Option<T>, Vec<ChangeEvent<T>>) {
1117 match self.put_checked_inner::<EMIT_CDC>(value.clone(), adopt) {
1118 Ok(res) => res,
1119 Err((mut node_guard, idx, max)) => {
1120 let mut value = value;
1124 if let Some(stored) = node_guard.get_ith(idx) {
1125 adopt(stored, &mut value);
1126 }
1127 let mut cdc = vec![];
1128 #[cfg(feature = "cdc")]
1129 if EMIT_CDC {
1130 if node_guard.len() == 1 {
1131 let node_removal = ChangeEvent::RemoveNode {
1132 event_id: self.event_id.fetch_add(1, Ordering::Relaxed).into(),
1135 max_value: max.clone(),
1136 };
1137 let node_insertion = ChangeEvent::CreateNode {
1138 event_id: self.event_id.fetch_add(1, Ordering::Relaxed).into(),
1140 max_value: value.clone(),
1141 };
1142 cdc.push(node_removal);
1143 cdc.push(node_insertion);
1144 } else if idx == node_guard.len() - 1 {
1145 let new_max = if node_guard.len() <= 1 {
1146 None
1147 } else {
1148 node_guard.get_ith(node_guard.len() - 2)
1149 };
1150 let node_element_removal = ChangeEvent::RemoveAt {
1151 event_id: self.event_id.fetch_add(1, Ordering::Relaxed).into(),
1154 max_value: max.clone(),
1155 value: value.clone(),
1156 index: idx,
1157 };
1158 let node_element_insertion = ChangeEvent::InsertAt {
1159 event_id: self.event_id.fetch_add(1, Ordering::Relaxed).into(),
1161 max_value: new_max.expect("length was checked so should be ok").clone(),
1162 value: value.clone(),
1163 index: idx,
1164 };
1165 cdc.push(node_element_removal);
1166 cdc.push(node_element_insertion);
1167 } else {
1168 let node_element_removal = ChangeEvent::RemoveAt {
1169 event_id: self.event_id.fetch_add(1, Ordering::Relaxed).into(),
1172 max_value: max.clone(),
1173 value: value.clone(),
1174 index: idx,
1175 };
1176 let node_element_insertion = ChangeEvent::InsertAt {
1177 event_id: self.event_id.fetch_add(1, Ordering::Relaxed).into(),
1179 max_value: max.clone(),
1180 value: value.clone(),
1181 index: idx,
1182 };
1183 cdc.push(node_element_removal);
1184 cdc.push(node_element_insertion);
1185 }
1186 }
1187
1188 (NodeLike::replace(&mut *node_guard, idx, value.clone()), cdc)
1189 }
1190 }
1191 }
1192
1193 pub(crate) fn put(&self, value: T) -> Option<T> {
1194 self.put_inner::<false>(value, no_identity_adoption).0
1195 }
1196
1197 #[cfg(feature = "multimap")]
1198 pub(crate) fn put_with(&self, value: T, adopt: fn(&T, &mut T)) -> Option<T> {
1199 self.put_inner::<false>(value, adopt).0
1200 }
1201
1202 #[allow(clippy::type_complexity)]
1203 pub(crate) fn put_checked(
1204 &self,
1205 value: T,
1206 ) -> Result<(Option<T>, Vec<ChangeEvent<T>>), (ArcRwLockWriteGuard<RawRwLock, Node>, usize, T)> {
1207 self.put_checked_inner::<false>(value, no_identity_adoption)
1208 }
1209
1210 pub(crate) fn put_cdc(&self, value: T) -> (Option<T>, Vec<ChangeEvent<T>>) {
1211 self.put_inner::<true>(value, no_identity_adoption)
1212 }
1213
1214 #[cfg(all(feature = "multimap", feature = "cdc"))]
1215 pub(crate) fn put_cdc_with(&self, value: T, adopt: fn(&T, &mut T)) -> (Option<T>, Vec<ChangeEvent<T>>) {
1216 self.put_inner::<true>(value, adopt)
1217 }
1218
1219 #[allow(clippy::type_complexity)]
1220 pub(crate) fn put_cdc_checked(
1221 &self,
1222 value: T,
1223 ) -> Result<(Option<T>, Vec<ChangeEvent<T>>), (ArcRwLockWriteGuard<RawRwLock, Node>, usize, T)> {
1224 self.put_checked_inner::<true>(value, no_identity_adoption)
1225 }
1226
1227 pub fn insert(&self, value: T) -> bool {
1248 self.put(value).is_none()
1249 }
1250 fn remove_inner<const EMIT_CDC: bool, Q>(&self, value: &Q) -> (Option<T>, Vec<ChangeEvent<T>>)
1253 where
1254 T: Borrow<Q>,
1255 Q: Ord + ?Sized,
1256 {
1257 let mut cdc = vec![];
1258 let index = self.index.read();
1259 if let Some(target_node_entry) =
1266 first_for_borrowed_bound(&index, Bound::Included(value), self.borrow_order_matches)
1267 .or_else(|| index.last_key_value())
1268 {
1269 let mut node_guard = target_node_entry.1.clone().write_arc();
1270 let old_max = node_guard.max().cloned();
1271 let deleted = NodeLike::delete(&mut *node_guard, value);
1272 if deleted.is_none() {
1273 return (None, cdc);
1274 }
1275 let (deleted, idx) = deleted.expect("should be ok as checked before");
1276
1277 let operation = if node_guard.len() > 0 {
1278 #[cfg(feature = "cdc")]
1279 if EMIT_CDC {
1280 let node_element_removal = ChangeEvent::RemoveAt {
1281 event_id: self.event_id.fetch_add(1, Ordering::Relaxed).into(),
1284 max_value: old_max.clone().expect("Max value should exist as Node is not empty"),
1285 value: deleted.clone(),
1286 index: idx,
1287 };
1288 cdc.push(node_element_removal);
1289 }
1290
1291 if old_max.as_ref() == node_guard.max() {
1292 return (Some(deleted), cdc);
1293 }
1294
1295 Some(Operation::UpdateMax(
1300 target_node_entry.1.clone(),
1301 target_node_entry.0.clone(),
1302 ))
1303 } else {
1304 Some(Operation::MakeUnreachable(
1305 target_node_entry.1.clone(),
1306 target_node_entry.0.clone(),
1307 ))
1308 };
1309
1310 drop(node_guard);
1311 drop(index);
1312
1313 let operation = operation.unwrap();
1314 let mut index = match &operation {
1315 Operation::UpdateMax(_, _) => self.index.write_rekey(),
1316 Operation::Split(_, _, _) | Operation::MakeUnreachable(_, _) => self.index.write(),
1317 };
1318
1319 return if let Ok((_, value_cdc)) = operation.commit::<EMIT_CDC>(&mut index, no_identity_adoption) {
1320 #[cfg(feature = "cdc")]
1321 if EMIT_CDC {
1322 for unassigned_event in value_cdc {
1323 let event_id = self.event_id.fetch_add(1, Ordering::Relaxed).into();
1324 cdc.push(unassigned_event.assign_id(event_id));
1325 }
1326 }
1327 (Some(deleted), cdc)
1328 } else {
1329 (Some(deleted), cdc)
1330 };
1331 }
1332
1333 (None, vec![])
1334 }
1335
1336 pub fn remove_cdc<Q>(&self, value: &Q) -> (Option<T>, Vec<ChangeEvent<T>>)
1337 where
1338 T: Borrow<Q>,
1339 Q: Ord + ?Sized,
1340 {
1341 self.remove_inner::<true, Q>(value)
1342 }
1343 pub fn remove<Q>(&self, value: &Q) -> Option<T>
1362 where
1363 T: Borrow<Q>,
1364 Q: Ord + ?Sized,
1365 {
1366 self.remove_inner::<false, Q>(value).0
1367 }
1368
1369 #[inline(always)]
1375 fn lock_node_for_value_optimistic<Q>(&self, value: &Q) -> Option<ArcRwLockReadGuard<RawRwLock, Node>>
1376 where
1377 T: Borrow<Q>,
1378 Q: Ord + ?Sized,
1379 {
1380 let node = {
1381 let index = self.index.read();
1382 match first_for_borrowed_bound(&index, Bound::Included(value), self.borrow_order_matches) {
1383 Some((_, node)) => Some(node.clone()),
1384 None => index
1385 .last_key_value()
1386 .map(|(_, node)| node.clone())
1387 .or_else(|| index.first_key_value().map(|(_, node)| node.clone())),
1388 }
1389 }?;
1390 Some(node.read_arc())
1391 }
1392
1393 #[inline(always)]
1400 fn lock_node_for_value<Q>(&self, value: &Q) -> Option<ArcRwLockReadGuard<RawRwLock, Node>>
1401 where
1402 T: Borrow<Q>,
1403 Q: Ord + ?Sized,
1404 {
1405 let mut retries = 0;
1406 let mut writer_spins = 0;
1407
1408 loop {
1409 let generation = self.index.generation.load(Ordering::Acquire);
1410 if !generation.is_multiple_of(2) {
1411 if writer_spins < ROOT_PUBLICATION_SPIN_LIMIT {
1412 writer_spins += 1;
1413 ::core::hint::spin_loop();
1414 } else {
1415 yield_now();
1416 }
1417 continue;
1418 }
1419 writer_spins = 0;
1420
1421 if retries >= STABLE_READ_BLOCKING_FALLBACK_AFTER {
1422 let index = self.index.read();
1426 let node = match first_for_borrowed_bound(&index, Bound::Included(value), self.borrow_order_matches) {
1427 Some((_, node)) => Some(node.clone()),
1428 None => index
1429 .last_key_value()
1430 .map(|(_, node)| node.clone())
1431 .or_else(|| index.first_key_value().map(|(_, node)| node.clone())),
1432 }?;
1433 let node_guard = node.read_arc();
1434 drop(index);
1435 return Some(node_guard);
1436 }
1437
1438 let pin = self.index.published.domain.pin();
1439 let snapshot = self.index.published.current.load(Ordering::Acquire);
1440 let index = unsafe { &*snapshot };
1443 let node =
1444 match first_published_for_borrowed_bound(index, Bound::Included(value), self.borrow_order_matches) {
1445 Some((_, node)) => Some(node.clone()),
1446 None => index
1447 .last_key_value()
1448 .map(|(_, node)| node.clone())
1449 .or_else(|| index.first_key_value().map(|(_, node)| node.clone())),
1450 };
1451 let Some(node) = node else {
1452 if self.index.generation.load(Ordering::Acquire) == generation {
1453 return None;
1454 }
1455 retries += 1;
1456 continue;
1457 };
1458
1459 drop(pin);
1463 let node_guard = node.read_arc();
1464 if self.index.generation.load(Ordering::Acquire) == generation {
1465 return Some(node_guard);
1466 }
1467 retries += 1;
1468 }
1469 }
1470
1471 #[inline(always)]
1472 fn get_with_guard<Q, R>(
1473 node_guard: ArcRwLockReadGuard<RawRwLock, Node>,
1474 value: &Q,
1475 read: impl FnOnce(&T) -> R,
1476 ) -> Option<R>
1477 where
1478 T: Borrow<Q>,
1479 Q: Ord + ?Sized,
1480 {
1481 let position = node_guard.try_select(value)?;
1482 node_guard.get_ith(position).map(read)
1483 }
1484
1485 #[inline(always)]
1486 pub(crate) fn get_with<Q, R>(&self, value: &Q, read: impl FnOnce(&T) -> R) -> Option<R>
1487 where
1488 T: Borrow<Q>,
1489 Q: Ord + ?Sized,
1490 {
1491 let mut retries = 0;
1492 let mut writer_spins = 0;
1493 let mut read = Some(read);
1494
1495 loop {
1496 let generation = self.index.generation.load(Ordering::Acquire);
1497 if !generation.is_multiple_of(2) {
1498 if writer_spins < ROOT_PUBLICATION_SPIN_LIMIT {
1499 writer_spins += 1;
1500 ::core::hint::spin_loop();
1501 } else {
1502 yield_now();
1503 }
1504 continue;
1505 }
1506 writer_spins = 0;
1507
1508 if retries >= STABLE_READ_BLOCKING_FALLBACK_AFTER {
1509 let index = self.index.read();
1510 let node = first_for_borrowed_bound(&index, Bound::Included(value), self.borrow_order_matches)
1511 .or_else(|| index.last_key_value())
1512 .or_else(|| index.first_key_value())
1513 .map(|(_, node)| node.clone())?;
1514 let node_guard = node.read_arc();
1515 drop(index);
1516 let position = node_guard.try_select(value)?;
1517 return node_guard
1518 .get_ith(position)
1519 .map(read.take().expect("read closure is consumed only on return"));
1520 }
1521
1522 let pin = self.index.published.domain.pin();
1523 let snapshot = self.index.published.current.load(Ordering::Acquire);
1524 let index = unsafe { &*snapshot };
1527 let node = first_published_for_borrowed_bound(index, Bound::Included(value), self.borrow_order_matches)
1528 .or_else(|| index.last_key_value())
1529 .or_else(|| index.first_key_value())
1530 .map(|(_, node)| node);
1531 let Some(node) = node else {
1532 if self.index.generation.load(Ordering::Acquire) == generation {
1533 return None;
1534 }
1535 retries += 1;
1536 continue;
1537 };
1538
1539 if let Some(node_guard) = node.try_read() {
1545 if self.index.generation.load(Ordering::Acquire) != generation {
1546 retries += 1;
1547 continue;
1548 }
1549 let position = node_guard.try_select(value)?;
1550 return node_guard
1551 .get_ith(position)
1552 .map(read.take().expect("read closure is consumed only on return"));
1553 }
1554
1555 let node = node.clone();
1556 drop(pin);
1557 let node_guard = node.read_arc();
1558 if self.index.generation.load(Ordering::Acquire) != generation {
1559 retries += 1;
1560 continue;
1561 }
1562 let position = node_guard.try_select(value)?;
1563 return node_guard
1564 .get_ith(position)
1565 .map(read.take().expect("read closure is consumed only on return"));
1566 }
1567 }
1568
1569 #[inline(always)]
1570 pub(crate) fn get_with_optimistic<Q, R>(&self, value: &Q, read: impl FnOnce(&T) -> R) -> Option<R>
1571 where
1572 T: Borrow<Q>,
1573 Q: Ord + ?Sized,
1574 {
1575 Self::get_with_guard(self.lock_node_for_value_optimistic(value)?, value, read)
1576 }
1577
1578 pub fn contains<Q>(&self, value: &Q) -> bool
1594 where
1595 T: Borrow<Q>,
1596 Q: Ord + ?Sized,
1597 {
1598 self.get_with(value, |_| ()).is_some()
1599 }
1600 pub fn get<'a, Q>(&'a self, value: &'a Q) -> Option<Ref<T, Node>>
1601 where
1602 T: Borrow<Q>,
1603 Q: Ord + ?Sized,
1604 {
1605 if let Some(node_guard) = self.lock_node_for_value(value) {
1606 let potential_position = node_guard.try_select(value);
1607
1608 if let Some(position) = potential_position {
1609 return Some(Ref {
1610 node_guard,
1611 position,
1612 phantom_data: PhantomData,
1613 });
1614 }
1615 }
1616
1617 None
1618 }
1619
1620 pub fn len(&self) -> usize {
1621 self.index.read().values().map(|node| node.read().len()).sum()
1622 }
1623 pub fn is_empty(&self) -> bool {
1624 self.index.read().values().all(|node| node.read().is_empty())
1625 }
1626 pub fn capacity(&self) -> usize {
1627 self.index
1628 .read()
1629 .values()
1630 .map(|node| {
1631 let guard = node.read();
1632 guard.capacity()
1633 })
1634 .sum()
1635 }
1636 pub fn node_count(&self) -> usize {
1637 self.index.read().len()
1638 }
1639}
1640
1641impl<T> FromIterator<T> for BTreeSet<T>
1642where
1643 T: Debug + Ord + Clone + Send,
1644{
1645 fn from_iter<K: IntoIterator<Item = T>>(iter: K) -> Self {
1646 let btree = BTreeSet::new();
1647 iter.into_iter().for_each(|item| {
1648 btree.insert(item);
1649 });
1650
1651 btree
1652 }
1653}
1654
1655impl<T, const N: usize> From<[T; N]> for BTreeSet<T>
1656where
1657 T: Debug + Ord + Clone + Send,
1658{
1659 fn from(value: [T; N]) -> Self {
1660 let btree: BTreeSet<T> = Default::default();
1661
1662 value.into_iter().for_each(|item| {
1663 btree.insert(item);
1664 });
1665
1666 btree
1667 }
1668}
1669
1670pub struct Iter<'a, T, Node>
1684where
1685 T: Debug + Ord + Clone + Send + 'static,
1686 Node: NodeLike<T> + Send + 'static,
1687{
1688 tree: &'a BTreeSet<T, Node>,
1689 current_front_batch: Option<alloc::vec::IntoIter<T>>,
1690 current_back_batch: Option<alloc::vec::IntoIter<T>>,
1691 exhausted_front_node: Option<Arc<RwLock<Node>>>,
1695 exhausted_back_node: Option<Arc<RwLock<Node>>>,
1696 front_partial: Option<(Arc<RwLock<Node>>, usize)>,
1703 back_partial: Option<(Arc<RwLock<Node>>, usize)>,
1704 front_batch_limit: usize,
1706 back_batch_limit: usize,
1707 current_front_value: Option<T>,
1708 current_back_value: Option<T>,
1709 met: bool,
1710}
1711
1712const INITIAL_BATCH: usize = 4;
1719
1720const MAX_BATCH: usize = 4096;
1723
1724impl<'a, T, Node> Iter<'a, T, Node>
1725where
1726 T: Debug + Ord + Clone + Send + 'static,
1727 Node: NodeLike<T> + Send + 'static,
1728{
1729 pub fn new(btree: &'a BTreeSet<T, Node>) -> Self {
1730 Self {
1735 tree: btree,
1736 current_front_batch: None,
1737 current_back_batch: None,
1738 exhausted_front_node: None,
1739 exhausted_back_node: None,
1740 front_partial: None,
1741 back_partial: None,
1742 front_batch_limit: INITIAL_BATCH,
1743 back_batch_limit: INITIAL_BATCH,
1744 current_front_value: None,
1745 current_back_value: None,
1746 met: false,
1747 }
1748 }
1749
1750 fn install_front_batch(&mut self) -> bool {
1775 let index = self.tree.index.read();
1776 let candidate = match self.current_front_value.as_ref() {
1777 Some(last_yielded) => index.range((Bound::Excluded(last_yielded), Bound::Unbounded)).next(),
1778 None => index.first_key_value(),
1779 };
1780 let entry = match (candidate, self.exhausted_front_node.as_ref()) {
1786 (Some((key, node)), Some(exhausted)) if Arc::ptr_eq(node, exhausted) => {
1787 index.range((Bound::Excluded(key), Bound::Unbounded)).next()
1788 }
1789 (candidate, _) => candidate,
1790 };
1791 let Some((_, entry)) = entry else {
1792 return false;
1793 };
1794 let node = entry.clone();
1795 let guard = node.read_arc();
1796 drop(index);
1797
1798 let rank_skip = self
1799 .current_front_value
1800 .as_ref()
1801 .and_then(|value| guard.rank(Bound::Excluded(value), true))
1802 .map_or(0, |rank| rank + 1);
1803 let partial_skip = match self.front_partial.as_ref() {
1823 Some((partial, taken)) if Arc::ptr_eq(partial, &node) => *taken,
1824 _ => 0,
1825 };
1826 let skip = if self.current_front_value.is_some() {
1827 rank_skip
1828 } else {
1829 partial_skip
1830 };
1831
1832 let available = guard.len().saturating_sub(skip);
1838 let take = available.min(self.front_batch_limit);
1839 let batch = guard.iter().skip(skip).take(take).cloned().collect::<Vec<_>>();
1840 drop(guard);
1841
1842 if take == available {
1843 self.exhausted_front_node = Some(node);
1845 self.front_partial = None;
1846 } else {
1847 self.exhausted_front_node = None;
1850 self.front_partial = Some((node, skip + take));
1851 }
1852 self.front_batch_limit = self.front_batch_limit.saturating_mul(2).min(MAX_BATCH);
1853 self.current_front_batch = Some(batch.into_iter());
1854 true
1855 }
1856
1857 fn install_back_batch(&mut self) -> bool {
1861 let index = self.tree.index.read();
1862 let candidate = match self.current_back_value.as_ref() {
1863 Some(last_yielded) => index
1864 .range((Bound::Included(last_yielded), Bound::Unbounded))
1865 .next()
1866 .or_else(|| index.last_key_value()),
1867 None => index.last_key_value(),
1868 };
1869 let entry = match (candidate, self.exhausted_back_node.as_ref()) {
1870 (Some((key, node)), Some(exhausted)) if Arc::ptr_eq(node, exhausted) => index.range(..key).next_back(),
1871 (candidate, _) => candidate,
1872 };
1873 let Some((_, entry)) = entry else {
1874 return false;
1875 };
1876 let node = entry.clone();
1877 let guard = node.read_arc();
1878 drop(index);
1879
1880 let truncate = self
1881 .current_back_value
1882 .as_ref()
1883 .and_then(|value| guard.rank(Bound::Excluded(value), false))
1884 .map_or(0, |rank| rank + 1);
1885 let partial_truncate = match self.back_partial.as_ref() {
1892 Some((partial, taken)) if Arc::ptr_eq(partial, &node) => *taken,
1893 _ => 0,
1894 };
1895 let truncate = if self.current_back_value.is_some() {
1896 truncate
1897 } else {
1898 partial_truncate
1899 };
1900 let available = guard.len().saturating_sub(truncate);
1901 let take = available.min(self.back_batch_limit);
1902 let skip = available - take;
1905 let batch = guard.iter().skip(skip).take(take).cloned().collect::<Vec<_>>();
1906 drop(guard);
1907
1908 if take == available {
1909 self.exhausted_back_node = Some(node);
1910 self.back_partial = None;
1911 } else {
1912 self.exhausted_back_node = None;
1913 self.back_partial = Some((node, truncate + take));
1914 }
1915 self.back_batch_limit = self.back_batch_limit.saturating_mul(2).min(MAX_BATCH);
1916 self.current_back_batch = Some(batch.into_iter());
1917 true
1918 }
1919}
1920
1921impl<'a, T, Node> Iterator for Iter<'a, T, Node>
1922where
1923 T: Debug + Ord + Clone + Send + 'static,
1924 Node: NodeLike<T> + Send + 'static,
1925{
1926 type Item = T;
1927
1928 fn next(&mut self) -> Option<Self::Item> {
1929 loop {
1930 if self.met {
1931 return None;
1932 }
1933
1934 if self.current_front_batch.is_none() && !self.install_front_batch() {
1935 return None;
1936 }
1937
1938 let batch = self.current_front_batch.as_mut().expect("installed above");
1939 if let Some(value) = batch.next() {
1940 if let Some(current_front_value) = self.current_front_value.as_ref() {
1946 if value.le(current_front_value) {
1947 continue;
1948 }
1949 }
1950 if let Some(current_back_value) = self.current_back_value.as_ref() {
1951 if value.ge(current_back_value) {
1952 self.met = true;
1953 return None;
1954 }
1955 }
1956 self.current_front_value = Some(value.clone());
1957 return Some(value);
1958 } else {
1959 self.current_front_batch = None;
1960 }
1961 }
1962 }
1963}
1964
1965impl<'a, T, Node> DoubleEndedIterator for Iter<'a, T, Node>
1966where
1967 T: Debug + Ord + Clone + Send + 'static,
1968 Node: NodeLike<T> + Send + 'static,
1969{
1970 fn next_back(&mut self) -> Option<Self::Item> {
1971 loop {
1972 if self.met {
1973 return None;
1974 }
1975
1976 if self.current_back_batch.is_none() && !self.install_back_batch() {
1977 return None;
1978 }
1979
1980 let batch = self.current_back_batch.as_mut().expect("installed above");
1981 if let Some(value) = batch.next_back() {
1982 if let Some(current_back_value) = self.current_back_value.as_ref() {
1986 if value.ge(current_back_value) {
1987 continue;
1988 }
1989 }
1990 if let Some(current_front_value) = self.current_front_value.as_ref() {
1991 if value.le(current_front_value) {
1992 self.met = true;
1993 return None;
1994 }
1995 }
1996 self.current_back_value = Some(value.clone());
1997 return Some(value);
1998 } else {
1999 self.current_back_batch = None;
2000 }
2001 }
2002 }
2003}
2004
2005impl<'a, T: Debug + Ord + Clone + Send, Node: NodeLike<T> + Send + 'static> FusedIterator for Iter<'a, T, Node> {}
2006
2007impl<'a, T, Node> IntoIterator for &'a BTreeSet<T, Node>
2008where
2009 T: Debug + Ord + Send + Clone,
2010 Node: NodeLike<T> + Send + 'static,
2011{
2012 type Item = T;
2013
2014 type IntoIter = Iter<'a, T, Node>;
2015
2016 fn into_iter(self) -> Self::IntoIter {
2017 Iter::new(self)
2018 }
2019}
2020
2021pub struct Range<'a, T, Node>
2024where
2025 T: Debug + Ord + Clone + Send + 'static,
2026 Node: NodeLike<T> + Send + 'static,
2027{
2028 iter: Iter<'a, T, Node>,
2029}
2030
2031impl<'a, T, Node> Range<'a, T, Node>
2032where
2033 T: Debug + Ord + Clone + Send + 'static,
2034 Node: NodeLike<T> + Send + 'static,
2035{
2036 pub fn new<Q, R>(btree: &'a BTreeSet<T, Node>, range: R) -> Self
2037 where
2038 T: Borrow<Q>,
2039 Q: Ord + ?Sized,
2040 R: RangeBounds<Q>,
2041 {
2042 let index = btree.index.read();
2043
2044 let start_bound = range.start_bound();
2045 let end_bound = range.end_bound();
2046 let mut met = match (start_bound, end_bound) {
2047 (Bound::Included(start), Bound::Included(end)) => start > end,
2048 (Bound::Included(start), Bound::Excluded(end))
2049 | (Bound::Excluded(start), Bound::Included(end))
2050 | (Bound::Excluded(start), Bound::Excluded(end)) => start >= end,
2051 _ => false,
2052 };
2053
2054 let current_front_entry = first_for_borrowed_bound(&index, start_bound, btree.borrow_order_matches);
2055
2056 let front_value = if let Some((front_key, front_node)) = current_front_entry {
2057 let front_guard = front_node.clone().read_arc();
2058 let rank = match start_bound {
2059 Bound::Included(v) => front_guard.rank(Bound::Included(v), true),
2060 Bound::Excluded(v) => front_guard.rank(Bound::Excluded(v), true),
2061 Bound::Unbounded => None,
2062 };
2063 if let Some(rank) = rank {
2064 let value = front_guard.iter().nth(rank).cloned();
2065 drop(front_guard);
2066
2067 value
2068 } else {
2069 drop(front_guard);
2075 if let Some((_, pre_front_node)) = index.range::<T, _>(..front_key).next_back() {
2076 let pre_front_guard = pre_front_node.clone().read_arc();
2077 pre_front_guard.iter().last().cloned()
2078 } else {
2079 None
2080 }
2081 }
2082 } else {
2083 None
2084 };
2085
2086 let current_back_entry = match end_bound {
2087 Bound::Included(end) | Bound::Excluded(end) => {
2088 node_for_borrowed_end(&index, end, btree.borrow_order_matches)
2089 }
2090 Bound::Unbounded => index.last_key_value(),
2091 };
2092
2093 let back_value = if let Some((back_key, back_node)) = current_back_entry {
2094 let back_guard = back_node.clone().read_arc();
2095 let rank = match end_bound {
2096 Bound::Included(v) => back_guard.rank(Bound::Included(v), false),
2097 Bound::Excluded(v) => back_guard.rank(Bound::Excluded(v), false),
2098 Bound::Unbounded => None,
2099 };
2100 if let Some(rank) = rank {
2101 let value = back_guard.iter().nth_back(rank).cloned();
2102 drop(back_guard);
2103
2104 value
2105 } else {
2106 drop(back_guard);
2108 if let Some((_, next_back_node)) = index
2109 .range::<T, _>((Bound::Excluded(back_key), Bound::Unbounded))
2110 .next()
2111 {
2112 let next_back_guard = next_back_node.clone().read_arc();
2113 next_back_guard.iter().next().cloned()
2114 } else {
2115 None
2116 }
2117 }
2118 } else {
2119 None
2120 };
2121
2122 if front_value.is_none() && back_value.is_none() {
2123 if start_bound != Bound::Unbounded || end_bound != Bound::Unbounded {
2125 if let Some(max) = index
2126 .last_key_value()
2127 .and_then(|(_, node)| node.clone().read_arc().max().cloned())
2128 {
2129 if let Bound::Included(v) = start_bound {
2130 if v > max.borrow() {
2131 met = true;
2132 }
2133 } else if let Bound::Excluded(v) = start_bound {
2134 if v >= max.borrow() {
2135 met = true;
2136 }
2137 }
2138 }
2139
2140 if let Some(min) = index
2141 .first_key_value()
2142 .and_then(|(_, node)| node.clone().read_arc().min().cloned())
2143 {
2144 if let Bound::Included(v) = end_bound {
2145 if v < min.borrow() {
2146 met = true;
2147 }
2148 } else if let Bound::Excluded(v) = end_bound {
2149 if v <= min.borrow() {
2150 met = true;
2151 }
2152 }
2153 }
2154 }
2155 }
2156
2157 Self {
2162 iter: Iter {
2163 tree: btree,
2164 current_front_batch: None,
2165 current_back_batch: None,
2166 exhausted_front_node: None,
2167 exhausted_back_node: None,
2168 front_partial: None,
2169 back_partial: None,
2170 front_batch_limit: INITIAL_BATCH,
2171 back_batch_limit: INITIAL_BATCH,
2172 current_front_value: front_value,
2173 current_back_value: back_value,
2174 met,
2175 },
2176 }
2177 }
2178}
2179
2180impl<'a, T, Node> Iterator for Range<'a, T, Node>
2181where
2182 T: Debug + Ord + Clone + Send + 'static,
2183 Node: NodeLike<T> + Send + 'static,
2184{
2185 type Item = T;
2186
2187 fn next(&mut self) -> Option<Self::Item> {
2188 self.iter.next()
2189 }
2190}
2191
2192impl<'a, T, Node> DoubleEndedIterator for Range<'a, T, Node>
2193where
2194 T: Debug + Ord + Clone + Send + 'static,
2195 Node: NodeLike<T> + Send + 'static,
2196{
2197 fn next_back(&mut self) -> Option<Self::Item> {
2198 self.iter.next_back()
2199 }
2200}
2201
2202impl<'a, T, Node> FusedIterator for Range<'a, T, Node>
2203where
2204 T: Debug + Ord + Clone + Send + 'static,
2205 Node: NodeLike<T> + Send + 'static,
2206{
2207}
2208
2209impl<'a, T, Node> BTreeSet<T, Node>
2210where
2211 T: Debug + Ord + Clone + Send + 'static,
2212 Node: NodeLike<T> + Send + 'static,
2213{
2214 pub fn iter(&'a self) -> Iter<'a, T, Node> {
2247 Iter::new(self)
2248 }
2249 pub fn range<Q, R>(&'a self, range: R) -> Range<'a, T, Node>
2277 where
2278 T: Borrow<Q>,
2279 Q: Ord + ?Sized,
2280 R: RangeBounds<Q>,
2281 {
2282 Range::new(self, range)
2283 }
2284}
2285
2286impl<T> BTreeSet<T>
2287where
2288 T: Debug + Ord + Clone + Send + 'static,
2289{
2290 pub fn remove_range<R, Q>(&self, range: R)
2291 where
2292 Q: Ord + ?Sized,
2293 T: Borrow<Q>,
2294 R: RangeBounds<Q>,
2295 {
2296 let mut detached_nodes = Vec::new();
2299 let mut index = self.index.write();
2300
2301 let start_bound = range.start_bound();
2302 let end_bound = range.end_bound();
2303
2304 let Some((front_key, front_node)) = first_for_borrowed_bound(&index, start_bound, self.borrow_order_matches)
2307 else {
2308 return;
2309 };
2310 let front_key = front_key.clone();
2311 let front_node = front_node.clone();
2312
2313 let back_entry = match end_bound {
2319 Bound::Included(end) | Bound::Excluded(end) => {
2320 node_for_borrowed_end(&index, end, self.borrow_order_matches)
2321 }
2322 Bound::Unbounded => index.last_key_value(),
2323 };
2324 let Some((back_key, back_node)) = back_entry else {
2325 return;
2326 };
2327 let back_key = back_key.clone();
2328 let back_node = back_node.clone();
2329 if back_key < front_key {
2330 return;
2332 }
2333
2334 let removed_prefix_len = |guard: &Vec<T>| -> usize {
2337 match end_bound {
2338 Bound::Included(end) => guard.rank(Bound::Excluded(end), true).map_or(0, |last| last + 1),
2339 Bound::Excluded(end) => guard.rank(Bound::Included(end), true).map_or(0, |last| last + 1),
2340 Bound::Unbounded => guard.len(),
2341 }
2342 };
2343
2344 if Arc::ptr_eq(&front_node, &back_node) {
2345 let mut guard = front_node.clone().write_arc();
2347 let front_position = guard.rank(start_bound, true).map_or(0, |last| last + 1);
2348 let back_position = removed_prefix_len(&guard);
2349 if back_position <= front_position {
2350 return;
2351 }
2352
2353 let original_len = guard.len();
2354 guard.drain(front_position..back_position);
2355 if back_position == original_len {
2356 index.remove::<T>(&front_key);
2359 if let Some(new_max) = guard.last().cloned() {
2360 index.insert(new_max, front_node);
2361 }
2362 }
2363 return;
2364 }
2365
2366 let mut front_guard = front_node.clone().write_arc();
2367 let mut back_guard = back_node.clone().write_arc();
2368 let front_position = front_guard.rank(start_bound, true).map_or(0, |last| last + 1);
2369 let back_position = removed_prefix_len(&back_guard);
2370
2371 let middle_keys = index
2373 .range::<T, _>((Bound::Excluded(&front_key), Bound::Excluded(&back_key)))
2374 .map(|(key, _)| key.clone())
2375 .collect::<Vec<_>>();
2376 for key in middle_keys {
2377 let node = index
2378 .remove::<T>(&key)
2379 .expect("middle key was collected under the write lock");
2380 let mut removed_node = node.write_arc();
2381 detached_nodes.push(::core::mem::take(&mut *removed_node));
2382 }
2383
2384 index.remove::<T>(&front_key);
2387 front_guard.drain(front_position..);
2388 if !front_guard.is_empty() {
2389 let new_front_max = front_guard.last().unwrap().clone();
2390 index.insert(new_front_max, front_node);
2391 }
2392
2393 if back_position >= back_guard.len() {
2396 index.remove::<T>(&back_key);
2397 back_guard.drain(..);
2398 } else if back_position > 0 {
2399 back_guard.drain(..back_position);
2400 }
2401 }
2402}
2403
2404#[cfg(test)]
2405mod tests {
2406 use crate::concurrent::operation::Operation;
2407 use crate::concurrent::set::{BTreeSet, Iter, DEFAULT_INNER_SIZE, INITIAL_BATCH};
2408 use crate::core::node::NodeLike;
2409 use rand::Rng;
2410 use std::collections::HashSet;
2411 use std::ops::Bound::{self, Included};
2412 use std::sync::mpsc;
2413 use std::sync::{Arc, Barrier, Mutex};
2414 use std::thread;
2415 use std::time::Duration;
2416
2417 #[test]
2419 fn test_node_size_two_preserves_all_u64_values() {
2420 let set = BTreeSet::<u64>::with_maximum_node_size(2);
2421
2422 for value in 0..10_u64 {
2423 set.insert(value);
2424 }
2425
2426 assert_eq!(set.iter().collect::<Vec<_>>(), (0..10).collect::<Vec<_>>());
2427 }
2428
2429 #[test]
2431 fn test_node_size_three_preserves_all_u8_values() {
2432 let set = BTreeSet::<u8>::with_maximum_node_size(3);
2433
2434 for value in 0..20_u8 {
2435 set.insert(value);
2436 }
2437
2438 assert_eq!(set.iter().collect::<Vec<_>>(), (0..20).collect::<Vec<_>>());
2439 }
2440
2441 #[test]
2442 fn concurrent_first_writers_preserve_disjoint_ranges() {
2443 const WRITERS: u64 = 8;
2444 const VALUES_PER_WRITER: u64 = 1_000;
2445
2446 let set = Arc::new(BTreeSet::<u64>::new());
2447 let start = Arc::new(Barrier::new(WRITERS as usize));
2448 let handles = (0..WRITERS)
2449 .map(|writer| {
2450 let set = Arc::clone(&set);
2451 let start = Arc::clone(&start);
2452 thread::spawn(move || {
2453 start.wait();
2454 let first = writer * VALUES_PER_WRITER;
2455 for value in first..first + VALUES_PER_WRITER {
2456 assert!(set.insert(value));
2457 }
2458 })
2459 })
2460 .collect::<Vec<_>>();
2461
2462 for handle in handles {
2463 handle.join().unwrap();
2464 }
2465
2466 let expected = (0..WRITERS * VALUES_PER_WRITER).collect::<Vec<_>>();
2467 assert_eq!(set.len(), expected.len());
2468 assert_eq!(set.iter().collect::<Vec<_>>(), expected);
2469 }
2470
2471 #[test]
2472 fn published_point_reads_remain_definitive_across_splits() {
2473 use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
2474
2475 const STABLE_KEYS: usize = 256;
2476 const FINAL_KEYS: usize = 4_096;
2477 const READERS: usize = 4;
2478
2479 let set = Arc::new(BTreeSet::<usize>::with_maximum_node_size(8));
2480 for key in 0..STABLE_KEYS {
2481 set.insert(key);
2482 }
2483
2484 let start = Arc::new(Barrier::new(READERS + 1));
2485 let done = Arc::new(AtomicBool::new(false));
2486 let published_up_to = Arc::new(AtomicUsize::new(STABLE_KEYS - 1));
2487 let readers = (0..READERS)
2488 .map(|reader| {
2489 let set = Arc::clone(&set);
2490 let start = Arc::clone(&start);
2491 let done = Arc::clone(&done);
2492 let published_up_to = Arc::clone(&published_up_to);
2493 thread::spawn(move || {
2494 start.wait();
2495 let mut probe = reader;
2496 while !done.load(Ordering::Acquire) {
2497 let key = probe % STABLE_KEYS;
2498 assert_eq!(set.get_with(&key, |value| *value), Some(key));
2499 let newest_acknowledged = published_up_to.load(Ordering::Acquire);
2500 assert_eq!(
2501 set.get_with(&newest_acknowledged, |value| *value),
2502 Some(newest_acknowledged),
2503 "an acknowledged insert disappeared from the published route"
2504 );
2505 probe += READERS;
2506 }
2507 })
2508 })
2509 .collect::<Vec<_>>();
2510
2511 start.wait();
2512 for key in STABLE_KEYS..FINAL_KEYS {
2513 set.insert(key);
2514 published_up_to.store(key, Ordering::Release);
2515 }
2516 done.store(true, Ordering::Release);
2517
2518 for reader in readers {
2519 reader.join().unwrap();
2520 }
2521 assert_eq!(set.len(), FINAL_KEYS);
2522 for key in 0..FINAL_KEYS {
2523 assert_eq!(set.get_with(&key, |value| *value), Some(key));
2524 }
2525 }
2526
2527 #[test]
2528 fn published_pointer_survives_reclamation_interleavings() {
2529 use std::sync::atomic::{AtomicBool, Ordering};
2530
2531 let set = Arc::new(BTreeSet::<usize>::with_maximum_node_size(2));
2532 for key in 0..8 {
2533 set.insert(key);
2534 }
2535 let start = Arc::new(Barrier::new(2));
2536 let done = Arc::new(AtomicBool::new(false));
2537
2538 let reader_set = Arc::clone(&set);
2539 let reader_start = Arc::clone(&start);
2540 let reader_done = Arc::clone(&done);
2541 let reader = thread::spawn(move || {
2542 reader_start.wait();
2543 let mut probe = 0;
2544 while !reader_done.load(Ordering::Acquire) {
2545 let key = probe % 8;
2546 assert_eq!(reader_set.get_with(&key, |value| *value), Some(key));
2547 probe += 1;
2548 }
2549 });
2550
2551 start.wait();
2552 for key in 8..80 {
2553 set.insert(key);
2554 }
2555 for key in 8..80 {
2556 assert_eq!(set.remove(&key), Some(key));
2557 }
2558 done.store(true, Ordering::Release);
2559 reader.join().unwrap();
2560
2561 for key in 0..8 {
2562 assert_eq!(set.get_with(&key, |value| *value), Some(key));
2563 }
2564 }
2565
2566 #[test]
2567 fn published_route_chunks_split_and_merge_without_losing_keys() {
2568 let set = BTreeSet::<usize>::with_maximum_node_size(2);
2569 for key in 0..600 {
2570 assert!(set.insert(key));
2571 }
2572 for key in (0..600).step_by(2) {
2573 assert_eq!(set.remove(&key), Some(key));
2574 }
2575 for key in 0..600 {
2576 assert_eq!(set.contains(&key), key % 2 == 1, "probe {key}");
2577 }
2578 for key in (1..600).step_by(2) {
2579 assert_eq!(set.remove(&key), Some(key));
2580 }
2581 assert!(set.is_empty());
2582 }
2583
2584 #[test]
2585 fn mixed_structural_and_node_lock_paths_complete_without_deadlock() {
2586 const THREADS: usize = 8;
2587 const OPERATIONS: usize = 1_000;
2588
2589 let set = Arc::new(BTreeSet::<usize>::with_maximum_node_size(8));
2590 for value in 0..256 {
2591 set.insert(value);
2592 }
2593
2594 let start = Arc::new(Barrier::new(THREADS));
2595 let (done_tx, done_rx) = mpsc::channel();
2596 let handles = (0..THREADS)
2597 .map(|worker| {
2598 let set = Arc::clone(&set);
2599 let start = Arc::clone(&start);
2600 let done_tx = done_tx.clone();
2601 thread::spawn(move || {
2602 start.wait();
2603 for operation in 0..OPERATIONS {
2604 let value = (operation * 17 + worker * 31) % 512;
2605 match (operation + worker) % 5 {
2606 0 => {
2607 set.insert(value);
2608 }
2609 1 => {
2610 set.remove(&value);
2611 }
2612 2 => {
2613 let _ = set.contains(&value);
2614 }
2615 3 => {
2616 let _ = set.get_with(&value, Clone::clone);
2617 }
2618 _ => {
2619 set.remove_range(value..=value);
2620 set.insert(value);
2621 }
2622 }
2623 }
2624 done_tx.send(()).unwrap();
2625 })
2626 })
2627 .collect::<Vec<_>>();
2628 drop(done_tx);
2629
2630 for _ in 0..THREADS {
2631 done_rx
2632 .recv_timeout(Duration::from_secs(10))
2633 .expect("mixed structural/node-lock workload did not complete");
2634 }
2635 for handle in handles {
2636 handle.join().unwrap();
2637 }
2638 }
2639
2640 #[test]
2641 fn test_concurrent_insert() {
2642 let set = Arc::new(BTreeSet::<i32>::new());
2643 let num_threads = 128;
2644 let operations_per_thread = 10000;
2645 let mut handles = vec![];
2646
2647 let test_data: Vec<Vec<(i32, i32)>> = (0..num_threads)
2648 .map(|_| {
2649 let mut rng = rand::rng();
2650 (0..operations_per_thread)
2651 .map(|_| {
2652 let value = rng.random_range(0..100000);
2653 let operation = rng.random_range(0..2);
2654 (operation, value)
2655 })
2656 .collect()
2657 })
2658 .collect();
2659
2660 let expected_values = Arc::new(Mutex::new(HashSet::new()));
2661
2662 for thread_idx in 0..num_threads {
2663 let set_clone = Arc::clone(&set);
2664 let expected_values = Arc::clone(&expected_values);
2665 let thread_data = test_data[thread_idx].clone();
2666
2667 let handle = thread::spawn(move || {
2668 for (operation, value) in thread_data {
2669 if operation == 0 {
2670 let _a = set_clone.insert(value);
2671 expected_values.lock().unwrap().insert(value);
2672 }
2673 }
2674 });
2675 handles.push(handle);
2676 }
2677
2678 for handle in handles {
2679 handle.join().unwrap();
2680 }
2681
2682 let expected_values = expected_values.lock().unwrap();
2683 assert_eq!(set.len(), expected_values.len());
2684
2685 for value in expected_values.iter() {
2686 assert!(set.contains(value));
2687 }
2688 }
2689
2690 #[test]
2691 fn test_insert_desc() {
2692 let set = Arc::new(BTreeSet::<i32>::new());
2693
2694 assert!(set.insert(2));
2695 assert!(set.insert(1));
2696 }
2697
2698 #[test]
2699 fn test_insert_st() {
2700 let set = Arc::new(BTreeSet::<i32>::new());
2701 let mut rng = rand::rng();
2702
2703 let n = 2048 * 100;
2704 let range = 0..n;
2705 let mut inserted_values = HashSet::new();
2706 for _ in range {
2707 let value = rng.random_range(0..n);
2708 if inserted_values.insert(value) {
2709 set.insert(value);
2710 }
2711 }
2712
2713 assert_eq!(
2714 set.len(),
2715 inserted_values.len(),
2716 "Length did not match, missing: {:?}",
2717 set.index
2718 .read()
2719 .values()
2720 .flat_map(|node| node.read().iter().cloned().collect::<Vec<_>>())
2721 .collect::<HashSet<_>>()
2722 .symmetric_difference(&inserted_values)
2723 .collect::<Vec<_>>()
2724 );
2725 for i in inserted_values {
2726 assert!(
2727 set.contains(&i),
2728 "Did not find: {} with index: {:?}",
2729 i,
2730 set.index.read().keys().cloned().collect::<Vec<_>>(),
2731 );
2732 }
2733 }
2734
2735 #[test]
2736 fn test_single_element() {
2737 let set = BTreeSet::<i32>::new();
2738 set.insert(1);
2739 let mut iter = set.into_iter();
2740 assert_eq!(iter.next(), Some(1));
2741 assert_eq!(iter.next(), None);
2742 assert_eq!(iter.next_back(), None);
2743 }
2744
2745 #[test]
2746 fn test_multiple_elements() {
2747 let set = BTreeSet::<i32>::new();
2748 set.insert(1);
2749 set.insert(2);
2750 set.insert(3);
2751 let mut iter = set.into_iter();
2752 assert_eq!(iter.next(), Some(1));
2753 assert_eq!(iter.next_back(), Some(3));
2754 assert_eq!(iter.next(), Some(2));
2755 assert_eq!(iter.next(), None);
2756 assert_eq!(iter.next_back(), None);
2757 }
2758
2759 #[test]
2760 fn test_bidirectional_iteration() {
2761 let set = BTreeSet::<i32>::with_maximum_node_size(3);
2762 for i in 1..=20 {
2763 set.insert(i);
2764 }
2765 let mut iter = set.into_iter();
2766 for i in 0..10 {
2767 let tree = set.index.read().keys().cloned().collect::<Vec<_>>();
2769
2770 let expected_next = i + 1;
2771 let actual_next = iter.next();
2772 assert_eq!(actual_next, Some(expected_next), "Tree: {:?}", tree);
2773
2774 let expected_next_back = 20 - i;
2775 let actual_next_back = iter.next_back();
2776 assert_eq!(actual_next_back, Some(expected_next_back), "Tree: {:?}", tree);
2777 }
2778 assert_eq!(iter.next(), None);
2779 assert_eq!(iter.next_back(), None);
2780 }
2781
2782 #[test]
2783 fn test_fused_iterator() {
2784 let set = BTreeSet::<i32>::new();
2785 set.insert(1);
2786 let mut iter = set.into_iter();
2787 assert_eq!(iter.next(), Some(1));
2788 assert_eq!(iter.next(), None);
2789 assert_eq!(iter.next(), None);
2790 }
2791
2792 #[test]
2793 fn test_fused_iterator_back() {
2794 let set = BTreeSet::<i32>::new();
2795 set.insert(1);
2796 let mut iter = set.into_iter();
2797 assert_eq!(iter.next_back(), Some(1));
2798 assert_eq!(iter.next_back(), None);
2799 assert_eq!(iter.next_back(), None);
2800 }
2801
2802 #[test]
2803 fn test_out_of_bounds_range() {
2804 let btree: BTreeSet<usize> = BTreeSet::from_iter(0..10);
2805 assert_eq!(btree.range((Included(5), Included(10))).count(), 5);
2806 assert_eq!(btree.range((Included(5), Included(11))).count(), 5);
2807 assert_eq!(btree.range((Included(5), Included(10 + DEFAULT_INNER_SIZE))).count(), 5);
2808 assert_eq!(btree.range((Included(0), Included(11))).count(), 10);
2809 }
2810
2811 #[test]
2812 fn test_iterating_over_blocks() {
2813 let btree = BTreeSet::from_iter((0..(DEFAULT_INNER_SIZE + 10)).into_iter());
2814 assert_eq!(btree.iter().count(), (0..(DEFAULT_INNER_SIZE + 10)).count());
2815 let start = btree.range(0..DEFAULT_INNER_SIZE).into_iter().collect::<Vec<_>>();
2816
2817 assert_eq!(start, (0..DEFAULT_INNER_SIZE).collect::<Vec<_>>());
2818 assert_eq!(
2819 btree.range(0..=DEFAULT_INNER_SIZE).into_iter().collect::<Vec<_>>(),
2820 (0..=DEFAULT_INNER_SIZE).collect::<Vec<_>>()
2821 );
2822 assert_eq!(
2823 btree.range(0..=DEFAULT_INNER_SIZE + 1).count(),
2824 (0..=DEFAULT_INNER_SIZE + 1).count()
2825 );
2826 assert_eq!(btree.iter().rev().count(), (0..(DEFAULT_INNER_SIZE + 10)).count());
2827 assert_eq!(
2828 btree.range(0..DEFAULT_INNER_SIZE).rev().count(),
2829 (0..DEFAULT_INNER_SIZE).count()
2830 );
2831 assert_eq!(
2832 btree.range(0..=DEFAULT_INNER_SIZE).rev().count(),
2833 (0..=DEFAULT_INNER_SIZE).count()
2834 );
2835 assert_eq!(
2836 btree.range(0..=DEFAULT_INNER_SIZE + 1).rev().count(),
2837 (0..=DEFAULT_INNER_SIZE + 1).count()
2838 );
2839 }
2840
2841 #[test]
2842 fn test_empty_set() {
2843 let btree: BTreeSet<usize> = BTreeSet::new();
2844 assert_eq!(btree.iter().count(), 0);
2845 assert_eq!(btree.range(0..0).count(), 0);
2846 assert_eq!(btree.range(0..).count(), 0);
2847 assert_eq!(btree.range(..0).count(), 0);
2848 assert_eq!(btree.range(..).count(), 0);
2849 assert_eq!(btree.range(0..=0).count(), 0);
2850 assert_eq!(btree.range(..1).count(), 0);
2851
2852 assert_eq!(btree.iter().rev().count(), 0);
2853 assert_eq!(btree.range(0..0).rev().count(), 0);
2854 assert_eq!(btree.range(..).rev().count(), 0);
2855 assert_eq!(btree.range(..1).rev().count(), 0);
2856
2857 assert_eq!(btree.range(..DEFAULT_INNER_SIZE).count(), 0);
2858 assert_eq!(btree.range(DEFAULT_INNER_SIZE..DEFAULT_INNER_SIZE * 2).count(), 0);
2859 }
2860
2861 #[test]
2862 fn test_remove_range() {
2863 let btree = BTreeSet::from_iter(0..(DEFAULT_INNER_SIZE * 2));
2865 let expected_len = DEFAULT_INNER_SIZE * 2;
2866 let actual_len = btree.len();
2867 assert_eq!(expected_len, actual_len);
2868
2869 btree.remove_range(5..15);
2871 let expected_len = expected_len - 10;
2872 let actual_len = btree.len();
2873 assert_eq!(expected_len, actual_len);
2874
2875 btree.remove_range(DEFAULT_INNER_SIZE - 5..DEFAULT_INNER_SIZE + 5);
2877 let expected_len = expected_len - 10;
2878 let actual_len = btree.len();
2879 assert_eq!(expected_len, actual_len);
2880
2881 btree.remove_range(..DEFAULT_INNER_SIZE / 2);
2883 let expected_len = expected_len - (DEFAULT_INNER_SIZE / 2) + 10;
2885 let actual_len = btree.len();
2886 assert_eq!(expected_len, actual_len);
2887
2888 let from = (DEFAULT_INNER_SIZE * 3) / 2;
2891 btree.remove_range(from..);
2892 let expected_len = expected_len - DEFAULT_INNER_SIZE / 2;
2893 let actual_len = btree.len();
2894 assert_eq!(expected_len, actual_len);
2895
2896 btree.remove_range(..);
2898 assert_eq!(btree.len(), 0);
2899
2900 for i in 0..(DEFAULT_INNER_SIZE * 2) {
2902 btree.insert(i);
2903 }
2904 let expected_len = DEFAULT_INNER_SIZE * 2;
2905 let actual_len = btree.len();
2906 assert_eq!(expected_len, actual_len);
2907
2908 btree.remove_range((std::ops::Bound::Excluded(5), std::ops::Bound::Excluded(15)));
2909 let expected_len = expected_len - 9;
2910 let actual_len = btree.len();
2911 assert_eq!(expected_len, actual_len);
2912
2913 btree.remove_range((
2914 std::ops::Bound::Included(DEFAULT_INNER_SIZE),
2915 std::ops::Bound::Excluded(DEFAULT_INNER_SIZE + 10),
2916 ));
2917 let expected_len = expected_len - 10;
2918 let actual_len = btree.len();
2919 assert_eq!(expected_len, actual_len);
2920
2921 btree.remove_range(DEFAULT_INNER_SIZE * 3..DEFAULT_INNER_SIZE * 4);
2923 let expected_len = expected_len;
2924 let actual_len = btree.len();
2925 assert_eq!(expected_len, actual_len);
2926
2927 btree.remove_range(DEFAULT_INNER_SIZE * 2 - 5..DEFAULT_INNER_SIZE * 3);
2929 let expected_len = expected_len - 5;
2930 let actual_len = btree.len();
2931 assert_eq!(expected_len, actual_len);
2932 }
2933
2934 #[test]
2935 fn remove_range_end_bound_regressions() {
2936 let set = BTreeSet::<u64>::with_maximum_node_size(4);
2938 for value in 0..10 {
2939 set.insert(value);
2940 }
2941 set.remove_range(7..);
2942 assert_eq!(set.iter().collect::<Vec<_>>(), (0..7).collect::<Vec<_>>());
2943
2944 let set = BTreeSet::<u64>::with_maximum_node_size(4);
2946 for value in 0..10 {
2947 set.insert(value);
2948 }
2949 set.remove_range(..);
2950 assert_eq!(set.len(), 0);
2951 assert!(set.is_empty());
2952
2953 let set = BTreeSet::<u64>::with_maximum_node_size(4);
2955 for value in 0..10 {
2956 set.insert(value);
2957 }
2958 set.remove_range(3..=5);
2959 assert_eq!(set.iter().collect::<Vec<_>>(), vec![0, 1, 2, 6, 7, 8, 9]);
2960
2961 let set = BTreeSet::<u64>::with_maximum_node_size(4);
2963 for value in 0..10 {
2964 set.insert(value);
2965 }
2966 set.remove_range(2..=2);
2967 assert_eq!(set.iter().collect::<Vec<_>>(), vec![0, 1, 3, 4, 5, 6, 7, 8, 9]);
2968
2969 let set = BTreeSet::<u64>::with_maximum_node_size(3);
2972 for value in 0..9 {
2973 set.insert(value);
2974 }
2975 let boundary = *set.index.read().first_key_value().expect("node must exist").0;
2976 set.remove_range(0..boundary);
2977 let expected = (0..9).filter(|value| *value >= boundary).collect::<Vec<_>>();
2978 assert_eq!(set.iter().collect::<Vec<_>>(), expected);
2979 }
2980
2981 #[test]
2982 fn remove_range_matches_btreeset_oracle() {
2983 use std::ops::Bound;
2984
2985 fn oracle_case(node_size: usize, values: &[u64], start: Bound<u64>, end: Bound<u64>) {
2986 let set = BTreeSet::<u64>::with_maximum_node_size(node_size);
2987 for &value in values {
2988 set.insert(value);
2989 }
2990 let mut oracle = values.iter().copied().collect::<std::collections::BTreeSet<_>>();
2991
2992 let range = (start, end);
2993 oracle.retain(|value| !std::ops::RangeBounds::contains(&range, value));
2994 set.remove_range(range);
2995
2996 assert_eq!(
2997 set.iter().collect::<Vec<_>>(),
2998 oracle.iter().copied().collect::<Vec<_>>(),
2999 "node_size={node_size}, start={start:?}, end={end:?}"
3000 );
3001 assert_eq!(
3002 set.len(),
3003 oracle.len(),
3004 "node_size={node_size}, start={start:?}, end={end:?}"
3005 );
3006 }
3007
3008 let values = (0..15u64).map(|value| value * 2).collect::<Vec<_>>();
3011 let mut bounds = vec![Bound::Unbounded];
3012 for probe in 0..=30u64 {
3013 bounds.push(Bound::Included(probe));
3014 bounds.push(Bound::Excluded(probe));
3015 }
3016
3017 for node_size in [4usize, 7, 64] {
3019 for &start in &bounds {
3020 for &end in &bounds {
3021 oracle_case(node_size, &values, start, end);
3022 }
3023 }
3024 }
3025 }
3026
3027 #[test]
3028 fn remove_range_clears_detached_nodes() {
3029 let set = BTreeSet::<u64>::with_maximum_node_size(4);
3034 for value in 0..32 {
3035 set.insert(value);
3036 }
3037
3038 let detached = set
3039 .index
3040 .read()
3041 .range((Included(&2), Bound::Unbounded))
3042 .nth(1)
3043 .unwrap()
3044 .1
3045 .clone();
3046 let detached_values = detached.read().iter().copied().collect::<Vec<_>>();
3047 assert!(detached_values.iter().all(|value| (2..30).contains(value)));
3048
3049 set.remove_range(2..30);
3050
3051 assert!(detached.read().is_empty());
3052 assert!(detached_values.iter().all(|value| !set.contains(value)));
3053 }
3054
3055 #[test]
3056 fn remove_reaches_value_above_every_index_key() {
3057 let set = BTreeSet::<u64>::new();
3058 for value in [1u64, 2, 3] {
3059 set.insert(value);
3060 }
3061
3062 {
3067 let node = set.index.read().last_key_value().expect("node must exist").1.clone();
3068 let mut guard = node.write();
3069 NodeLike::insert(&mut *guard, 5u64);
3070 }
3071
3072 assert!(set.contains(&5));
3073 assert_eq!(set.remove(&5), Some(5), "value above every index key must be removable");
3074 assert!(!set.contains(&5));
3075 assert_eq!(set.iter().collect::<Vec<_>>(), vec![1, 2, 3]);
3076 }
3077
3078 fn drain_node_with_pending_unlink(set: &BTreeSet<u64>, values: &[u64], stale_key: u64) -> Operation<u64, Vec<u64>> {
3082 let node = set.index.read().last_key_value().expect("node must exist").1.clone();
3083 {
3084 let mut guard = node.write();
3085 for value in values {
3086 NodeLike::delete(&mut *guard, value).expect("seeded value must be present");
3087 }
3088 }
3089 Operation::MakeUnreachable(node, stale_key)
3090 }
3091
3092 #[test]
3093 fn split_commit_against_drained_node_fails_instead_of_dropping_insert() {
3094 let set = BTreeSet::<u64>::new();
3095 for seeded in [10u64, 20, 30] {
3096 set.insert(seeded);
3097 }
3098 let node = set.index.read().last_key_value().expect("node must exist").1.clone();
3099 let pending_split = Operation::Split(node.clone(), 30u64, 15u64);
3101 {
3103 let mut guard = node.write();
3104 for seeded in [10u64, 20, 30] {
3105 NodeLike::delete(&mut *guard, &seeded).expect("seeded value must be present");
3106 }
3107 }
3108
3109 assert!(pending_split
3112 .commit::<false>(&mut set.index.write(), super::no_identity_adoption)
3113 .is_err());
3114 assert!(
3115 set.index.read().get(&30).is_some(),
3116 "drained node must stay linked for the retry"
3117 );
3118
3119 assert!(set.insert(15));
3121 assert!(set.contains(&15));
3122 assert_eq!(set.remove(&15), Some(15));
3123 assert!(set.is_empty());
3124 }
3125
3126 #[cfg(feature = "cdc")]
3127 #[test]
3128 fn split_commit_against_drained_node_does_not_panic_in_cdc_build() {
3129 let set = BTreeSet::<u64>::new();
3130 for seeded in [10u64, 20, 30] {
3131 set.insert(seeded);
3132 }
3133 let node = set.index.read().last_key_value().expect("node must exist").1.clone();
3134 let pending_split = Operation::Split(node.clone(), 30u64, 15u64);
3135 {
3136 let mut guard = node.write();
3137 for seeded in [10u64, 20, 30] {
3138 NodeLike::delete(&mut *guard, &seeded).expect("seeded value must be present");
3139 }
3140 }
3141
3142 assert!(pending_split
3145 .commit::<true>(&mut set.index.write(), super::no_identity_adoption)
3146 .is_err());
3147 assert!(set.index.read().get(&30).is_some());
3148
3149 let (old, _events) = set.put_cdc(15);
3150 assert!(old.is_none());
3151 assert!(set.contains(&15));
3152 }
3153
3154 #[test]
3155 fn insert_into_emptied_node_survives_stale_make_unreachable() {
3156 for value in [5u64, 40u64] {
3158 let set = BTreeSet::<u64>::new();
3159 for seeded in [10u64, 20, 30] {
3160 set.insert(seeded);
3161 }
3162 let pending_unlink = drain_node_with_pending_unlink(&set, &[10, 20, 30], 30);
3163
3164 assert!(set.insert(value));
3167
3168 let _ = pending_unlink.commit::<false>(&mut set.index.write(), super::no_identity_adoption);
3171
3172 assert!(set.contains(&value), "value {value} lost after stale unlink");
3173 assert_eq!(set.iter().collect::<Vec<_>>(), vec![value]);
3174 assert_eq!(set.remove(&value), Some(value));
3175 assert!(!set.contains(&value));
3176 assert_eq!(set.len(), 0);
3177 }
3178 }
3179
3180 #[test]
3181 fn stale_make_unreachable_rekeys_refilled_node_instead_of_unlinking() {
3182 for value in [5u64, 40u64] {
3183 let set = BTreeSet::<u64>::new();
3184 for seeded in [10u64, 20, 30] {
3185 set.insert(seeded);
3186 }
3187 let node = set.index.read().last_key_value().expect("node must exist").1.clone();
3188 let pending_unlink = drain_node_with_pending_unlink(&set, &[10, 20, 30], 30);
3189
3190 {
3194 let mut guard = node.write();
3195 NodeLike::insert(&mut *guard, value);
3196 }
3197 let pending_repair = Operation::UpdateMax(node.clone(), 30u64);
3198
3199 assert!(pending_unlink
3202 .commit::<false>(&mut set.index.write(), super::no_identity_adoption)
3203 .is_ok());
3204 let _ = pending_repair.commit::<false>(&mut set.index.write(), super::no_identity_adoption);
3206
3207 assert!(set.contains(&value), "value {value} lost to stale unlink");
3208 assert_eq!(set.remove(&value), Some(value));
3209 assert!(set.is_empty());
3210 }
3211 }
3212
3213 #[test]
3214 fn published_route_updates_when_a_non_last_boundary_shrinks() {
3215 let set = BTreeSet::<u64>::with_maximum_node_size(8);
3216 set.attach_nodes([vec![1, 10], vec![20, 30]]);
3217
3218 assert_eq!(set.remove(&10), Some(10));
3223 assert!(set.insert(5));
3224 assert!(set.contains(&5));
3225 assert_eq!(set.get(&5).map(|value| *value.get()), Some(5));
3226 }
3227
3228 #[test]
3229 fn attach_repairs_a_stale_last_node_boundary() {
3230 let set = BTreeSet::<u64>::with_maximum_node_size(8);
3231 set.attach_node(vec![1, 10]);
3232
3233 assert_eq!(set.remove(&10), Some(10));
3238 set.attach_node(vec![5, 20]);
3239
3240 assert_eq!(set.get(&5).map(|value| *value.get()), Some(5));
3241 assert!(set.contains(&5));
3242 }
3243
3244 #[test]
3245 fn attach_repairs_a_stale_low_last_node_boundary() {
3246 let set = BTreeSet::<u64>::with_maximum_node_size(8);
3247 set.attach_node(vec![1, 10]);
3248
3249 assert!(set.insert(20));
3253 set.attach_node(vec![25, 30]);
3254
3255 assert_eq!(set.get(&20).map(|value| *value.get()), Some(20));
3256 assert_eq!(set.get(&25).map(|value| *value.get()), Some(25));
3257 }
3258
3259 #[test]
3260 fn attach_recovers_from_a_missing_published_identity() {
3261 let set = BTreeSet::<u64>::with_maximum_node_size(8);
3262 set.attach_node(vec![1, 10]);
3263 let last_identity = {
3264 let index = set.index.read();
3265 super::node_identity(index.last_key_value().unwrap().1)
3266 };
3267 assert!(set.index.published_keys.lock().remove(&last_identity).is_some());
3268
3269 set.attach_node(vec![20, 30]);
3270
3271 for value in [1, 10, 20, 30] {
3272 assert_eq!(set.get(&value).map(|found| *found.get()), Some(value));
3273 }
3274 }
3275
3276 #[test]
3277 fn insert_recovers_from_a_missing_replaced_node_identity() {
3278 let set = BTreeSet::<u64>::with_maximum_node_size(8);
3279 set.attach_node(vec![1, 10]);
3280 let old_node = set.index.read().last_key_value().unwrap().1.clone();
3281 assert!(set
3282 .index
3283 .published_keys
3284 .lock()
3285 .remove(&super::node_identity(&old_node))
3286 .is_some());
3287
3288 {
3289 let mut index = set.index.write();
3290 let replaced = index.insert(10, Arc::new(parking_lot::RwLock::new(vec![5, 10])));
3291 assert!(replaced.is_some_and(|node| Arc::ptr_eq(&node, &old_node)));
3292 }
3293
3294 assert!(!set.contains(&1));
3295 assert!(set.contains(&5));
3296 assert!(set.contains(&10));
3297 }
3298
3299 #[test]
3300 fn remove_recovers_from_a_missing_node_identity() {
3301 let set = BTreeSet::<u64>::with_maximum_node_size(8);
3302 set.attach_node(vec![1, 10]);
3303 let old_node = set.index.read().last_key_value().unwrap().1.clone();
3304 assert!(set
3305 .index
3306 .published_keys
3307 .lock()
3308 .remove(&super::node_identity(&old_node))
3309 .is_some());
3310
3311 {
3312 let mut index = set.index.write();
3313 let removed = index.remove(&10).expect("canonical route exists");
3314 assert!(Arc::ptr_eq(&removed, &old_node));
3315 }
3316
3317 assert!(set.is_empty());
3318 assert!(!set.contains(&1));
3319 }
3320
3321 #[test]
3322 fn missing_published_remove_does_not_clone_a_shared_chunk() {
3323 let mut published = super::PublishedNodeIndex::<u64, Vec<u64>> {
3324 chunks: Vec::new(),
3325 len: 0,
3326 };
3327 for key in 0..16 {
3328 published.insert(key, Arc::new(parking_lot::RwLock::new(vec![key])));
3329 }
3330 let snapshot = published.clone();
3331 assert!(Arc::ptr_eq(&published.chunks[0], &snapshot.chunks[0]));
3332
3333 assert!(published.remove(&100).is_none());
3334
3335 assert!(Arc::ptr_eq(&published.chunks[0], &snapshot.chunks[0]));
3336 }
3337
3338 #[test]
3339 fn published_chunks_have_split_merge_hysteresis() {
3340 let mut published = super::PublishedNodeIndex::<u64, Vec<u64>> {
3341 chunks: Vec::new(),
3342 len: 0,
3343 };
3344 for key in 0..=128 {
3345 published.insert(key, Arc::new(parking_lot::RwLock::new(vec![key])));
3346 }
3347 assert_eq!(published.chunks.len(), 2);
3348
3349 for key in 0..33 {
3350 assert!(published.remove(&key).is_some());
3351 }
3352 assert_eq!(published.chunks.len(), 1);
3353
3354 published.insert(0, Arc::new(parking_lot::RwLock::new(vec![0])));
3355 assert_eq!(
3356 published.chunks.len(),
3357 1,
3358 "one insert after a merge must not split again"
3359 );
3360 assert!(published.remove(&0).is_some());
3361 assert_eq!(
3362 published.chunks.len(),
3363 1,
3364 "one remove after a merge must not change chunking"
3365 );
3366 }
3367
3368 #[test]
3369 fn attach_boundary_repair_is_a_complete_publication_by_itself() {
3370 let set = BTreeSet::<u64>::with_maximum_node_size(8);
3371 set.attach_node(vec![1, 10]);
3372 assert_eq!(set.remove(&10), Some(10));
3373
3374 {
3379 let mut index = set.index.write();
3380 index.repair_last_route_before_attach();
3381 }
3382 set.attach_node(vec![5, 20]);
3383
3384 assert_eq!(set.get(&5).map(|found| *found.get()), Some(5));
3385 }
3386
3387 #[cfg(debug_assertions)]
3388 #[test]
3389 #[should_panic(expected = "generic topology removal requires publication")]
3390 fn publication_must_be_enabled_before_an_opt_out_guard_mutates() {
3391 let set = BTreeSet::<u64>::with_maximum_node_size(8);
3392 set.attach_node(vec![1, 10]);
3393 let mut index = set.index.write_rekey();
3394 index.remove(&10);
3395 }
3396
3397 #[test]
3398 fn published_point_routes_match_a_sequential_oracle_under_churn() {
3399 let set = BTreeSet::<u64>::with_maximum_node_size(4);
3400 let mut oracle = std::collections::BTreeSet::new();
3401 let mut state = 0x8f4d_2a71_c390_6be5u64;
3402
3403 for step in 0..2_000 {
3404 state ^= state << 13;
3407 state ^= state >> 7;
3408 state ^= state << 17;
3409 let key = state % 64;
3410 if state & 1 == 0 {
3411 assert_eq!(set.insert(key), oracle.insert(key), "insert step {step}, key {key}");
3412 } else {
3413 assert_eq!(
3414 set.remove(&key).is_some(),
3415 oracle.remove(&key),
3416 "remove step {step}, key {key}"
3417 );
3418 }
3419
3420 for probe in 0..64 {
3421 assert_eq!(
3422 set.contains(&probe),
3423 oracle.contains(&probe),
3424 "point route diverged at step {step}, probe {probe}"
3425 );
3426 }
3427 assert_eq!(
3428 set.iter().collect::<Vec<_>>(),
3429 oracle.iter().copied().collect::<Vec<_>>()
3430 );
3431 }
3432 }
3433
3434 #[test]
3435 fn concurrent_remove_reinsert_over_emptying_nodes_preserves_all_keys() {
3436 const THREADS: u64 = 4;
3437 const ITERATIONS: u64 = 1_000;
3438
3439 let set = Arc::new(BTreeSet::<u64>::with_maximum_node_size(2));
3442 for key in 0..THREADS {
3443 set.insert(key);
3444 }
3445
3446 let start = Arc::new(Barrier::new(THREADS as usize));
3447 let (done_tx, done_rx) = mpsc::channel();
3448 let handles = (0..THREADS)
3449 .map(|key| {
3450 let set = Arc::clone(&set);
3451 let start = Arc::clone(&start);
3452 let done_tx = done_tx.clone();
3453 thread::spawn(move || {
3454 start.wait();
3455 for _ in 0..ITERATIONS {
3456 let mut attempts = 0;
3463 while set.remove(&key).is_none() {
3464 let index = set.index.read();
3465 let present = index.values().any(|node| node.read().contains(&key));
3466 drop(index);
3467 assert!(present, "acknowledged insert of {key} was lost");
3468 attempts += 1;
3469 assert!(attempts < 10_000, "key {key} present but never became removable");
3470 std::hint::spin_loop();
3471 }
3472 assert!(set.insert(key), "{key} still present after acknowledged remove");
3473 }
3474 done_tx.send(()).unwrap();
3475 })
3476 })
3477 .collect::<Vec<_>>();
3478 drop(done_tx);
3479
3480 for _ in 0..THREADS {
3481 done_rx
3482 .recv_timeout(Duration::from_secs(30))
3483 .expect("remove/reinsert workload did not complete in time");
3484 }
3485 for handle in handles {
3486 handle.join().unwrap();
3487 }
3488
3489 for key in 0..THREADS {
3490 assert!(set.contains(&key), "key {key} lost after churn");
3491 assert_eq!(set.remove(&key), Some(key));
3492 }
3493 assert!(set.is_empty());
3494 }
3495
3496 #[test]
3497 fn test_remove_single_element() {
3498 let set = BTreeSet::<i32>::new();
3499 set.insert(5);
3500 assert!(set.contains(&5));
3501 assert!(set.remove(&5).is_some());
3502 assert!(!set.contains(&5));
3503 assert!(!set.remove(&5).is_some());
3504 }
3505
3506 #[test]
3507 fn test_remove_multiple_elements() {
3508 let set = BTreeSet::<i32>::new();
3509 for i in 0..2048 {
3510 set.insert(i);
3511 }
3512 for i in 0..2048 {
3513 assert!(set.remove(&i).is_some());
3514 assert!(!set.contains(&i));
3515 }
3516 assert_eq!(set.len(), 0);
3517 }
3518
3519 #[test]
3520 fn test_remove_non_existent() {
3521 let set = BTreeSet::<i32>::new();
3522 set.insert(5);
3523 assert!(!set.remove(&10).is_some());
3524 assert!(set.contains(&5));
3525 }
3526
3527 #[test]
3528 fn test_remove_stress() {
3529 let set = Arc::new(BTreeSet::<i32>::new());
3530 const NUM_ELEMENTS: i32 = 10000;
3531
3532 for i in 0..NUM_ELEMENTS {
3533 set.insert(i);
3534 }
3535 assert_eq!(set.len(), NUM_ELEMENTS as usize, "Incorrect size after insertion");
3536
3537 let num_threads = 8;
3538 let elements_per_thread = NUM_ELEMENTS / num_threads;
3539 let handles: Vec<_> = (0..num_threads)
3540 .map(|t| {
3541 let set = Arc::clone(&set);
3542 thread::spawn(move || {
3543 for i in (t * elements_per_thread)..((t + 1) * elements_per_thread) {
3544 if i % 2 == 1 {
3545 assert!(set.remove(&i).is_some(), "Failed to remove {}", i);
3546 }
3547 }
3548 })
3549 })
3550 .collect();
3551
3552 for handle in handles {
3553 handle.join().unwrap();
3554 }
3555
3556 assert_eq!(set.len(), NUM_ELEMENTS as usize / 2, "Incorrect size after removal");
3557
3558 for i in 0..NUM_ELEMENTS {
3559 if i % 2 == 0 {
3560 assert!(set.contains(&i), "Even number {} should be in the set", i);
3561 } else {
3562 assert!(!set.contains(&i), "Odd number {} should not be in the set", i);
3563 }
3564 }
3565 }
3566
3567 #[test]
3568 fn test_remove_all_elements() {
3569 let set = BTreeSet::<i32>::new();
3570 let n = 2048;
3571
3572 for i in 0..n {
3573 set.insert(i);
3574 }
3575
3576 for i in 0..n {
3577 assert!(set.remove(&i).is_some(), "Failed to remove {}", i);
3578 }
3579
3580 assert_eq!(set.len(), 0, "Set should be empty");
3581
3582 for i in 0..n {
3583 assert!(!set.contains(&i), "Element {} should not be in the set", i);
3584 }
3585 }
3586
3587 #[test]
3588 fn test_range_edge_cases() {
3589 let set = BTreeSet::<i32>::with_maximum_node_size(10);
3590 for i in 0..20 {
3591 set.insert(i);
3592 }
3593 assert_eq!(set.range(0..=0).collect::<Vec<_>>(), vec![0]);
3600 assert_eq!(set.range(0..1).collect::<Vec<_>>(), vec![0]);
3601
3602 assert_eq!(set.range(5..=5).collect::<Vec<_>>(), vec![5]);
3603 assert_eq!(set.range(5..6).collect::<Vec<_>>(), vec![5]);
3604
3605 assert_eq!(set.range(10..=10).collect::<Vec<_>>(), vec![10]);
3606 assert_eq!(set.range(10..11).collect::<Vec<_>>(), vec![10]);
3607
3608 assert_eq!(set.range(0..=3).collect::<Vec<_>>(), vec![0, 1, 2, 3]);
3610 assert_eq!(set.range(0..3).collect::<Vec<_>>(), vec![0, 1, 2]);
3611
3612 assert_eq!(set.range(5..=8).collect::<Vec<_>>(), vec![5, 6, 7, 8]);
3613 assert_eq!(set.range(5..8).collect::<Vec<_>>(), vec![5, 6, 7]);
3614
3615 assert_eq!(set.range(10..=13).collect::<Vec<_>>(), vec![10, 11, 12, 13]);
3616 assert_eq!(set.range(10..13).collect::<Vec<_>>(), vec![10, 11, 12]);
3617
3618 assert_eq!(set.range(4..=4).collect::<Vec<_>>(), vec![4]);
3620 assert_eq!(set.range(4..5).collect::<Vec<_>>(), vec![4]);
3621
3622 assert_eq!(set.range(9..=9).collect::<Vec<_>>(), vec![9]);
3623 assert_eq!(set.range(9..10).collect::<Vec<_>>(), vec![9]);
3624
3625 assert_eq!(set.range(19..=19).collect::<Vec<_>>(), vec![19]);
3626 assert_eq!(set.range(19..20).collect::<Vec<_>>(), vec![19]);
3627
3628 assert_eq!(set.range(17..=19).collect::<Vec<_>>(), vec![17, 18, 19]);
3630 assert_eq!(set.range(17..20).collect::<Vec<_>>(), vec![17, 18, 19]);
3631
3632 assert_eq!(set.range(7..=9).collect::<Vec<_>>(), vec![7, 8, 9]);
3633 assert_eq!(set.range(7..10).collect::<Vec<_>>(), vec![7, 8, 9]);
3634
3635 assert_eq!(set.range(2..=4).collect::<Vec<_>>(), vec![2, 3, 4]);
3636 assert_eq!(set.range(2..5).collect::<Vec<_>>(), vec![2, 3, 4]);
3637
3638 assert_eq!(set.range(0..=4).collect::<Vec<_>>(), vec![0, 1, 2, 3, 4]);
3640 assert_eq!(set.range(0..5).collect::<Vec<_>>(), vec![0, 1, 2, 3, 4]);
3641
3642 assert_eq!(set.range(5..=9).collect::<Vec<_>>(), vec![5, 6, 7, 8, 9]);
3643 assert_eq!(set.range(5..10).collect::<Vec<_>>(), vec![5, 6, 7, 8, 9]);
3644
3645 assert_eq!(
3646 set.range(10..=19).collect::<Vec<_>>(),
3647 vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
3648 );
3649 assert_eq!(
3650 set.range(10..20).collect::<Vec<_>>(),
3651 vec![10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
3652 );
3653
3654 assert_eq!(set.range(3..=6).collect::<Vec<_>>(), vec![3, 4, 5, 6]);
3656 assert_eq!(set.range(3..7).collect::<Vec<_>>(), vec![3, 4, 5, 6]);
3657
3658 assert_eq!(set.range(8..=11).collect::<Vec<_>>(), vec![8, 9, 10, 11]);
3659 assert_eq!(set.range(8..12).collect::<Vec<_>>(), vec![8, 9, 10, 11]);
3660
3661 assert_eq!(set.range(0..=0).rev().collect::<Vec<_>>(), vec![0]);
3665 assert_eq!(set.range(0..1).rev().collect::<Vec<_>>(), vec![0]);
3666
3667 assert_eq!(set.range(5..=5).rev().collect::<Vec<_>>(), vec![5]);
3668 assert_eq!(set.range(5..6).rev().collect::<Vec<_>>(), vec![5]);
3669
3670 assert_eq!(set.range(10..=10).rev().collect::<Vec<_>>(), vec![10]);
3671 assert_eq!(set.range(10..11).rev().collect::<Vec<_>>(), vec![10]);
3672
3673 assert_eq!(set.range(0..=3).rev().collect::<Vec<_>>(), vec![3, 2, 1, 0]);
3675 assert_eq!(set.range(0..3).rev().collect::<Vec<_>>(), vec![2, 1, 0]);
3676
3677 assert_eq!(set.range(5..=8).rev().collect::<Vec<_>>(), vec![8, 7, 6, 5]);
3678 assert_eq!(set.range(5..8).rev().collect::<Vec<_>>(), vec![7, 6, 5]);
3679
3680 assert_eq!(set.range(10..=13).rev().collect::<Vec<_>>(), vec![13, 12, 11, 10]);
3681 assert_eq!(set.range(10..13).rev().collect::<Vec<_>>(), vec![12, 11, 10]);
3682
3683 assert_eq!(set.range(4..=4).rev().collect::<Vec<_>>(), vec![4]);
3685 assert_eq!(set.range(4..5).rev().collect::<Vec<_>>(), vec![4]);
3686
3687 assert_eq!(set.range(9..=9).rev().collect::<Vec<_>>(), vec![9]);
3688 assert_eq!(set.range(9..10).rev().collect::<Vec<_>>(), vec![9]);
3689
3690 assert_eq!(set.range(19..=19).rev().collect::<Vec<_>>(), vec![19]);
3691 assert_eq!(set.range(19..20).rev().collect::<Vec<_>>(), vec![19]);
3692
3693 assert_eq!(set.range(17..=19).rev().collect::<Vec<_>>(), vec![19, 18, 17]);
3695 assert_eq!(set.range(17..20).rev().collect::<Vec<_>>(), vec![19, 18, 17]);
3696
3697 assert_eq!(set.range(7..=9).rev().collect::<Vec<_>>(), vec![9, 8, 7]);
3698 assert_eq!(set.range(7..10).rev().collect::<Vec<_>>(), vec![9, 8, 7]);
3699
3700 assert_eq!(set.range(2..=4).rev().collect::<Vec<_>>(), vec![4, 3, 2]);
3701 assert_eq!(set.range(2..5).rev().collect::<Vec<_>>(), vec![4, 3, 2]);
3702
3703 assert_eq!(set.range(0..=4).rev().collect::<Vec<_>>(), vec![4, 3, 2, 1, 0]);
3705 assert_eq!(set.range(0..5).rev().collect::<Vec<_>>(), vec![4, 3, 2, 1, 0]);
3706
3707 assert_eq!(set.range(5..=9).rev().collect::<Vec<_>>(), vec![9, 8, 7, 6, 5]);
3708 assert_eq!(set.range(5..10).rev().collect::<Vec<_>>(), vec![9, 8, 7, 6, 5]);
3709
3710 assert_eq!(
3711 set.range(10..=19).rev().collect::<Vec<_>>(),
3712 vec![19, 18, 17, 16, 15, 14, 13, 12, 11, 10]
3713 );
3714 assert_eq!(
3715 set.range(10..20).rev().collect::<Vec<_>>(),
3716 vec![19, 18, 17, 16, 15, 14, 13, 12, 11, 10]
3717 );
3718
3719 assert_eq!(set.range(3..=6).rev().collect::<Vec<_>>(), vec![6, 5, 4, 3]);
3721 assert_eq!(set.range(3..7).rev().collect::<Vec<_>>(), vec![6, 5, 4, 3]);
3722
3723 assert_eq!(set.range(8..=11).rev().collect::<Vec<_>>(), vec![11, 10, 9, 8]);
3724 assert_eq!(set.range(8..12).rev().collect::<Vec<_>>(), vec![11, 10, 9, 8]);
3725
3726 assert!(set.range(20..).collect::<Vec<_>>().is_empty());
3728 assert!(set.range(..0).collect::<Vec<_>>().is_empty());
3729 assert!(set.range(20..).rev().collect::<Vec<_>>().is_empty());
3730 assert!(set.range(..0).rev().collect::<Vec<_>>().is_empty());
3731 }
3732
3733 #[test]
3734 fn concurrent_range_constructions_at_node_boundaries_do_not_deadlock() {
3735 const THREAD_ITERATIONS: usize = 20_000;
3736
3737 let set = Arc::new(BTreeSet::<u64>::with_maximum_node_size(4));
3738 for value in 0..64 {
3739 set.insert(value);
3740 }
3741
3742 let (done_tx, done_rx) = mpsc::channel();
3748 let forward = {
3749 let set = Arc::clone(&set);
3750 let done_tx = done_tx.clone();
3751 thread::spawn(move || {
3752 for iteration in 0..THREAD_ITERATIONS {
3753 let start = (iteration % 64) as u64;
3754 assert_eq!(set.range(start..).next(), Some(start));
3755 }
3756 done_tx.send(()).unwrap();
3757 })
3758 };
3759 let backward = {
3760 let set = Arc::clone(&set);
3761 let done_tx = done_tx.clone();
3762 thread::spawn(move || {
3763 for iteration in 0..THREAD_ITERATIONS {
3764 let end = (iteration % 64) as u64;
3765 assert_eq!(set.range(..=end).next_back(), Some(end));
3766 }
3767 done_tx.send(()).unwrap();
3768 })
3769 };
3770 drop(done_tx);
3771
3772 for _ in 0..2 {
3773 done_rx
3774 .recv_timeout(Duration::from_secs(30))
3775 .expect("concurrent range constructions deadlocked");
3776 }
3777 forward.join().unwrap();
3778 backward.join().unwrap();
3779 }
3780
3781 fn three_node_set() -> BTreeSet<u64> {
3783 let set = BTreeSet::<u64>::with_maximum_node_size(4);
3784 for value in [0u64, 10, 20, 30, 40, 50, 60] {
3785 set.insert(value);
3786 }
3787 assert_eq!(
3788 set.index.read().keys().copied().collect::<Vec<_>>(),
3789 vec![10, 30, 60],
3790 "fixture geometry changed"
3791 );
3792 set
3793 }
3794
3795 #[test]
3796 fn forward_scan_repositions_when_current_node_vanishes() {
3797 let set = three_node_set();
3798
3799 let mut iter = set.iter();
3800 assert_eq!(iter.next(), Some(0));
3801 assert_eq!(iter.next(), Some(10));
3802 assert_eq!(iter.next(), Some(20));
3803
3804 set.index.write().remove(&30).expect("fixture entry");
3808
3809 assert_eq!(iter.next(), Some(30));
3810 assert_eq!(iter.next(), Some(40));
3811 assert_eq!(iter.next(), Some(50));
3812 assert_eq!(iter.next(), Some(60));
3813 assert_eq!(iter.next(), None);
3814 }
3815
3816 #[test]
3817 fn backward_scan_repositions_when_current_node_vanishes() {
3818 let set = three_node_set();
3819
3820 let mut iter = set.iter();
3821 assert_eq!(iter.next_back(), Some(60));
3822 assert_eq!(iter.next_back(), Some(50));
3823
3824 set.index.write().remove(&60).expect("fixture entry");
3825
3826 assert_eq!(iter.next_back(), Some(40));
3827 assert_eq!(iter.next_back(), Some(30));
3828 assert_eq!(iter.next_back(), Some(20));
3829 assert_eq!(iter.next_back(), Some(10));
3830 assert_eq!(iter.next_back(), Some(0));
3831 assert_eq!(iter.next_back(), None);
3832 }
3833
3834 #[test]
3835 fn forward_scan_does_not_re_yield_after_split_of_finished_node() {
3836 let set = BTreeSet::<u64>::with_maximum_node_size(4);
3839 for value in [0u64, 10, 20, 30, 40] {
3840 set.insert(value);
3841 }
3842
3843 let iter = Iter {
3847 tree: &set,
3848 current_front_batch: None,
3849 current_back_batch: None,
3850 exhausted_front_node: Some(set.index.read().first_key_value().expect("fixture node").1.clone()),
3851 exhausted_back_node: None,
3852 front_partial: None,
3853 back_partial: None,
3854 front_batch_limit: INITIAL_BATCH,
3855 back_batch_limit: INITIAL_BATCH,
3856 current_front_value: Some(20),
3857 current_back_value: None,
3858 met: false,
3859 };
3860
3861 assert_eq!(iter.collect::<Vec<_>>(), vec![30, 40]);
3862 }
3863
3864 #[test]
3865 fn backward_scan_does_not_re_yield_values_from_scanned_range() {
3866 let set = BTreeSet::<u64>::new();
3870 set.attach_node(vec![0u64, 10]);
3871 set.attach_node(vec![30u64, 40]);
3872 {
3873 let node = set.index.read().first_key_value().expect("fixture node").1.clone();
3874 let mut guard = node.write();
3875 NodeLike::insert(&mut *guard, 35u64);
3876 }
3877
3878 let mut iter = Iter {
3879 tree: &set,
3880 current_front_batch: None,
3881 current_back_batch: None,
3882 exhausted_front_node: None,
3883 exhausted_back_node: Some(set.index.read().last_key_value().expect("fixture node").1.clone()),
3884 front_partial: None,
3885 back_partial: None,
3886 front_batch_limit: INITIAL_BATCH,
3887 back_batch_limit: INITIAL_BATCH,
3888 current_front_value: None,
3889 current_back_value: Some(30),
3890 met: false,
3891 };
3892
3893 let mut collected = vec![];
3894 while let Some(value) = iter.next_back() {
3895 collected.push(value);
3896 }
3897 assert_eq!(collected, vec![10, 0]);
3898 }
3899
3900 #[test]
3901 fn backward_scan_does_not_skip_values_split_away_after_positioning() {
3902 let set = BTreeSet::<u64>::with_maximum_node_size(4);
3910 for value in [0u64, 10, 20, 30] {
3911 set.insert(value);
3912 }
3913
3914 let mut iter = set.iter();
3916 set.insert(40);
3920 assert!(set.node_count() > 1, "fixture must split");
3921
3922 let mut collected = vec![];
3923 while let Some(value) = iter.next_back() {
3924 collected.push(value);
3925 }
3926
3927 for baseline in [30u64, 20, 10, 0] {
3933 assert!(
3934 collected.iter().any(|value| *value == baseline),
3935 "baseline value {baseline} skipped by backward scan (yielded: {collected:?})"
3936 );
3937 }
3938 assert!(
3939 collected.windows(2).all(|pair| pair[0] > pair[1]),
3940 "backward scan not strictly decreasing: {collected:?}"
3941 );
3942 }
3943
3944 #[test]
3945 fn bidirectional_meet_into_opposite_held_node_does_not_self_deadlock() {
3946 let set = Arc::new(BTreeSet::<u64>::with_maximum_node_size(4));
3948 for value in [0u64, 10, 20, 30, 40] {
3949 set.insert(value);
3950 }
3951
3952 let (done_tx, done_rx) = mpsc::channel();
3953 let handle = {
3954 let set = Arc::clone(&set);
3955 thread::spawn(move || {
3956 let mut finished = set.iter();
3963 assert_eq!(finished.next_back(), Some(40));
3964 assert_eq!(finished.next(), Some(0));
3965 assert_eq!(finished.next(), Some(10));
3966 assert_eq!(finished.next(), Some(20));
3967 assert_eq!(finished.next(), Some(30));
3968 assert_eq!(finished.next(), None);
3969 assert_eq!(finished.next_back(), None);
3970
3971 let mut iter = set.iter();
3976 assert_eq!(iter.next(), Some(0));
3977 assert_eq!(iter.next_back(), Some(40));
3978 assert_eq!(iter.next_back(), Some(30));
3979 assert_eq!(iter.next_back(), Some(20));
3980 assert_eq!(iter.next_back(), Some(10));
3981 assert_eq!(iter.next_back(), None);
3982 assert_eq!(iter.next(), None);
3983 drop(finished);
3984
3985 done_tx.send(()).unwrap();
3986 })
3987 };
3988
3989 done_rx
3990 .recv_timeout(Duration::from_secs(10))
3991 .expect("bidirectional meet-in-the-middle deadlocked");
3992 handle.join().unwrap();
3993 }
3994
3995 #[test]
3996 fn structural_commits_complete_against_paused_scan() {
3997 let set = Arc::new(BTreeSet::<u64>::with_maximum_node_size(2));
3999 for value in 0..8 {
4000 set.insert(value);
4001 }
4002
4003 let scan_holds_guard = Arc::new(Barrier::new(3));
4004 let (done_tx, done_rx) = mpsc::channel();
4005
4006 let scanner = {
4007 let set = Arc::clone(&set);
4008 let scan_holds_guard = Arc::clone(&scan_holds_guard);
4009 let done_tx = done_tx.clone();
4010 thread::spawn(move || {
4011 let mut iter = set.iter();
4012 assert_eq!(iter.next(), Some(0));
4016 scan_holds_guard.wait();
4017 thread::sleep(Duration::from_millis(100));
4020 let mut collected = vec![];
4025 while let Some(value) = iter.next_back() {
4026 collected.push(value);
4027 }
4028 assert_eq!(collected, vec![7, 6, 5, 4, 3, 2, 1]);
4029 done_tx.send(()).unwrap();
4030 })
4031 };
4032
4033 let writer = {
4034 let set = Arc::clone(&set);
4035 let scan_holds_guard = Arc::clone(&scan_holds_guard);
4036 let done_tx = done_tx.clone();
4037 thread::spawn(move || {
4038 scan_holds_guard.wait();
4039 set.remove_range(0..=0);
4042 done_tx.send(()).unwrap();
4043 })
4044 };
4045 drop(done_tx);
4046 scan_holds_guard.wait();
4047
4048 for _ in 0..2 {
4049 done_rx
4050 .recv_timeout(Duration::from_secs(10))
4051 .expect("scan or structural commit deadlocked");
4052 }
4053 scanner.join().unwrap();
4054 writer.join().unwrap();
4055 assert!(!set.contains(&0));
4056 }
4057
4058 #[test]
4059 fn full_scans_do_not_degrade_quadratically_with_node_count() {
4060 use std::time::Instant;
4061
4062 const VALUES: u64 = 30_000;
4064 let set = BTreeSet::<u64>::with_maximum_node_size(2);
4065 for value in 0..VALUES {
4066 set.insert(value);
4067 }
4068 assert!(
4069 set.node_count() >= (VALUES / 4) as usize,
4070 "fixture must be a many-node tree, got {} nodes",
4071 set.node_count()
4072 );
4073
4074 let started = Instant::now();
4075 assert_eq!(set.iter().count(), VALUES as usize);
4076 let forward = started.elapsed();
4077
4078 let started = Instant::now();
4079 assert_eq!(set.iter().rev().count(), VALUES as usize);
4080 let backward = started.elapsed();
4081
4082 let budget = Duration::from_secs(10);
4088 assert!(
4089 forward < budget,
4090 "forward scan took {forward:?}, node advance is not logarithmic"
4091 );
4092 assert!(
4093 backward < budget,
4094 "backward scan took {backward:?}, node advance is not logarithmic"
4095 );
4096 }
4097
4098 #[test]
4099 fn scans_stay_sorted_and_complete_under_monotonic_insert_churn() {
4100 use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
4101
4102 const BASELINE: u64 = 400;
4103 const EXTRA: u64 = 2_000;
4104 const SCAN_BOUND: usize = 10_000;
4105
4106 let set = Arc::new(BTreeSet::<u64>::with_maximum_node_size(8));
4109 for value in 0..BASELINE {
4110 set.insert(value);
4111 }
4112
4113 let done = Arc::new(AtomicBool::new(false));
4114 let writer = {
4115 let set = Arc::clone(&set);
4116 let done = Arc::clone(&done);
4117 thread::spawn(move || {
4118 for value in BASELINE..BASELINE + EXTRA {
4119 assert!(set.insert(value));
4120 }
4121 done.store(true, AtomicOrdering::Release);
4122 })
4123 };
4124
4125 let mut scans = 0usize;
4126 loop {
4127 let forward = set.iter().collect::<Vec<_>>();
4128 assert!(
4129 forward.windows(2).all(|pair| pair[0] < pair[1]),
4130 "forward scan not strictly increasing (duplicate or unordered yield)"
4131 );
4132 assert_eq!(
4133 forward.iter().filter(|value| **value < BASELINE).count() as u64,
4134 BASELINE,
4135 "forward scan truncated: baseline keys missing"
4136 );
4137
4138 let backward = set.iter().rev().collect::<Vec<_>>();
4139 assert!(
4140 backward.windows(2).all(|pair| pair[0] > pair[1]),
4141 "backward scan not strictly decreasing (duplicate or unordered yield)"
4142 );
4143 assert_eq!(
4144 backward.iter().filter(|value| **value < BASELINE).count() as u64,
4145 BASELINE,
4146 "backward scan truncated: baseline keys missing"
4147 );
4148
4149 scans += 1;
4150 if done.load(AtomicOrdering::Acquire) || scans >= SCAN_BOUND {
4151 break;
4152 }
4153 }
4154
4155 writer.join().unwrap();
4156
4157 let expected = (0..BASELINE + EXTRA).collect::<Vec<_>>();
4158 assert_eq!(set.iter().collect::<Vec<_>>(), expected);
4159 assert_eq!(set.iter().rev().collect::<Vec<_>>(), {
4160 let mut reversed = expected;
4161 reversed.reverse();
4162 reversed
4163 });
4164 }
4165
4166 #[test]
4167 fn collected_owned_values_survive_arbitrary_concurrent_mutation() {
4168 use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering};
4169
4170 const BASELINE: u64 = 512;
4171 const CHURN: u64 = 4_000;
4172
4173 let set = Arc::new(BTreeSet::<u64>::with_maximum_node_size(8));
4176 for value in 0..BASELINE {
4177 set.insert(value);
4178 }
4179
4180 let done = Arc::new(AtomicBool::new(false));
4181 let writer = {
4182 let set = Arc::clone(&set);
4183 let done = Arc::clone(&done);
4184 thread::spawn(move || {
4185 for value in BASELINE..BASELINE + CHURN {
4186 assert!(set.insert(value));
4187 assert_eq!(set.remove(&value), Some(value));
4188 }
4189 done.store(true, AtomicOrdering::Release);
4190 })
4191 };
4192
4193 let mut snapshots: Vec<Vec<u64>> = Vec::new();
4198 loop {
4199 let snapshot: Vec<u64> = set.iter().collect();
4200 snapshots.push(snapshot);
4201 if done.load(AtomicOrdering::Acquire) {
4202 break;
4203 }
4204 }
4205 writer.join().unwrap();
4206
4207 set.remove_range(..);
4210 assert!(set.is_empty());
4211
4212 for snapshot in snapshots {
4213 assert!(
4214 snapshot.windows(2).all(|pair| pair[0] < pair[1]),
4215 "snapshot not strictly increasing"
4216 );
4217 assert_eq!(
4218 snapshot.iter().filter(|value| **value < BASELINE).count() as u64,
4219 BASELINE,
4220 "snapshot lost baseline keys"
4221 );
4222 }
4223 }
4224
4225 #[test]
4226 fn parallel_iter_and_mut() {
4227 let set = Arc::new(BTreeSet::<i32>::new());
4228 for i in 0..10_000 {
4229 set.insert(i);
4230 }
4231
4232 let set_clone = Arc::clone(&set);
4233 let handle = thread::spawn(move || {
4234 for _ in 0..1000 {
4235 let mut _sum = 0;
4236 for value in set_clone.iter() {
4237 _sum += value;
4238 }
4239 }
4240 });
4241
4242 for i in 10_000..20_000 {
4243 set.insert(i);
4244 }
4245 handle.join().unwrap();
4246 }
4247
4248 #[test]
4257 fn a_scan_across_several_batch_installs_is_complete_and_ordered() {
4258 let set: BTreeSet<u64> = BTreeSet::new();
4259 let count = (INITIAL_BATCH * 20) as u64;
4262 for i in 0..count {
4263 set.insert(i);
4264 }
4265
4266 let seen: Vec<u64> = set.iter().collect();
4267 let expected: Vec<u64> = (0..count).collect();
4268 assert_eq!(seen, expected, "a partial-batch scan lost or repeated elements");
4269 }
4270
4271 #[test]
4273 fn a_backward_scan_across_several_installs_is_complete_and_ordered() {
4274 let set: BTreeSet<u64> = BTreeSet::new();
4275 let count = (INITIAL_BATCH * 20) as u64;
4276 for i in 0..count {
4277 set.insert(i);
4278 }
4279
4280 let seen: Vec<u64> = set.iter().rev().collect();
4281 let expected: Vec<u64> = (0..count).rev().collect();
4282 assert_eq!(
4283 seen, expected,
4284 "a partial-batch backward scan lost or repeated elements"
4285 );
4286 }
4287
4288 #[test]
4291 fn a_scan_within_a_single_node_resumes_correctly() {
4292 let set: BTreeSet<u64> = BTreeSet::with_maximum_node_size(DEFAULT_INNER_SIZE);
4293 let count = 200u64;
4294 for i in 0..count {
4295 set.insert(i);
4296 }
4297 assert_eq!(set.node_count(), 1, "fixture wants one node");
4298
4299 let seen: Vec<u64> = set.iter().collect();
4300 assert_eq!(seen, (0..count).collect::<Vec<_>>());
4301 }
4302
4303 #[test]
4308 fn a_single_element_range_yields_one_element() {
4309 let set: BTreeSet<u64> = BTreeSet::new();
4310 for i in 0..1_000u64 {
4311 set.insert(i);
4312 }
4313
4314 for probe in [0u64, 1, 499, 998, 999] {
4315 let got: Vec<u64> = set.range(probe..=probe).collect();
4316 assert_eq!(got, vec![probe], "range({probe}..={probe})");
4317 }
4318 assert!(set.range(1_000..=1_000).next().is_none(), "absent key");
4319 }
4320
4321 #[test]
4326 fn ranges_spanning_batch_boundaries_are_exact() {
4327 let set: BTreeSet<u64> = BTreeSet::new();
4328 for i in 0..500u64 {
4329 set.insert(i);
4330 }
4331
4332 for width in 1..=(INITIAL_BATCH * 8) as u64 {
4333 let start = 100u64;
4334 let got: Vec<u64> = set.range(start..start + width).collect();
4335 let expected: Vec<u64> = (start..start + width).collect();
4336 assert_eq!(got, expected, "range width {width}");
4337 }
4338 }
4339
4340 #[test]
4345 fn a_double_ended_scan_meets_without_repeating() {
4346 let set: BTreeSet<u64> = BTreeSet::new();
4347 let count = (INITIAL_BATCH * 10) as u64;
4348 for i in 0..count {
4349 set.insert(i);
4350 }
4351
4352 let mut iter = set.iter();
4353 let mut front = Vec::new();
4354 let mut back = Vec::new();
4355 loop {
4356 match iter.next() {
4357 Some(v) => front.push(v),
4358 None => break,
4359 }
4360 match iter.next_back() {
4361 Some(v) => back.push(v),
4362 None => break,
4363 }
4364 }
4365 back.reverse();
4366 front.extend(back);
4367 front.sort_unstable();
4368 assert_eq!(
4369 front,
4370 (0..count).collect::<Vec<_>>(),
4371 "double-ended scan is not a partition"
4372 );
4373 }
4374
4375 #[test]
4391 fn a_scan_under_concurrent_mutation_terminates() {
4392 use std::sync::atomic::{AtomicBool, Ordering};
4393 use std::sync::Arc;
4394
4395 const SIZE: u64 = 4_000;
4396 const CAP: usize = (SIZE * 20) as usize;
4399
4400 for _ in 0..8 {
4401 let set: Arc<BTreeSet<u64>> = Arc::new(BTreeSet::new());
4402 for i in 0..SIZE {
4403 set.insert(i);
4404 }
4405 let stop = Arc::new(AtomicBool::new(false));
4406
4407 let writers: Vec<_> = (0..3)
4409 .map(|w| {
4410 let (set, stop) = (Arc::clone(&set), Arc::clone(&stop));
4411 std::thread::spawn(move || {
4412 let mut i = SIZE + w * 100_000;
4413 while !stop.load(Ordering::Relaxed) {
4414 set.insert(i);
4415 set.remove(&i);
4416 i += 1;
4417 }
4418 })
4419 })
4420 .collect();
4421
4422 let mut yielded = 0usize;
4423 for _ in set.iter() {
4424 yielded += 1;
4425 if yielded >= CAP {
4426 break;
4427 }
4428 }
4429
4430 stop.store(true, Ordering::Relaxed);
4431 for w in writers {
4432 w.join().expect("writer did not panic");
4433 }
4434
4435 assert!(
4436 yielded < CAP,
4437 "scan did not make progress under concurrent mutation: {yielded} yields"
4438 );
4439 }
4440 }
4441
4442 #[allow(clippy::manual_contains)]
4450 fn yielded(seen: &[u64], value: u64) -> bool {
4451 seen.iter().any(|item| *item == value)
4452 }
4453
4454 #[test]
4467 fn deleting_a_yielded_element_does_not_skip_a_live_one() {
4468 for prefix in 1..12usize {
4469 let set: BTreeSet<u64> = BTreeSet::new();
4470 for i in 0..256u64 {
4471 set.insert(i);
4472 }
4473
4474 let mut seen = Vec::new();
4475 for value in set.iter() {
4476 seen.push(value);
4477 if seen.len() == prefix {
4478 set.remove(&0);
4479 }
4480 }
4481
4482 for expected in 1..256u64 {
4483 assert!(
4484 yielded(&seen, expected),
4485 "prefix {prefix}: {expected} was present for the whole scan but was never yielded"
4486 );
4487 }
4488 }
4489 }
4490
4491 #[test]
4495 fn deleting_a_yielded_element_backwards_does_not_skip_a_live_one() {
4496 for prefix in 1..12usize {
4497 let set: BTreeSet<u64> = BTreeSet::new();
4498 for i in 0..256u64 {
4499 set.insert(i);
4500 }
4501
4502 let mut seen = Vec::new();
4503 for value in set.iter().rev() {
4504 seen.push(value);
4505 if seen.len() == prefix {
4506 set.remove(&255);
4507 }
4508 }
4509
4510 for expected in 0..255u64 {
4511 assert!(
4512 yielded(&seen, expected),
4513 "prefix {prefix}: {expected} was present for the whole scan but was never yielded"
4514 );
4515 }
4516 }
4517 }
4518}