Coverage Report

Created: 2025-07-18 06:42

/rust/registry/src/index.crates.io-6f17d22bba15001f/sharded-slab-0.1.7/src/pool.rs
Line
Count
Source (jump to first uncovered line)
1
//! A lock-free concurrent object pool.
2
//!
3
//! See the [`Pool` type's documentation][pool] for details on the object pool API and how
4
//! it differs from the [`Slab`] API.
5
//!
6
//! [pool]: ../struct.Pool.html
7
//! [`Slab`]: ../struct.Slab.html
8
use crate::{
9
    cfg::{self, CfgPrivate, DefaultConfig},
10
    clear::Clear,
11
    page, shard,
12
    tid::Tid,
13
    Pack, Shard,
14
};
15
16
use std::{fmt, marker::PhantomData, sync::Arc};
17
18
/// A lock-free concurrent object pool.
19
///
20
/// Slabs provide pre-allocated storage for many instances of a single type. But, when working with
21
/// heap allocated objects, the advantages of a slab are lost, as the memory allocated for the
22
/// object is freed when the object is removed from the slab. With a pool, we can instead reuse
23
/// this memory for objects being added to the pool in the future, therefore reducing memory
24
/// fragmentation and avoiding additional allocations.
25
///
26
/// This type implements a lock-free concurrent pool, indexed by `usize`s. The items stored in this
27
/// type need to implement [`Clear`] and `Default`.
28
///
29
/// The `Pool` type shares similar semantics to [`Slab`] when it comes to sharing across threads
30
/// and storing mutable shared data. The biggest difference is there are no [`Slab::insert`] and
31
/// [`Slab::take`] analouges for the `Pool` type. Instead new items are added to the pool by using
32
/// the [`Pool::create`] method, and marked for clearing by the [`Pool::clear`] method.
33
///
34
/// # Examples
35
///
36
/// Add an entry to the pool, returning an index:
37
/// ```
38
/// # use sharded_slab::Pool;
39
/// let pool: Pool<String> = Pool::new();
40
///
41
/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
42
/// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
43
/// ```
44
///
45
/// Create a new pooled item, returning a guard that allows mutable access:
46
/// ```
47
/// # use sharded_slab::Pool;
48
/// let pool: Pool<String> = Pool::new();
49
///
50
/// let mut guard = pool.create().unwrap();
51
/// let key = guard.key();
52
/// guard.push_str("hello world");
53
///
54
/// drop(guard); // release the guard, allowing immutable access.
55
/// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
56
/// ```
57
///
58
/// Pool entries can be cleared by calling [`Pool::clear`]. This marks the entry to
59
/// be cleared when the guards referencing to it are dropped.
60
/// ```
61
/// # use sharded_slab::Pool;
62
/// let pool: Pool<String> = Pool::new();
63
///
64
/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
65
///
66
/// // Mark this entry to be cleared.
67
/// pool.clear(key);
68
///
69
/// // The cleared entry is no longer available in the pool
70
/// assert!(pool.get(key).is_none());
71
/// ```
72
/// # Configuration
73
///
74
/// Both `Pool` and [`Slab`] share the same configuration mechanism. See [crate level documentation][config-doc]
75
/// for more details.
76
///
77
/// [`Slab::take`]: crate::Slab::take
78
/// [`Slab::insert`]: crate::Slab::insert
79
/// [`Pool::create`]: Pool::create
80
/// [`Pool::clear`]: Pool::clear
81
/// [config-doc]: crate#configuration
82
/// [`Clear`]: crate::Clear
83
/// [`Slab`]: crate::Slab
84
pub struct Pool<T, C = DefaultConfig>
85
where
86
    T: Clear + Default,
87
    C: cfg::Config,
88
{
89
    shards: shard::Array<T, C>,
90
    _cfg: PhantomData<C>,
91
}
92
93
/// A guard that allows access to an object in a pool.
94
///
95
/// While the guard exists, it indicates to the pool that the item the guard references is
96
/// currently being accessed. If the item is removed from the pool while the guard exists, the
97
/// removal will be deferred until all guards are dropped.
98
pub struct Ref<'a, T, C = DefaultConfig>
99
where
100
    T: Clear + Default,
101
    C: cfg::Config,
102
{
103
    inner: page::slot::Guard<T, C>,
104
    shard: &'a Shard<T, C>,
105
    key: usize,
106
}
107
108
/// A guard that allows exclusive mutable access to an object in a pool.
109
///
110
/// While the guard exists, it indicates to the pool that the item the guard
111
/// references is currently being accessed. If the item is removed from the pool
112
/// while a guard exists, the removal will be deferred until the guard is
113
/// dropped. The slot cannot be accessed by other threads while it is accessed
114
/// mutably.
115
pub struct RefMut<'a, T, C = DefaultConfig>
116
where
117
    T: Clear + Default,
118
    C: cfg::Config,
119
{
120
    inner: page::slot::InitGuard<T, C>,
121
    shard: &'a Shard<T, C>,
122
    key: usize,
123
}
124
125
/// An owned guard that allows shared immutable access to an object in a pool.
126
///
127
/// While the guard exists, it indicates to the pool that the item the guard references is
128
/// currently being accessed. If the item is removed from the pool while the guard exists, the
129
/// removal will be deferred until all guards are dropped.
130
///
131
/// Unlike [`Ref`], which borrows the pool, an `OwnedRef` clones the `Arc`
132
/// around the pool. Therefore, it keeps the pool from being dropped until all
133
/// such guards have been dropped. This means that an `OwnedRef` may be held for
134
/// an arbitrary lifetime.
135
///
136
///
137
/// # Examples
138
///
139
/// ```
140
/// # use sharded_slab::Pool;
141
/// use std::sync::Arc;
142
///
143
/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
144
/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
145
///
146
/// // Look up the created `Key`, returning an `OwnedRef`.
147
/// let value = pool.clone().get_owned(key).unwrap();
148
///
149
/// // Now, the original `Arc` clone of the pool may be dropped, but the
150
/// // returned `OwnedRef` can still access the value.
151
/// assert_eq!(value, String::from("hello world"));
152
/// ```
153
///
154
/// Unlike [`Ref`], an `OwnedRef` may be stored in a struct which must live
155
/// for the `'static` lifetime:
156
///
157
/// ```
158
/// # use sharded_slab::Pool;
159
/// use sharded_slab::pool::OwnedRef;
160
/// use std::sync::Arc;
161
///
162
/// pub struct MyStruct {
163
///     pool_ref: OwnedRef<String>,
164
///     // ... other fields ...
165
/// }
166
///
167
/// // Suppose this is some arbitrary function which requires a value that
168
/// // lives for the 'static lifetime...
169
/// fn function_requiring_static<T: 'static>(t: &T) {
170
///     // ... do something extremely important and interesting ...
171
/// }
172
///
173
/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
174
/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
175
///
176
/// // Look up the created `Key`, returning an `OwnedRef`.
177
/// let pool_ref = pool.clone().get_owned(key).unwrap();
178
/// let my_struct = MyStruct {
179
///     pool_ref,
180
///     // ...
181
/// };
182
///
183
/// // We can use `my_struct` anywhere where it is required to have the
184
/// // `'static` lifetime:
185
/// function_requiring_static(&my_struct);
186
/// ```
187
///
188
/// `OwnedRef`s may be sent between threads:
189
///
190
/// ```
191
/// # use sharded_slab::Pool;
192
/// use std::{thread, sync::Arc};
193
///
194
/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
195
/// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
196
///
197
/// // Look up the created `Key`, returning an `OwnedRef`.
198
/// let value = pool.clone().get_owned(key).unwrap();
199
///
200
/// thread::spawn(move || {
201
///     assert_eq!(value, String::from("hello world"));
202
///     // ...
203
/// }).join().unwrap();
204
/// ```
205
///
206
/// [`Ref`]: crate::pool::Ref
207
pub struct OwnedRef<T, C = DefaultConfig>
208
where
209
    T: Clear + Default,
210
    C: cfg::Config,
211
{
212
    inner: page::slot::Guard<T, C>,
213
    pool: Arc<Pool<T, C>>,
214
    key: usize,
215
}
216
217
/// An owned guard that allows exclusive, mutable access to an object in a pool.
218
///
219
/// An `OwnedRefMut<T>` functions more or less identically to an owned
220
/// `Box<T>`: it can be passed to functions, stored in structure fields, and
221
/// borrowed mutably or immutably, and can be owned for arbitrary lifetimes.
222
/// The difference is that, unlike a `Box<T>`, the memory allocation for the
223
/// `T` lives in the `Pool`; when an `OwnedRefMut` is created, it may reuse
224
/// memory that was allocated for a previous pooled object that has been
225
/// cleared. Additionally, the `OwnedRefMut` may be [downgraded] to an
226
/// [`OwnedRef`] which may be shared freely, essentially turning the `Box`
227
/// into an `Arc`.
228
///
229
/// This is returned by [`Pool::create_owned`].
230
///
231
/// While the guard exists, it indicates to the pool that the item the guard
232
/// references is currently being accessed. If the item is removed from the pool
233
/// while the guard exists, theremoval will be deferred until all guards are
234
/// dropped.
235
///
236
/// Unlike [`RefMut`], which borrows the pool, an `OwnedRefMut` clones the `Arc`
237
/// around the pool. Therefore, it keeps the pool from being dropped until all
238
/// such guards have been dropped. This means that an `OwnedRefMut` may be held for
239
/// an arbitrary lifetime.
240
///
241
/// # Examples
242
///
243
/// ```rust
244
/// # use sharded_slab::Pool;
245
/// # use std::thread;
246
/// use std::sync::Arc;
247
///
248
/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
249
///
250
/// // Create a new pooled item, returning an owned guard that allows mutable
251
/// // access to the new item.
252
/// let mut item = pool.clone().create_owned().unwrap();
253
/// // Return a key that allows indexing the created item once the guard
254
/// // has been dropped.
255
/// let key = item.key();
256
///
257
/// // Mutate the item.
258
/// item.push_str("Hello");
259
/// // Drop the guard, releasing mutable access to the new item.
260
/// drop(item);
261
///
262
/// /// Other threads may now (immutably) access the item using the returned key.
263
/// thread::spawn(move || {
264
///    assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
265
/// }).join().unwrap();
266
/// ```
267
///
268
/// ```rust
269
/// # use sharded_slab::Pool;
270
/// use std::sync::Arc;
271
///
272
/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
273
///
274
/// // Create a new item, returning an owned, mutable guard.
275
/// let mut value = pool.clone().create_owned().unwrap();
276
///
277
/// // Now, the original `Arc` clone of the pool may be dropped, but the
278
/// // returned `OwnedRefMut` can still access the value.
279
/// drop(pool);
280
///
281
/// value.push_str("hello world");
282
/// assert_eq!(value, String::from("hello world"));
283
/// ```
284
///
285
/// Unlike [`RefMut`], an `OwnedRefMut` may be stored in a struct which must live
286
/// for the `'static` lifetime:
287
///
288
/// ```
289
/// # use sharded_slab::Pool;
290
/// use sharded_slab::pool::OwnedRefMut;
291
/// use std::sync::Arc;
292
///
293
/// pub struct MyStruct {
294
///     pool_ref: OwnedRefMut<String>,
295
///     // ... other fields ...
296
/// }
297
///
298
/// // Suppose this is some arbitrary function which requires a value that
299
/// // lives for the 'static lifetime...
300
/// fn function_requiring_static<T: 'static>(t: &T) {
301
///     // ... do something extremely important and interesting ...
302
/// }
303
///
304
/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
305
///
306
/// // Create a new item, returning a mutable owned reference.
307
/// let pool_ref = pool.clone().create_owned().unwrap();
308
///
309
/// let my_struct = MyStruct {
310
///     pool_ref,
311
///     // ...
312
/// };
313
///
314
/// // We can use `my_struct` anywhere where it is required to have the
315
/// // `'static` lifetime:
316
/// function_requiring_static(&my_struct);
317
/// ```
318
///
319
/// `OwnedRefMut`s may be sent between threads:
320
///
321
/// ```
322
/// # use sharded_slab::Pool;
323
/// use std::{thread, sync::Arc};
324
///
325
/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
326
///
327
/// let mut value = pool.clone().create_owned().unwrap();
328
/// let key = value.key();
329
///
330
/// thread::spawn(move || {
331
///     value.push_str("hello world");
332
///     // ...
333
/// }).join().unwrap();
334
///
335
/// // Once the `OwnedRefMut` has been dropped by the other thread, we may
336
/// // now access the value immutably on this thread.
337
///
338
/// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
339
/// ```
340
///
341
/// Downgrading from a mutable to an immutable reference:
342
///
343
/// ```
344
/// # use sharded_slab::Pool;
345
/// use std::{thread, sync::Arc};
346
///
347
/// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
348
///
349
/// let mut value = pool.clone().create_owned().unwrap();
350
/// let key = value.key();
351
/// value.push_str("hello world");
352
///
353
/// // Downgrade the mutable owned ref to an immutable owned ref.
354
/// let value = value.downgrade();
355
///
356
/// // Once the `OwnedRefMut` has been downgraded, other threads may
357
/// // immutably access the pooled value:
358
/// thread::spawn(move || {
359
///     assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
360
/// }).join().unwrap();
361
///
362
/// // This thread can still access the pooled value through the
363
/// // immutable owned ref:
364
/// assert_eq!(value, String::from("hello world"));
365
/// ```
366
///
367
/// [`Pool::create_owned`]: crate::Pool::create_owned
368
/// [`RefMut`]: crate::pool::RefMut
369
/// [`OwnedRefMut`]: crate::pool::OwnedRefMut
370
/// [downgraded]: crate::pool::OwnedRefMut::downgrade
371
pub struct OwnedRefMut<T, C = DefaultConfig>
372
where
373
    T: Clear + Default,
374
    C: cfg::Config,
375
{
376
    inner: page::slot::InitGuard<T, C>,
377
    pool: Arc<Pool<T, C>>,
378
    key: usize,
379
}
380
381
impl<T> Pool<T>
382
where
383
    T: Clear + Default,
384
{
385
    /// Returns a new `Pool` with the default configuration parameters.
386
0
    pub fn new() -> Self {
387
0
        Self::new_with_config()
388
0
    }
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::new
Unexecuted instantiation: <sharded_slab::pool::Pool<_>>::new
389
390
    /// Returns a new `Pool` with the provided configuration parameters.
391
0
    pub fn new_with_config<C: cfg::Config>() -> Pool<T, C> {
392
0
        C::validate();
393
0
        Pool {
394
0
            shards: shard::Array::new(),
395
0
            _cfg: PhantomData,
396
0
        }
397
0
    }
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::new_with_config::<sharded_slab::cfg::DefaultConfig>
Unexecuted instantiation: <sharded_slab::pool::Pool<_>>::new_with_config::<_>
398
}
399
400
impl<T, C> Pool<T, C>
401
where
402
    T: Clear + Default,
403
    C: cfg::Config,
404
{
405
    /// The number of bits in each index which are used by the pool.
406
    ///
407
    /// If other data is packed into the `usize` indices returned by
408
    /// [`Pool::create`], user code is free to use any bits higher than the
409
    /// `USED_BITS`-th bit freely.
410
    ///
411
    /// This is determined by the [`Config`] type that configures the pool's
412
    /// parameters. By default, all bits are used; this can be changed by
413
    /// overriding the [`Config::RESERVED_BITS`][res] constant.
414
    ///
415
    /// [`Config`]: trait.Config.html
416
    /// [res]: trait.Config.html#associatedconstant.RESERVED_BITS
417
    /// [`Slab::insert`]: struct.Slab.html#method.insert
418
    pub const USED_BITS: usize = C::USED_BITS;
419
420
    /// Creates a new object in the pool, returning an [`RefMut`] guard that
421
    /// may be used to mutate the new object.
422
    ///
423
    /// If this function returns `None`, then the shard for the current thread is full and no items
424
    /// can be added until some are removed, or the maximum number of shards has been reached.
425
    ///
426
    /// # Examples
427
    /// ```rust
428
    /// # use sharded_slab::Pool;
429
    /// # use std::thread;
430
    /// let pool: Pool<String> = Pool::new();
431
    ///
432
    /// // Create a new pooled item, returning a guard that allows mutable
433
    /// // access to the new item.
434
    /// let mut item = pool.create().unwrap();
435
    /// // Return a key that allows indexing the created item once the guard
436
    /// // has been dropped.
437
    /// let key = item.key();
438
    ///
439
    /// // Mutate the item.
440
    /// item.push_str("Hello");
441
    /// // Drop the guard, releasing mutable access to the new item.
442
    /// drop(item);
443
    ///
444
    /// /// Other threads may now (immutably) access the item using the returned key.
445
    /// thread::spawn(move || {
446
    ///    assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
447
    /// }).join().unwrap();
448
    /// ```
449
    ///
450
    /// [`RefMut`]: crate::pool::RefMut
451
0
    pub fn create(&self) -> Option<RefMut<'_, T, C>> {
452
0
        let (tid, shard) = self.shards.current();
453
0
        test_println!("pool: create {:?}", tid);
454
0
        let (key, inner) = shard.init_with(|idx, slot| {
455
0
            let guard = slot.init()?;
456
0
            let gen = guard.generation();
457
0
            Some((gen.pack(idx), guard))
458
0
        })?;
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::create::{closure#0}
Unexecuted instantiation: <sharded_slab::pool::Pool<_, _>>::create::{closure#0}
459
0
        Some(RefMut {
460
0
            inner,
461
0
            key: tid.pack(key),
462
0
            shard,
463
0
        })
464
0
    }
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::create
Unexecuted instantiation: <sharded_slab::pool::Pool<_, _>>::create
465
466
    /// Creates a new object in the pool, returning an [`OwnedRefMut`] guard that
467
    /// may be used to mutate the new object.
468
    ///
469
    /// If this function returns `None`, then the shard for the current thread
470
    /// is full and no items can be added until some are removed, or the maximum
471
    /// number of shards has been reached.
472
    ///
473
    /// Unlike [`create`], which borrows the pool, this method _clones_ the `Arc`
474
    /// around the pool if a value exists for the given key. This means that the
475
    /// returned [`OwnedRefMut`] can be held for an arbitrary lifetime. However,
476
    /// this method requires that the pool itself be wrapped in an `Arc`.
477
    ///
478
    /// An `OwnedRefMut<T>` functions more or less identically to an owned
479
    /// `Box<T>`: it can be passed to functions, stored in structure fields, and
480
    /// borrowed mutably or immutably, and can be owned for arbitrary lifetimes.
481
    /// The difference is that, unlike a `Box<T>`, the memory allocation for the
482
    /// `T` lives in the `Pool`; when an `OwnedRefMut` is created, it may reuse
483
    /// memory that was allocated for a previous pooled object that has been
484
    /// cleared. Additionally, the `OwnedRefMut` may be [downgraded] to an
485
    /// [`OwnedRef`] which may be shared freely, essentially turning the `Box`
486
    /// into an `Arc`.
487
    ///
488
    /// # Examples
489
    ///
490
    /// ```rust
491
    /// # use sharded_slab::Pool;
492
    /// # use std::thread;
493
    /// use std::sync::Arc;
494
    ///
495
    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
496
    ///
497
    /// // Create a new pooled item, returning an owned guard that allows mutable
498
    /// // access to the new item.
499
    /// let mut item = pool.clone().create_owned().unwrap();
500
    /// // Return a key that allows indexing the created item once the guard
501
    /// // has been dropped.
502
    /// let key = item.key();
503
    ///
504
    /// // Mutate the item.
505
    /// item.push_str("Hello");
506
    /// // Drop the guard, releasing mutable access to the new item.
507
    /// drop(item);
508
    ///
509
    /// /// Other threads may now (immutably) access the item using the returned key.
510
    /// thread::spawn(move || {
511
    ///    assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
512
    /// }).join().unwrap();
513
    /// ```
514
    ///
515
    /// ```rust
516
    /// # use sharded_slab::Pool;
517
    /// use std::sync::Arc;
518
    ///
519
    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
520
    ///
521
    /// // Create a new item, returning an owned, mutable guard.
522
    /// let mut value = pool.clone().create_owned().unwrap();
523
    ///
524
    /// // Now, the original `Arc` clone of the pool may be dropped, but the
525
    /// // returned `OwnedRefMut` can still access the value.
526
    /// drop(pool);
527
    ///
528
    /// value.push_str("hello world");
529
    /// assert_eq!(value, String::from("hello world"));
530
    /// ```
531
    ///
532
    /// Unlike [`RefMut`], an `OwnedRefMut` may be stored in a struct which must live
533
    /// for the `'static` lifetime:
534
    ///
535
    /// ```
536
    /// # use sharded_slab::Pool;
537
    /// use sharded_slab::pool::OwnedRefMut;
538
    /// use std::sync::Arc;
539
    ///
540
    /// pub struct MyStruct {
541
    ///     pool_ref: OwnedRefMut<String>,
542
    ///     // ... other fields ...
543
    /// }
544
    ///
545
    /// // Suppose this is some arbitrary function which requires a value that
546
    /// // lives for the 'static lifetime...
547
    /// fn function_requiring_static<T: 'static>(t: &T) {
548
    ///     // ... do something extremely important and interesting ...
549
    /// }
550
    ///
551
    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
552
    ///
553
    /// // Create a new item, returning a mutable owned reference.
554
    /// let pool_ref = pool.clone().create_owned().unwrap();
555
    ///
556
    /// let my_struct = MyStruct {
557
    ///     pool_ref,
558
    ///     // ...
559
    /// };
560
    ///
561
    /// // We can use `my_struct` anywhere where it is required to have the
562
    /// // `'static` lifetime:
563
    /// function_requiring_static(&my_struct);
564
    /// ```
565
    ///
566
    /// `OwnedRefMut`s may be sent between threads:
567
    ///
568
    /// ```
569
    /// # use sharded_slab::Pool;
570
    /// use std::{thread, sync::Arc};
571
    ///
572
    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
573
    ///
574
    /// let mut value = pool.clone().create_owned().unwrap();
575
    /// let key = value.key();
576
    ///
577
    /// thread::spawn(move || {
578
    ///     value.push_str("hello world");
579
    ///     // ...
580
    /// }).join().unwrap();
581
    ///
582
    /// // Once the `OwnedRefMut` has been dropped by the other thread, we may
583
    /// // now access the value immutably on this thread.
584
    ///
585
    /// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
586
    /// ```
587
    ///
588
    /// Downgrading from a mutable to an immutable reference:
589
    ///
590
    /// ```
591
    /// # use sharded_slab::Pool;
592
    /// use std::{thread, sync::Arc};
593
    ///
594
    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
595
    ///
596
    /// let mut value = pool.clone().create_owned().unwrap();
597
    /// let key = value.key();
598
    /// value.push_str("hello world");
599
    ///
600
    /// // Downgrade the mutable owned ref to an immutable owned ref.
601
    /// let value = value.downgrade();
602
    ///
603
    /// // Once the `OwnedRefMut` has been downgraded, other threads may
604
    /// // immutably access the pooled value:
605
    /// thread::spawn(move || {
606
    ///     assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
607
    /// }).join().unwrap();
608
    ///
609
    /// // This thread can still access the pooled value through the
610
    /// // immutable owned ref:
611
    /// assert_eq!(value, String::from("hello world"));
612
    /// ```
613
    ///
614
    /// [`create`]: Pool::create
615
    /// [`OwnedRef`]: crate::pool::OwnedRef
616
    /// [`RefMut`]: crate::pool::RefMut
617
    /// [`OwnedRefMut`]: crate::pool::OwnedRefMut
618
    /// [downgraded]: crate::pool::OwnedRefMut::downgrade
619
0
    pub fn create_owned(self: Arc<Self>) -> Option<OwnedRefMut<T, C>> {
620
0
        let (tid, shard) = self.shards.current();
621
0
        test_println!("pool: create_owned {:?}", tid);
622
0
        let (inner, key) = shard.init_with(|idx, slot| {
623
0
            let inner = slot.init()?;
624
0
            let gen = inner.generation();
625
0
            Some((inner, tid.pack(gen.pack(idx))))
626
0
        })?;
627
0
        Some(OwnedRefMut {
628
0
            inner,
629
0
            pool: self,
630
0
            key,
631
0
        })
632
0
    }
633
634
    /// Creates a new object in the pool with the provided initializer,
635
    /// returning a key that may be used to access the new object.
636
    ///
637
    /// If this function returns `None`, then the shard for the current thread is full and no items
638
    /// can be added until some are removed, or the maximum number of shards has been reached.
639
    ///
640
    /// # Examples
641
    /// ```rust
642
    /// # use sharded_slab::Pool;
643
    /// # use std::thread;
644
    /// let pool: Pool<String> = Pool::new();
645
    ///
646
    /// // Create a new pooled item, returning its integer key.
647
    /// let key = pool.create_with(|s| s.push_str("Hello")).unwrap();
648
    ///
649
    /// /// Other threads may now (immutably) access the item using the key.
650
    /// thread::spawn(move || {
651
    ///    assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
652
    /// }).join().unwrap();
653
    /// ```
654
0
    pub fn create_with(&self, init: impl FnOnce(&mut T)) -> Option<usize> {
655
0
        test_println!("pool: create_with");
656
0
        let mut guard = self.create()?;
657
0
        init(&mut guard);
658
0
        Some(guard.key())
659
0
    }
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::create_with::<<tracing_subscriber::registry::sharded::Registry as tracing_core::subscriber::Subscriber>::new_span::{closure#2}>
Unexecuted instantiation: <sharded_slab::pool::Pool<_, _>>::create_with::<_>
660
661
    /// Return a borrowed reference to the value associated with the given key.
662
    ///
663
    /// If the pool does not contain a value for the given key, `None` is returned instead.
664
    ///
665
    /// # Examples
666
    ///
667
    /// ```rust
668
    /// # use sharded_slab::Pool;
669
    /// let pool: Pool<String> = Pool::new();
670
    /// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
671
    ///
672
    /// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
673
    /// assert!(pool.get(12345).is_none());
674
    /// ```
675
0
    pub fn get(&self, key: usize) -> Option<Ref<'_, T, C>> {
676
0
        let tid = C::unpack_tid(key);
677
0
678
0
        test_println!("pool: get{:?}; current={:?}", tid, Tid::<C>::current());
679
0
        let shard = self.shards.get(tid.as_usize())?;
680
0
        let inner = shard.with_slot(key, |slot| slot.get(C::unpack_gen(key)))?;
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::get::{closure#0}
Unexecuted instantiation: <sharded_slab::pool::Pool<_, _>>::get::{closure#0}
681
0
        Some(Ref { inner, shard, key })
682
0
    }
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::get
Unexecuted instantiation: <sharded_slab::pool::Pool<_, _>>::get
683
684
    /// Return an owned reference to the value associated with the given key.
685
    ///
686
    /// If the pool does not contain a value for the given key, `None` is
687
    /// returned instead.
688
    ///
689
    /// Unlike [`get`], which borrows the pool, this method _clones_ the `Arc`
690
    /// around the pool if a value exists for the given key. This means that the
691
    /// returned [`OwnedRef`] can be held for an arbitrary lifetime. However,
692
    /// this method requires that the pool itself be wrapped in an `Arc`.
693
    ///
694
    /// # Examples
695
    ///
696
    /// ```rust
697
    /// # use sharded_slab::Pool;
698
    /// use std::sync::Arc;
699
    ///
700
    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
701
    /// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
702
    ///
703
    /// // Look up the created `Key`, returning an `OwnedRef`.
704
    /// let value = pool.clone().get_owned(key).unwrap();
705
    ///
706
    /// // Now, the original `Arc` clone of the pool may be dropped, but the
707
    /// // returned `OwnedRef` can still access the value.
708
    /// assert_eq!(value, String::from("hello world"));
709
    /// ```
710
    ///
711
    /// Unlike [`Ref`], an `OwnedRef` may be stored in a struct which must live
712
    /// for the `'static` lifetime:
713
    ///
714
    /// ```
715
    /// # use sharded_slab::Pool;
716
    /// use sharded_slab::pool::OwnedRef;
717
    /// use std::sync::Arc;
718
    ///
719
    /// pub struct MyStruct {
720
    ///     pool_ref: OwnedRef<String>,
721
    ///     // ... other fields ...
722
    /// }
723
    ///
724
    /// // Suppose this is some arbitrary function which requires a value that
725
    /// // lives for the 'static lifetime...
726
    /// fn function_requiring_static<T: 'static>(t: &T) {
727
    ///     // ... do something extremely important and interesting ...
728
    /// }
729
    ///
730
    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
731
    /// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
732
    ///
733
    /// // Look up the created `Key`, returning an `OwnedRef`.
734
    /// let pool_ref = pool.clone().get_owned(key).unwrap();
735
    /// let my_struct = MyStruct {
736
    ///     pool_ref,
737
    ///     // ...
738
    /// };
739
    ///
740
    /// // We can use `my_struct` anywhere where it is required to have the
741
    /// // `'static` lifetime:
742
    /// function_requiring_static(&my_struct);
743
    /// ```
744
    ///
745
    /// `OwnedRef`s may be sent between threads:
746
    ///
747
    /// ```
748
    /// # use sharded_slab::Pool;
749
    /// use std::{thread, sync::Arc};
750
    ///
751
    /// let pool: Arc<Pool<String>> = Arc::new(Pool::new());
752
    /// let key = pool.create_with(|item| item.push_str("hello world")).unwrap();
753
    ///
754
    /// // Look up the created `Key`, returning an `OwnedRef`.
755
    /// let value = pool.clone().get_owned(key).unwrap();
756
    ///
757
    /// thread::spawn(move || {
758
    ///     assert_eq!(value, String::from("hello world"));
759
    ///     // ...
760
    /// }).join().unwrap();
761
    /// ```
762
    ///
763
    /// [`get`]: Pool::get
764
    /// [`OwnedRef`]: crate::pool::OwnedRef
765
    /// [`Ref`]: crate::pool::Ref
766
0
    pub fn get_owned(self: Arc<Self>, key: usize) -> Option<OwnedRef<T, C>> {
767
0
        let tid = C::unpack_tid(key);
768
0
769
0
        test_println!("pool: get{:?}; current={:?}", tid, Tid::<C>::current());
770
0
        let shard = self.shards.get(tid.as_usize())?;
771
0
        let inner = shard.with_slot(key, |slot| slot.get(C::unpack_gen(key)))?;
772
0
        Some(OwnedRef {
773
0
            inner,
774
0
            pool: self.clone(),
775
0
            key,
776
0
        })
777
0
    }
778
779
    /// Remove the value using the storage associated with the given key from the pool, returning
780
    /// `true` if the value was removed.
781
    ///
782
    /// This method does _not_ block the current thread until the value can be
783
    /// cleared. Instead, if another thread is currently accessing that value, this marks it to be
784
    /// cleared by that thread when it is done accessing that value.
785
    ///
786
    /// # Examples
787
    ///
788
    /// ```rust
789
    /// # use sharded_slab::Pool;
790
    /// let pool: Pool<String> = Pool::new();
791
    ///
792
    /// // Check out an item from the pool.
793
    /// let mut item = pool.create().unwrap();
794
    /// let key = item.key();
795
    /// item.push_str("hello world");
796
    /// drop(item);
797
    ///
798
    /// assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
799
    ///
800
    /// pool.clear(key);
801
    /// assert!(pool.get(key).is_none());
802
    /// ```
803
    ///
804
    /// ```
805
    /// # use sharded_slab::Pool;
806
    /// let pool: Pool<String> = Pool::new();
807
    ///
808
    /// let key = pool.create_with(|item| item.push_str("Hello world!")).unwrap();
809
    ///
810
    /// // Clearing a key that doesn't exist in the `Pool` will return `false`
811
    /// assert_eq!(pool.clear(key + 69420), false);
812
    ///
813
    /// // Clearing a key that does exist returns `true`
814
    /// assert!(pool.clear(key));
815
    ///
816
    /// // Clearing a key that has previously been cleared will return `false`
817
    /// assert_eq!(pool.clear(key), false);
818
    /// ```
819
    /// [`clear`]: #method.clear
820
0
    pub fn clear(&self, key: usize) -> bool {
821
0
        let tid = C::unpack_tid(key);
822
0
823
0
        let shard = self.shards.get(tid.as_usize());
824
0
        if tid.is_current() {
825
0
            shard
826
0
                .map(|shard| shard.mark_clear_local(key))
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::clear::{closure#0}
Unexecuted instantiation: <sharded_slab::pool::Pool<_, _>>::clear::{closure#0}
827
0
                .unwrap_or(false)
828
        } else {
829
0
            shard
830
0
                .map(|shard| shard.mark_clear_remote(key))
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::clear::{closure#1}
Unexecuted instantiation: <sharded_slab::pool::Pool<_, _>>::clear::{closure#1}
831
0
                .unwrap_or(false)
832
        }
833
0
    }
Unexecuted instantiation: <sharded_slab::pool::Pool<tracing_subscriber::registry::sharded::DataInner>>::clear
Unexecuted instantiation: <sharded_slab::pool::Pool<_, _>>::clear
834
}
835
836
unsafe impl<T, C> Send for Pool<T, C>
837
where
838
    T: Send + Clear + Default,
839
    C: cfg::Config,
840
{
841
}
842
unsafe impl<T, C> Sync for Pool<T, C>
843
where
844
    T: Sync + Clear + Default,
845
    C: cfg::Config,
846
{
847
}
848
849
impl<T> Default for Pool<T>
850
where
851
    T: Clear + Default,
852
{
853
0
    fn default() -> Self {
854
0
        Self::new()
855
0
    }
856
}
857
858
impl<T, C> fmt::Debug for Pool<T, C>
859
where
860
    T: fmt::Debug + Clear + Default,
861
    C: cfg::Config,
862
{
863
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
864
0
        f.debug_struct("Pool")
865
0
            .field("shards", &self.shards)
866
0
            .field("config", &C::debug())
867
0
            .finish()
868
0
    }
869
}
870
871
// === impl Ref ===
872
873
impl<'a, T, C> Ref<'a, T, C>
874
where
875
    T: Clear + Default,
876
    C: cfg::Config,
877
{
878
    /// Returns the key used to access this guard
879
0
    pub fn key(&self) -> usize {
880
0
        self.key
881
0
    }
Unexecuted instantiation: <sharded_slab::pool::Ref<tracing_subscriber::registry::sharded::DataInner>>::key
Unexecuted instantiation: <sharded_slab::pool::Ref<_, _>>::key
882
883
    #[inline]
884
0
    fn value(&self) -> &T {
885
0
        unsafe {
886
0
            // Safety: calling `slot::Guard::value` is unsafe, since the `Guard`
887
0
            // value contains a pointer to the slot that may outlive the slab
888
0
            // containing that slot. Here, the `Ref` has a borrowed reference to
889
0
            // the shard containing that slot, which ensures that the slot will
890
0
            // not be dropped while this `Guard` exists.
891
0
            self.inner.value()
892
0
        }
893
0
    }
Unexecuted instantiation: <sharded_slab::pool::Ref<tracing_subscriber::registry::sharded::DataInner>>::value
Unexecuted instantiation: <sharded_slab::pool::Ref<_, _>>::value
894
}
895
896
impl<'a, T, C> std::ops::Deref for Ref<'a, T, C>
897
where
898
    T: Clear + Default,
899
    C: cfg::Config,
900
{
901
    type Target = T;
902
903
0
    fn deref(&self) -> &Self::Target {
904
0
        self.value()
905
0
    }
Unexecuted instantiation: <sharded_slab::pool::Ref<tracing_subscriber::registry::sharded::DataInner> as core::ops::deref::Deref>::deref
Unexecuted instantiation: <sharded_slab::pool::Ref<_, _> as core::ops::deref::Deref>::deref
906
}
907
908
impl<'a, T, C> Drop for Ref<'a, T, C>
909
where
910
    T: Clear + Default,
911
    C: cfg::Config,
912
{
913
0
    fn drop(&mut self) {
914
0
        test_println!("drop Ref: try clearing data");
915
0
        let should_clear = unsafe {
916
0
            // Safety: calling `slot::Guard::release` is unsafe, since the
917
0
            // `Guard` value contains a pointer to the slot that may outlive the
918
0
            // slab containing that slot. Here, the `Ref` guard owns a
919
0
            // borrowed reference to the shard containing that slot, which
920
0
            // ensures that the slot will not be dropped while this `Ref`
921
0
            // exists.
922
0
            self.inner.release()
923
0
        };
924
0
        if should_clear {
925
0
            self.shard.clear_after_release(self.key);
926
0
        }
927
0
    }
Unexecuted instantiation: <sharded_slab::pool::Ref<tracing_subscriber::registry::sharded::DataInner> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <sharded_slab::pool::Ref<_, _> as core::ops::drop::Drop>::drop
928
}
929
930
impl<'a, T, C> fmt::Debug for Ref<'a, T, C>
931
where
932
    T: fmt::Debug + Clear + Default,
933
    C: cfg::Config,
934
{
935
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
936
0
        fmt::Debug::fmt(self.value(), f)
937
0
    }
938
}
939
940
impl<'a, T, C> PartialEq<T> for Ref<'a, T, C>
941
where
942
    T: PartialEq<T> + Clear + Default,
943
    C: cfg::Config,
944
{
945
0
    fn eq(&self, other: &T) -> bool {
946
0
        *self.value() == *other
947
0
    }
948
}
949
950
// === impl GuardMut ===
951
952
impl<'a, T, C: cfg::Config> RefMut<'a, T, C>
953
where
954
    T: Clear + Default,
955
    C: cfg::Config,
956
{
957
    /// Returns the key used to access the guard.
958
0
    pub fn key(&self) -> usize {
959
0
        self.key
960
0
    }
Unexecuted instantiation: <sharded_slab::pool::RefMut<tracing_subscriber::registry::sharded::DataInner>>::key
Unexecuted instantiation: <sharded_slab::pool::RefMut<_, _>>::key
961
962
    /// Downgrades the mutable guard to an immutable guard, allowing access to
963
    /// the pooled value from other threads.
964
    ///
965
    /// ## Examples
966
    ///
967
    /// ```
968
    /// # use sharded_slab::Pool;
969
    /// # use std::{sync::Arc, thread};
970
    /// let pool = Arc::new(Pool::<String>::new());
971
    ///
972
    /// let mut guard_mut = pool.clone().create_owned().unwrap();
973
    /// let key = guard_mut.key();
974
    /// guard_mut.push_str("Hello");
975
    ///
976
    /// // The pooled string is currently borrowed mutably, so other threads
977
    /// // may not access it.
978
    /// let pool2 = pool.clone();
979
    /// thread::spawn(move || {
980
    ///     assert!(pool2.get(key).is_none())
981
    /// }).join().unwrap();
982
    ///
983
    /// // Downgrade the guard to an immutable reference.
984
    /// let guard = guard_mut.downgrade();
985
    ///
986
    /// // Now, other threads may also access the pooled value.
987
    /// let pool2 = pool.clone();
988
    /// thread::spawn(move || {
989
    ///     let guard = pool2.get(key)
990
    ///         .expect("the item may now be referenced by other threads");
991
    ///     assert_eq!(guard, String::from("Hello"));
992
    /// }).join().unwrap();
993
    ///
994
    /// // We can still access the value immutably through the downgraded guard.
995
    /// assert_eq!(guard, String::from("Hello"));
996
    /// ```
997
0
    pub fn downgrade(mut self) -> Ref<'a, T, C> {
998
0
        let inner = unsafe { self.inner.downgrade() };
999
0
        Ref {
1000
0
            inner,
1001
0
            shard: self.shard,
1002
0
            key: self.key,
1003
0
        }
1004
0
    }
1005
1006
    #[inline]
1007
0
    fn value(&self) -> &T {
1008
0
        unsafe {
1009
0
            // Safety: we are holding a reference to the shard which keeps the
1010
0
            // pointed slot alive. The returned reference will not outlive
1011
0
            // `self`.
1012
0
            self.inner.value()
1013
0
        }
1014
0
    }
1015
}
1016
1017
impl<'a, T, C: cfg::Config> std::ops::Deref for RefMut<'a, T, C>
1018
where
1019
    T: Clear + Default,
1020
    C: cfg::Config,
1021
{
1022
    type Target = T;
1023
1024
0
    fn deref(&self) -> &Self::Target {
1025
0
        self.value()
1026
0
    }
1027
}
1028
1029
impl<'a, T, C> std::ops::DerefMut for RefMut<'a, T, C>
1030
where
1031
    T: Clear + Default,
1032
    C: cfg::Config,
1033
{
1034
0
    fn deref_mut(&mut self) -> &mut Self::Target {
1035
0
        unsafe {
1036
0
            // Safety: we are holding a reference to the shard which keeps the
1037
0
            // pointed slot alive. The returned reference will not outlive `self`.
1038
0
            self.inner.value_mut()
1039
0
        }
1040
0
    }
Unexecuted instantiation: <sharded_slab::pool::RefMut<tracing_subscriber::registry::sharded::DataInner> as core::ops::deref::DerefMut>::deref_mut
Unexecuted instantiation: <sharded_slab::pool::RefMut<_, _> as core::ops::deref::DerefMut>::deref_mut
1041
}
1042
1043
impl<'a, T, C> Drop for RefMut<'a, T, C>
1044
where
1045
    T: Clear + Default,
1046
    C: cfg::Config,
1047
{
1048
0
    fn drop(&mut self) {
1049
0
        test_println!(" -> drop RefMut: try clearing data");
1050
0
        let should_clear = unsafe {
1051
0
            // Safety: we are holding a reference to the shard which keeps the
1052
0
            // pointed slot alive. The returned reference will not outlive `self`.
1053
0
            self.inner.release()
1054
0
        };
1055
0
        if should_clear {
1056
0
            self.shard.clear_after_release(self.key);
1057
0
        }
1058
0
    }
Unexecuted instantiation: <sharded_slab::pool::RefMut<tracing_subscriber::registry::sharded::DataInner> as core::ops::drop::Drop>::drop
Unexecuted instantiation: <sharded_slab::pool::RefMut<_, _> as core::ops::drop::Drop>::drop
1059
}
1060
1061
impl<'a, T, C> fmt::Debug for RefMut<'a, T, C>
1062
where
1063
    T: fmt::Debug + Clear + Default,
1064
    C: cfg::Config,
1065
{
1066
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1067
0
        fmt::Debug::fmt(self.value(), f)
1068
0
    }
1069
}
1070
1071
impl<'a, T, C> PartialEq<T> for RefMut<'a, T, C>
1072
where
1073
    T: PartialEq<T> + Clear + Default,
1074
    C: cfg::Config,
1075
{
1076
0
    fn eq(&self, other: &T) -> bool {
1077
0
        self.value().eq(other)
1078
0
    }
1079
}
1080
1081
// === impl OwnedRef ===
1082
1083
impl<T, C> OwnedRef<T, C>
1084
where
1085
    T: Clear + Default,
1086
    C: cfg::Config,
1087
{
1088
    /// Returns the key used to access this guard
1089
0
    pub fn key(&self) -> usize {
1090
0
        self.key
1091
0
    }
1092
1093
    #[inline]
1094
0
    fn value(&self) -> &T {
1095
0
        unsafe {
1096
0
            // Safety: calling `slot::Guard::value` is unsafe, since the `Guard`
1097
0
            // value contains a pointer to the slot that may outlive the slab
1098
0
            // containing that slot. Here, the `Ref` has a borrowed reference to
1099
0
            // the shard containing that slot, which ensures that the slot will
1100
0
            // not be dropped while this `Guard` exists.
1101
0
            self.inner.value()
1102
0
        }
1103
0
    }
1104
}
1105
1106
impl<T, C> std::ops::Deref for OwnedRef<T, C>
1107
where
1108
    T: Clear + Default,
1109
    C: cfg::Config,
1110
{
1111
    type Target = T;
1112
1113
0
    fn deref(&self) -> &Self::Target {
1114
0
        self.value()
1115
0
    }
1116
}
1117
1118
impl<T, C> Drop for OwnedRef<T, C>
1119
where
1120
    T: Clear + Default,
1121
    C: cfg::Config,
1122
{
1123
0
    fn drop(&mut self) {
1124
0
        test_println!("drop OwnedRef: try clearing data");
1125
0
        let should_clear = unsafe {
1126
0
            // Safety: calling `slot::Guard::release` is unsafe, since the
1127
0
            // `Guard` value contains a pointer to the slot that may outlive the
1128
0
            // slab containing that slot. Here, the `OwnedRef` owns an `Arc`
1129
0
            // clone of the pool, which keeps it alive as long as the `OwnedRef`
1130
0
            // exists.
1131
0
            self.inner.release()
1132
0
        };
1133
0
        if should_clear {
1134
0
            let shard_idx = Tid::<C>::from_packed(self.key);
1135
0
            test_println!("-> shard={:?}", shard_idx);
1136
0
            if let Some(shard) = self.pool.shards.get(shard_idx.as_usize()) {
1137
0
                shard.clear_after_release(self.key);
1138
0
            } else {
1139
0
                test_println!("-> shard={:?} does not exist! THIS IS A BUG", shard_idx);
1140
0
                debug_assert!(std::thread::panicking(), "[internal error] tried to drop an `OwnedRef` to a slot on a shard that never existed!");
1141
            }
1142
0
        }
1143
0
    }
1144
}
1145
1146
impl<T, C> fmt::Debug for OwnedRef<T, C>
1147
where
1148
    T: fmt::Debug + Clear + Default,
1149
    C: cfg::Config,
1150
{
1151
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1152
0
        fmt::Debug::fmt(self.value(), f)
1153
0
    }
1154
}
1155
1156
impl<T, C> PartialEq<T> for OwnedRef<T, C>
1157
where
1158
    T: PartialEq<T> + Clear + Default,
1159
    C: cfg::Config,
1160
{
1161
0
    fn eq(&self, other: &T) -> bool {
1162
0
        *self.value() == *other
1163
0
    }
1164
}
1165
1166
unsafe impl<T, C> Sync for OwnedRef<T, C>
1167
where
1168
    T: Sync + Clear + Default,
1169
    C: cfg::Config,
1170
{
1171
}
1172
1173
unsafe impl<T, C> Send for OwnedRef<T, C>
1174
where
1175
    T: Sync + Clear + Default,
1176
    C: cfg::Config,
1177
{
1178
}
1179
1180
// === impl OwnedRefMut ===
1181
1182
impl<T, C> OwnedRefMut<T, C>
1183
where
1184
    T: Clear + Default,
1185
    C: cfg::Config,
1186
{
1187
    /// Returns the key used to access this guard
1188
0
    pub fn key(&self) -> usize {
1189
0
        self.key
1190
0
    }
1191
1192
    /// Downgrades the owned mutable guard to an owned immutable guard, allowing
1193
    /// access to the pooled value from other threads.
1194
    ///
1195
    /// ## Examples
1196
    ///
1197
    /// ```
1198
    /// # use sharded_slab::Pool;
1199
    /// # use std::{sync::Arc, thread};
1200
    /// let pool = Arc::new(Pool::<String>::new());
1201
    ///
1202
    /// let mut guard_mut = pool.clone().create_owned().unwrap();
1203
    /// let key = guard_mut.key();
1204
    /// guard_mut.push_str("Hello");
1205
    ///
1206
    /// // The pooled string is currently borrowed mutably, so other threads
1207
    /// // may not access it.
1208
    /// let pool2 = pool.clone();
1209
    /// thread::spawn(move || {
1210
    ///     assert!(pool2.get(key).is_none())
1211
    /// }).join().unwrap();
1212
    ///
1213
    /// // Downgrade the guard to an immutable reference.
1214
    /// let guard = guard_mut.downgrade();
1215
    ///
1216
    /// // Now, other threads may also access the pooled value.
1217
    /// let pool2 = pool.clone();
1218
    /// thread::spawn(move || {
1219
    ///     let guard = pool2.get(key)
1220
    ///         .expect("the item may now be referenced by other threads");
1221
    ///     assert_eq!(guard, String::from("Hello"));
1222
    /// }).join().unwrap();
1223
    ///
1224
    /// // We can still access the value immutably through the downgraded guard.
1225
    /// assert_eq!(guard, String::from("Hello"));
1226
    /// ```
1227
0
    pub fn downgrade(mut self) -> OwnedRef<T, C> {
1228
0
        let inner = unsafe { self.inner.downgrade() };
1229
0
        OwnedRef {
1230
0
            inner,
1231
0
            pool: self.pool.clone(),
1232
0
            key: self.key,
1233
0
        }
1234
0
    }
1235
1236
0
    fn shard(&self) -> Option<&Shard<T, C>> {
1237
0
        let shard_idx = Tid::<C>::from_packed(self.key);
1238
0
        test_println!("-> shard={:?}", shard_idx);
1239
0
        self.pool.shards.get(shard_idx.as_usize())
1240
0
    }
1241
1242
    #[inline]
1243
0
    fn value(&self) -> &T {
1244
0
        unsafe {
1245
0
            // Safety: calling `slot::InitGuard::value` is unsafe, since the `Guard`
1246
0
            // value contains a pointer to the slot that may outlive the slab
1247
0
            // containing that slot. Here, the `OwnedRefMut` has an `Arc` clone of
1248
0
            // the shard containing that slot, which ensures that the slot will
1249
0
            // not be dropped while this `Guard` exists.
1250
0
            self.inner.value()
1251
0
        }
1252
0
    }
1253
}
1254
1255
impl<T, C> std::ops::Deref for OwnedRefMut<T, C>
1256
where
1257
    T: Clear + Default,
1258
    C: cfg::Config,
1259
{
1260
    type Target = T;
1261
1262
0
    fn deref(&self) -> &Self::Target {
1263
0
        self.value()
1264
0
    }
1265
}
1266
1267
impl<T, C> std::ops::DerefMut for OwnedRefMut<T, C>
1268
where
1269
    T: Clear + Default,
1270
    C: cfg::Config,
1271
{
1272
0
    fn deref_mut(&mut self) -> &mut Self::Target {
1273
0
        unsafe {
1274
0
            // Safety: calling `slot::InitGuard::value_mut` is unsafe, since the
1275
0
            // `Guard`  value contains a pointer to the slot that may outlive
1276
0
            // the slab   containing that slot. Here, the `OwnedRefMut` has an
1277
0
            // `Arc` clone of the shard containing that slot, which ensures that
1278
0
            // the slot will not be dropped while this `Guard` exists.
1279
0
            self.inner.value_mut()
1280
0
        }
1281
0
    }
1282
}
1283
1284
impl<T, C> Drop for OwnedRefMut<T, C>
1285
where
1286
    T: Clear + Default,
1287
    C: cfg::Config,
1288
{
1289
0
    fn drop(&mut self) {
1290
0
        test_println!("drop OwnedRefMut: try clearing data");
1291
0
        let should_clear = unsafe {
1292
0
            // Safety: calling `slot::Guard::release` is unsafe, since the
1293
0
            // `Guard` value contains a pointer to the slot that may outlive the
1294
0
            // slab containing that slot. Here, the `OwnedRefMut` owns an `Arc`
1295
0
            // clone of the pool, which keeps it alive as long as the
1296
0
            // `OwnedRefMut` exists.
1297
0
            self.inner.release()
1298
0
        };
1299
0
        if should_clear {
1300
0
            if let Some(shard) = self.shard() {
1301
0
                shard.clear_after_release(self.key);
1302
0
            } else {
1303
0
                test_println!("-> shard does not exist! THIS IS A BUG");
1304
0
                debug_assert!(std::thread::panicking(), "[internal error] tried to drop an `OwnedRefMut` to a slot on a shard that never existed!");
1305
            }
1306
0
        }
1307
0
    }
1308
}
1309
1310
impl<T, C> fmt::Debug for OwnedRefMut<T, C>
1311
where
1312
    T: fmt::Debug + Clear + Default,
1313
    C: cfg::Config,
1314
{
1315
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1316
0
        fmt::Debug::fmt(self.value(), f)
1317
0
    }
1318
}
1319
1320
impl<T, C> PartialEq<T> for OwnedRefMut<T, C>
1321
where
1322
    T: PartialEq<T> + Clear + Default,
1323
    C: cfg::Config,
1324
{
1325
0
    fn eq(&self, other: &T) -> bool {
1326
0
        *self.value() == *other
1327
0
    }
1328
}
1329
1330
unsafe impl<T, C> Sync for OwnedRefMut<T, C>
1331
where
1332
    T: Sync + Clear + Default,
1333
    C: cfg::Config,
1334
{
1335
}
1336
1337
unsafe impl<T, C> Send for OwnedRefMut<T, C>
1338
where
1339
    T: Sync + Clear + Default,
1340
    C: cfg::Config,
1341
{
1342
}