counting_pointer/sc.rs
1// Copyright 2020 Shin Yoshida
2//
3// "LGPL-3.0-or-later OR Apache-2.0 OR BSD-2-Clause"
4//
5// This is part of counting-pointer
6//
7// counting-pointer is free software: you can redistribute it and/or modify
8// it under the terms of the GNU Lesser General Public License as published by
9// the Free Software Foundation, either version 3 of the License, or
10// (at your option) any later version.
11//
12// counting-pointer is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU Lesser General Public License for more details.
16//
17// You should have received a copy of the GNU Lesser General Public License
18// along with counting-pointer. If not, see <http://www.gnu.org/licenses/>.
19//
20//
21// Licensed under the Apache License, Version 2.0 (the "License");
22// you may not use this file except in compliance with the License.
23// You may obtain a copy of the License at
24//
25// http://www.apache.org/licenses/LICENSE-2.0
26//
27// Unless required by applicable law or agreed to in writing, software
28// distributed under the License is distributed on an "AS IS" BASIS,
29// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
30// See the License for the specific language governing permissions and
31// limitations under the License.
32//
33//
34// Redistribution and use in source and binary forms, with or without modification, are permitted
35// provided that the following conditions are met:
36//
37// 1. Redistributions of source code must retain the above copyright notice, this list of
38// conditions and the following disclaimer.
39// 2. Redistributions in binary form must reproduce the above copyright notice, this
40// list of conditions and the following disclaimer in the documentation and/or other
41// materials provided with the distribution.
42//
43// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
44// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
45// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
46// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
47// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
48// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
49// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
50// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
52// POSSIBILITY OF SUCH DAMAGE.
53
54use core::alloc::{GlobalAlloc, Layout};
55use core::any::Any;
56use core::cmp::Ordering;
57use core::hash::{Hash, Hasher};
58use core::mem::{self, align_of, size_of, MaybeUninit};
59use core::ops::Deref;
60use core::result::Result;
61use std::alloc::{handle_alloc_error, System};
62use std::borrow::Borrow;
63use std::fmt;
64
65/// Bucket of `Sc` to allocate/deallocate memory for reference count and value at once.
66#[repr(C)]
67struct Bucket<T: ?Sized> {
68 count: usize,
69 size: usize,
70 val: T,
71}
72
73impl<T> From<T> for Bucket<T> {
74 fn from(val: T) -> Self {
75 debug_assert_eq!(align_of::<usize>(), align_of::<Self>());
76
77 Self {
78 count: 1,
79 size: size_of::<Self>(),
80 val,
81 }
82 }
83}
84
85impl<T: ?Sized> Bucket<T> {
86 unsafe fn count(val: &mut T) -> &mut usize {
87 let ptr: *mut T = val;
88 let ptr: *mut usize = ptr.cast();
89 let ptr = ptr.sub(2);
90 &mut *ptr
91 }
92
93 unsafe fn size(ptr: *const T) -> usize {
94 let ptr: *const usize = ptr.cast();
95 let ptr = ptr.sub(1);
96 *ptr
97 }
98
99 unsafe fn dealloc_ptr(ptr: *mut T) -> *mut u8 {
100 let ptr: *mut usize = ptr.cast();
101 let ptr = ptr.sub(2);
102 ptr as *mut u8
103 }
104}
105
106/// A single-threaded strong reference-counting pointer. 'Sc' stands for 'Strong Counted.'
107///
108/// It behaves like `std::rc::Rc` except for that this treats only strong pointer; i.e. `Sc` gives
109/// up weak pointer for the performance.
110///
111/// The inherent methods of `Sc` are all associated funcitons, which means that you have to call
112/// them as e.g., `Sc::get_mut(&mut value)` instead of `value.get_mut()` . This avoids conflicts
113/// with methods of the inner type `T` .
114pub struct Sc<T: ?Sized, A = System>
115where
116 A: GlobalAlloc,
117{
118 ptr: *mut T,
119 alloc: A,
120}
121
122impl<T: ?Sized, A> Drop for Sc<T, A>
123where
124 A: GlobalAlloc,
125{
126 fn drop(&mut self) {
127 unsafe {
128 let count = Bucket::count(&mut *self.ptr);
129 *count -= 1;
130
131 if *count == 0 {
132 let layout =
133 Layout::from_size_align(Bucket::size(self.ptr), align_of::<usize>()).unwrap();
134 let ptr = Bucket::dealloc_ptr(self.ptr);
135
136 self.ptr.drop_in_place();
137 self.alloc.dealloc(ptr, layout);
138 }
139 }
140 }
141}
142
143impl<T, A> Default for Sc<T, A>
144where
145 T: Default,
146 A: Default + GlobalAlloc,
147{
148 fn default() -> Self {
149 Self::new(T::default(), A::default())
150 }
151}
152
153impl<T, A> From<T> for Sc<T, A>
154where
155 A: Default + GlobalAlloc,
156{
157 fn from(val: T) -> Self {
158 Self::new(val, A::default())
159 }
160}
161
162impl<T, A> From<&'_ [T]> for Sc<[T], A>
163where
164 T: Clone,
165 A: Default + GlobalAlloc,
166{
167 fn from(vals: &'_ [T]) -> Self {
168 Sc::<T, A>::from_slice_alloc(vals, A::default())
169 }
170}
171
172impl<T: ?Sized, A> Clone for Sc<T, A>
173where
174 A: Clone + GlobalAlloc,
175{
176 fn clone(&self) -> Self {
177 // increment the count.
178 unsafe {
179 let val = &mut *self.ptr;
180 *Bucket::count(val) += 1;
181 };
182
183 Self {
184 ptr: self.ptr,
185 alloc: self.alloc.clone(),
186 }
187 }
188}
189
190impl<T, A> Sc<T, A>
191where
192 A: GlobalAlloc,
193{
194 /// Creates a new instance.
195 ///
196 /// # Examples
197 ///
198 /// ```
199 /// use std::alloc::System;
200 /// use counting_pointer::Sc;
201 ///
202 /// let _five = Sc::new(5, System);
203 /// ```
204 pub fn new(val: T, alloc: A) -> Self {
205 let bucket = unsafe {
206 let layout = Layout::new::<Bucket<T>>();
207 let ptr = alloc.alloc(layout) as *mut Bucket<T>;
208 if ptr.is_null() {
209 handle_alloc_error(layout);
210 }
211
212 ptr.write(Bucket::from(val));
213 &mut *ptr
214 };
215 Self {
216 ptr: &mut bucket.val,
217 alloc,
218 }
219 }
220
221 /// Creates a new instance of `Sc<[T], A>` .
222 ///
223 /// # Examples
224 ///
225 /// ```
226 /// use std::alloc::System;
227 /// use counting_pointer::Sc;
228 ///
229 /// let vals: [i32; 4] = [0, 1, 2, 3];
230 /// let sc = Sc::from_slice_alloc(&vals, System);
231 /// assert_eq!(&vals, &*sc);
232 /// ```
233 pub fn from_slice_alloc(vals: &[T], alloc: A) -> Sc<[T], A>
234 where
235 T: Clone,
236 {
237 unsafe {
238 let layout = {
239 let align = align_of::<Bucket<T>>();
240 let size = size_of::<Bucket<T>>() - size_of::<Bucket<T>>()
241 + vals.len() * size_of::<Bucket<T>>();
242 Layout::from_size_align_unchecked(size, align)
243 };
244
245 let ptr = alloc.alloc(layout) as *mut Bucket<T>;
246 if ptr.is_null() {
247 handle_alloc_error(layout);
248 }
249
250 let mut bucket = &mut *ptr;
251 bucket.count = 1;
252 bucket.size = layout.size();
253
254 let ptr = &mut bucket.val as *mut T;
255 for i in 0..vals.len() {
256 let v = vals[i].clone();
257 let ptr = ptr.add(i);
258 ptr.write(v);
259 }
260
261 let slice_ref = core::slice::from_raw_parts_mut(ptr, vals.len());
262 Sc::<[T], A> {
263 ptr: &mut *slice_ref,
264 alloc,
265 }
266 }
267 }
268}
269
270impl<A> Sc<dyn Any, A>
271where
272 A: GlobalAlloc,
273{
274 /// Creates `Sc<dyn Any>` instance.
275 ///
276 /// # Examples
277 ///
278 /// ```
279 /// use std::alloc::System;
280 /// use counting_pointer::Sc;
281 ///
282 /// let _five = Sc::new_any(5, System);
283 /// ```
284 pub fn new_any<T>(val: T, alloc: A) -> Self
285 where
286 T: Any,
287 {
288 let bucket = unsafe {
289 let layout = Layout::new::<Bucket<T>>();
290 let ptr = alloc.alloc(layout) as *mut Bucket<T>;
291 if ptr.is_null() {
292 handle_alloc_error(layout);
293 }
294
295 ptr.write(Bucket::from(val));
296 &mut *ptr
297 };
298 Self {
299 ptr: &mut bucket.val,
300 alloc,
301 }
302 }
303}
304
305impl<T: ?Sized, A> fmt::Debug for Sc<T, A>
306where
307 A: fmt::Debug + GlobalAlloc,
308{
309 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310 let ptr = format!("{:p}", self.ptr);
311 let alloc = format!("{:?}", self.alloc);
312
313 f.debug_struct("Sc")
314 .field("ptr", &ptr)
315 .field("alloc", &alloc)
316 .finish()
317 }
318}
319
320impl<T: ?Sized, A> PartialEq for Sc<T, A>
321where
322 T: PartialEq,
323 A: GlobalAlloc,
324{
325 fn eq(&self, other: &Self) -> bool {
326 let this: &T = self.borrow();
327 let other: &T = other.borrow();
328 this.eq(other)
329 }
330}
331
332impl<T: ?Sized, A> Eq for Sc<T, A>
333where
334 T: Eq,
335 A: GlobalAlloc,
336{
337}
338
339impl<T: ?Sized, A> PartialOrd for Sc<T, A>
340where
341 T: PartialOrd,
342 A: GlobalAlloc,
343{
344 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
345 let this: &T = self.borrow();
346 let other: &T = other.borrow();
347 this.partial_cmp(other)
348 }
349}
350
351impl<T: ?Sized, A> Ord for Sc<T, A>
352where
353 T: Ord,
354 A: GlobalAlloc,
355{
356 fn cmp(&self, other: &Self) -> Ordering {
357 let this: &T = self.borrow();
358 let other: &T = other.borrow();
359 this.cmp(other)
360 }
361}
362
363impl<T: ?Sized, A> Hash for Sc<T, A>
364where
365 T: Hash,
366 A: GlobalAlloc,
367{
368 fn hash<H>(&self, hasher: &mut H)
369 where
370 H: Hasher,
371 {
372 let inner: &T = self.borrow();
373 inner.hash(hasher);
374 }
375}
376
377impl<T: ?Sized, A> fmt::Display for Sc<T, A>
378where
379 T: fmt::Display,
380 A: GlobalAlloc,
381{
382 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383 let inner: &T = self.deref();
384 fmt::Display::fmt(inner, f)
385 }
386}
387
388impl<T: ?Sized, A> AsRef<T> for Sc<T, A>
389where
390 A: GlobalAlloc,
391{
392 fn as_ref(&self) -> &T {
393 self.deref()
394 }
395}
396
397impl<T: ?Sized, A> Borrow<T> for Sc<T, A>
398where
399 A: GlobalAlloc,
400{
401 fn borrow(&self) -> &T {
402 self.deref()
403 }
404}
405
406impl<T: ?Sized, A> Deref for Sc<T, A>
407where
408 A: GlobalAlloc,
409{
410 type Target = T;
411
412 fn deref(&self) -> &Self::Target {
413 unsafe { &*self.ptr }
414 }
415}
416
417impl<T, A> Sc<T, A>
418where
419 A: GlobalAlloc,
420{
421 /// Consumes `this`, returning `Sc<dyn Any, A>`
422 ///
423 /// # Examples
424 ///
425 /// ```
426 /// use counting_pointer::Sc;
427 ///
428 /// let sc: Sc<i32> = Sc::from(6);
429 /// let any = Sc::to_any(sc);
430 /// ```
431 pub fn to_any(this: Self) -> Sc<dyn Any, A>
432 where
433 T: Any,
434 {
435 let (ptr, alloc) = Self::decouple(this);
436 Sc::<dyn Any, A> { ptr, alloc }
437 }
438}
439
440impl<T: ?Sized, A> Sc<T, A>
441where
442 A: GlobalAlloc,
443{
444 /// Provides a raw pointer to the data.
445 ///
446 /// The counts are not affected in any way and the `Sc` is not consumed. The pointer is valid
447 /// for as long as another `Sc` instance is pointing to the address.
448 ///
449 /// # Examples
450 ///
451 /// ```
452 /// use counting_pointer::Sc;
453 ///
454 /// let x: Sc<String> = Sc::from(String::from("Hello"));
455 /// let x_ptr = Sc::as_ptr(&x);
456 /// assert_eq!("Hello", unsafe { &*x_ptr });
457 /// ```
458 pub fn as_ptr(this: &Self) -> *const T {
459 this.ptr
460 }
461
462 /// Returns the number of `Sc` pointers pointing to the same address.
463 ///
464 /// # Examples
465 ///
466 /// ```
467 /// use counting_pointer::Sc;
468 ///
469 /// let five: Sc<i32> = Sc::from(5);
470 /// assert_eq!(1, Sc::count(&five));
471 ///
472 /// let _also_five = five.clone();
473 /// assert_eq!(2, Sc::count(&five));
474 /// assert_eq!(2, Sc::count(&_also_five));
475 ///
476 /// drop(five);
477 /// assert_eq!(1, Sc::count(&_also_five));
478 /// ```
479 pub fn count(this: &Self) -> usize {
480 unsafe {
481 let val = &mut *this.ptr;
482 *Bucket::count(val)
483 }
484 }
485
486 /// Returns a mutable reference into the given `Sc` , if no other `Sc` instance is pointing to
487 /// the same address; otherwise returns `None` .
488 ///
489 /// See also [`make_mut`] , which will `clone` the inner value when some other `Sc` instances
490 /// are.
491 ///
492 /// [`make_mut`]: #method.make_mut
493 ///
494 /// # Examples
495 ///
496 /// ```
497 /// use counting_pointer::Sc;
498 ///
499 /// let mut x: Sc<i32> = Sc::from(3);
500 /// assert_eq!(3, *x);
501 ///
502 /// *Sc::get_mut(&mut x).unwrap() = 4;
503 /// assert_eq!(4, *x);
504 ///
505 /// let _y = x.clone();
506 /// let n = Sc::get_mut(&mut x);
507 /// assert!(n.is_none());
508 /// ```
509 pub fn get_mut(this: &mut Self) -> Option<&mut T> {
510 if Self::count(this) == 1 {
511 Some(unsafe { &mut *this.ptr })
512 } else {
513 None
514 }
515 }
516
517 /// Returns `true` if the two `Sc` instances point to the same address, or `false` .
518 ///
519 /// # Examples
520 ///
521 /// ```
522 /// use counting_pointer::Sc;
523 ///
524 /// let five: Sc<i32> = Sc::from(5);
525 /// let same_five = five.clone();
526 /// let other_five: Sc<i32> = Sc::from(5);
527 ///
528 /// assert_eq!(true, Sc::ptr_eq(&five, &same_five));
529 /// assert_eq!(false, Sc::ptr_eq(&five, &other_five));
530 /// ```
531 pub fn ptr_eq(this: &Self, other: &Self) -> bool {
532 Sc::as_ptr(this) == Sc::as_ptr(other)
533 }
534
535 /// Consumes `this` , returning the wrapped pointer and the allocator.
536 ///
537 /// To avoid memory leak, the returned pointer must be converted back to an `Sc` using
538 /// [`from_raw_alloc`] .
539 ///
540 /// Using this function and [`from_raw_alloc`] , user can create an `Sc<T: ?Sized>` instance.
541 ///
542 /// [`from_raw_alloc`]: #method.from_raw_alloc
543 ///
544 /// # Examples
545 ///
546 /// ```
547 /// use counting_pointer::Sc;
548 ///
549 /// let sc: Sc<String> = Sc::from("Foo".to_string());
550 /// let (ptr, alloc) = Sc::into_raw_alloc(sc);
551 /// let _sc: Sc<dyn AsRef<str>> = unsafe { Sc::from_raw_alloc(ptr, alloc) };
552 /// ```
553 pub fn into_raw_alloc(this: Self) -> (*const T, A) {
554 let (ptr, alloc) = Self::decouple(this);
555 (ptr, alloc)
556 }
557
558 /// Constructs a new instance from a raw pointer and allocator.
559 ///
560 /// The raw pointer must have been previously returned by a call to [`into_raw_alloc`] .
561 ///
562 /// Using this function and [`into_raw_alloc`] , user can create an `Sc<T: ?Sized>` instance.
563 ///
564 /// # Safety
565 ///
566 /// It may lead to memory unsafety to use improperly, even if the returned value will never be
567 /// accessed.
568 ///
569 /// [`into_raw_alloc`]: #method.into_raw_alloc
570 ///
571 /// # Examples
572 ///
573 /// ```
574 /// use counting_pointer::Sc;
575 ///
576 /// let sc: Sc<String> = Sc::from("Foo".to_string());
577 /// let (ptr, alloc) = Sc::into_raw_alloc(sc);
578 /// let _sc: Sc<dyn AsRef<str>> = unsafe { Sc::from_raw_alloc(ptr, alloc) };
579 /// ```
580 pub unsafe fn from_raw_alloc(ptr: *const T, alloc: A) -> Self {
581 Self {
582 ptr: ptr as *mut T,
583 alloc,
584 }
585 }
586
587 fn decouple(this: Self) -> (*mut T, A) {
588 let alloc = unsafe {
589 let mut alloc = MaybeUninit::<A>::uninit();
590 let ptr = alloc.as_mut_ptr();
591 ptr.copy_from_nonoverlapping(&this.alloc, 1);
592 alloc.assume_init()
593 };
594
595 let ret = (this.ptr, alloc);
596 mem::forget(this);
597 ret
598 }
599}
600
601impl<T: Clone, A: Clone> Sc<T, A>
602where
603 A: GlobalAlloc,
604{
605 /// Makes a mutable reference into the given `Sc` .
606 ///
607 /// If another `Sc` instance is pointing to the same address, `make_mut` will `clone` the inner
608 /// value to a new allocation to ensure unique ownership.
609 ///
610 /// See also [`get_mut`] , which will fail rather than cloning.
611 ///
612 /// [`get_mut`]: #method.get_mut
613 ///
614 /// # Examples
615 ///
616 /// ```
617 /// use counting_pointer::Sc;
618 ///
619 /// let mut data: Sc<i32> = Sc::from(5);
620 /// assert_eq!(5, *data);
621 ///
622 /// *Sc::make_mut(&mut data) += 1; // Won't clone anything.
623 /// assert_eq!(6, *data);
624 ///
625 /// let mut data2 = data.clone(); // Won't clone the inner data.
626 /// *Sc::make_mut(&mut data) += 1; // Clones inner data.
627 /// assert_eq!(7, *data);
628 /// assert_eq!(6, *data2);
629 /// ```
630 pub fn make_mut(this: &mut Self) -> &mut T {
631 if Self::count(this) != 1 {
632 let val: &T = this.deref();
633 *this = Sc::new(val.clone(), this.alloc.clone());
634 }
635
636 unsafe { &mut *this.ptr }
637 }
638}
639
640impl<A> Sc<dyn Any, A>
641where
642 A: GlobalAlloc,
643{
644 /// Attempts to downcast the `Sc<dyn Any, A>` to a concrete type.
645 ///
646 /// # Examples
647 ///
648 /// ```
649 /// use std::alloc::System;
650 /// use std::any::Any;
651 /// use counting_pointer::Sc;
652 ///
653 /// let sc = Sc::new_any(8 as i32, System);
654 ///
655 /// let success = Sc::downcast::<i32>(sc.clone()).unwrap();
656 /// assert_eq!(8, *success);
657 ///
658 /// let fail = Sc::downcast::<String>(sc.clone());
659 /// assert_eq!(true, fail.is_err());
660 /// ```
661 pub fn downcast<T: Any>(self) -> Result<Sc<T, A>, Self> {
662 let val: &mut dyn Any = unsafe { &mut *self.ptr };
663 match val.downcast_mut() {
664 None => Err(self),
665 Some(t) => {
666 let (_, alloc) = Self::decouple(self);
667 Ok(Sc::<T, A> {
668 ptr: t as *mut T,
669 alloc,
670 })
671 }
672 }
673 }
674}
675
676#[cfg(test)]
677mod tests {
678 use super::*;
679 use gharial::{GAlloc, GBox};
680
681 #[test]
682 fn new() {
683 let five = GBox::from(5);
684 let _five = Sc::new(five, GAlloc::default());
685 }
686
687 #[test]
688 fn clone() {
689 let five = GBox::from(5);
690
691 let five = Sc::new(five, GAlloc::default());
692 let _cloned = five.clone();
693 }
694
695 #[test]
696 fn make_mut() {
697 let inner = GBox::from(5);
698
699 let mut data = Sc::new(inner, GAlloc::default());
700 {
701 let _mr = Sc::make_mut(&mut data);
702 }
703
704 let _data2 = data.clone();
705 {
706 let _mr = Sc::make_mut(&mut data);
707 }
708 }
709
710 #[test]
711 fn downcast() {
712 let inner = GBox::from(8);
713
714 let sc = Sc::new_any(inner, GAlloc::default());
715
716 let ok = Sc::downcast::<GBox<i32>>(sc.clone());
717 assert_eq!(true, ok.is_ok());
718
719 let fail = Sc::downcast::<String>(sc.clone());
720 assert_eq!(true, fail.is_err());
721 }
722
723 #[test]
724 fn to_any() {
725 let inner = GBox::from(6);
726
727 let sc = Sc::new(inner, GAlloc::default());
728 let _any = Sc::to_any(sc);
729 }
730
731 #[test]
732 fn from_slice_alloc() {
733 let inners: [GBox<i32>; 2] = [GBox::from(6), GBox::from(4)];
734
735 let _sc = Sc::from_slice_alloc(&inners, GAlloc::default());
736 }
737
738 #[test]
739 fn raw_alloc() {
740 let sc: Sc<GBox<i32>> = Sc::from(GBox::from(0));
741 let (ptr, alloc) = Sc::into_raw_alloc(sc);
742 let _sc = unsafe { Sc::from_raw_alloc(ptr, alloc) };
743 }
744}