counting_pointer/
asc.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;
57use core::hash::{Hash, Hasher};
58use core::mem::{self, align_of, size_of, MaybeUninit};
59use core::ops::Deref;
60use core::result::Result;
61use core::sync::atomic::{AtomicUsize, Ordering};
62use std::alloc::{handle_alloc_error, System};
63use std::borrow::Borrow;
64use std::fmt;
65
66/// Bucket of `Asc` to allocate/deallocate memory for reference count and value at once.
67#[repr(C)]
68struct Bucket<T: ?Sized> {
69    count: AtomicUsize,
70    size: usize,
71    val: T,
72}
73
74impl<T> From<T> for Bucket<T> {
75    fn from(val: T) -> Self {
76        debug_assert_eq!(align_of::<usize>(), align_of::<Self>());
77
78        Self {
79            count: AtomicUsize::new(1),
80            size: size_of::<Self>(),
81            val,
82        }
83    }
84}
85
86impl<T: ?Sized> Bucket<T> {
87    unsafe fn count(val: &mut T) -> &AtomicUsize {
88        let ptr: *mut T = val;
89        let ptr: *mut usize = ptr.cast();
90        let ptr = ptr.sub(1);
91        let ptr: *const AtomicUsize = ptr.cast();
92        let ptr = ptr.sub(1);
93        &*ptr
94    }
95
96    unsafe fn size(ptr: *const T) -> usize {
97        let ptr: *const usize = ptr.cast();
98        let ptr = ptr.sub(1);
99        *ptr
100    }
101
102    unsafe fn dealloc_ptr(ptr: *mut T) -> *mut u8 {
103        let ptr: *mut usize = ptr.cast();
104        let ptr = ptr.sub(1);
105        let ptr: *const AtomicUsize = ptr.cast();
106        let ptr = ptr.sub(1);
107        ptr as *mut u8
108    }
109}
110
111/// A thread-safe strong reference-counting pointer. 'Asc' stands for 'Atomic Strong Counted.'
112///
113/// It behaves like `std::Sync::Arc` except for that this treats only strong pointer; i.e. `Asc`
114/// gives up weak pointer for the performance.
115///
116/// The inherent methods of `Asc` are all associated funcitons, which means that you have to call
117/// them as e.g., `Asc::get_mut(&mut value)` instead of `value.get_mut()` . This avoids conflicts
118/// with methods of the inner type `T` .
119///
120/// # Thread Safety
121///
122/// Unlike to [`Sc`] , `Asc` uses atomic operations for its reference counting. This means that it
123/// is thread-safe. The disadvangate is that atomic operations are more expensive than ordinary
124/// memory access.
125///
126/// [`Sc`]: struct.Sc.html
127pub struct Asc<T: ?Sized, A = System>
128where
129    A: GlobalAlloc,
130{
131    ptr: *mut T,
132    alloc: A,
133}
134
135unsafe impl<T: ?Sized, A> Sync for Asc<T, A>
136where
137    T: Send + Sync,
138    A: Sync + GlobalAlloc,
139{
140}
141
142unsafe impl<T: ?Sized, A> Send for Asc<T, A>
143where
144    T: Send + Sync,
145    A: Send + GlobalAlloc,
146{
147}
148
149impl<T: ?Sized, A> Drop for Asc<T, A>
150where
151    A: GlobalAlloc,
152{
153    fn drop(&mut self) {
154        unsafe {
155            let count = Bucket::count(&mut *self.ptr).fetch_sub(1, Ordering::Release);
156
157            if count == 1 {
158                let layout =
159                    Layout::from_size_align(Bucket::size(self.ptr), align_of::<usize>()).unwrap();
160                let ptr = Bucket::dealloc_ptr(self.ptr);
161
162                self.ptr.drop_in_place();
163                self.alloc.dealloc(ptr, layout);
164            }
165        }
166    }
167}
168
169impl<T, A> Default for Asc<T, A>
170where
171    T: Default,
172    A: Default + GlobalAlloc,
173{
174    fn default() -> Self {
175        Self::new(T::default(), A::default())
176    }
177}
178
179impl<T, A> From<T> for Asc<T, A>
180where
181    A: Default + GlobalAlloc,
182{
183    fn from(val: T) -> Self {
184        Self::new(val, A::default())
185    }
186}
187
188impl<T, A> From<&'_ [T]> for Asc<[T], A>
189where
190    T: Clone,
191    A: Default + GlobalAlloc,
192{
193    fn from(vals: &'_ [T]) -> Self {
194        Asc::<T, A>::from_slice_alloc(vals, A::default())
195    }
196}
197
198impl<T: ?Sized, A> Clone for Asc<T, A>
199where
200    A: Clone + GlobalAlloc,
201{
202    fn clone(&self) -> Self {
203        // increment the count.
204        unsafe {
205            let val = &mut *self.ptr;
206            Bucket::count(val).fetch_add(1, Ordering::Acquire);
207        };
208
209        Self {
210            ptr: self.ptr,
211            alloc: self.alloc.clone(),
212        }
213    }
214}
215
216impl<T, A> Asc<T, A>
217where
218    A: GlobalAlloc,
219{
220    /// Creates a new instance.
221    ///
222    /// # Examples
223    ///
224    /// ```
225    /// use std::alloc::System;
226    /// use counting_pointer::Asc;
227    ///
228    /// let _five = Asc::new(5, System);
229    /// ```
230    pub fn new(val: T, alloc: A) -> Self {
231        let bucket = unsafe {
232            let layout = Layout::new::<Bucket<T>>();
233            let ptr = alloc.alloc(layout) as *mut Bucket<T>;
234            if ptr.is_null() {
235                handle_alloc_error(layout);
236            }
237
238            ptr.write(Bucket::from(val));
239            &mut *ptr
240        };
241        Self {
242            ptr: &mut bucket.val,
243            alloc,
244        }
245    }
246
247    /// Creates a new instance of `Asc<[T], A>` .
248    ///
249    /// # Examples
250    ///
251    /// ```
252    /// use std::alloc::System;
253    /// use counting_pointer::Asc;
254    ///
255    /// let vals: [i32; 4] = [0, 1, 2, 3];
256    /// let sc = Asc::from_slice_alloc(&vals, System);
257    /// assert_eq!(&vals, &*sc);
258    /// ```
259    pub fn from_slice_alloc(vals: &[T], alloc: A) -> Asc<[T], A>
260    where
261        T: Clone,
262    {
263        unsafe {
264            let layout = {
265                let align = align_of::<Bucket<T>>();
266                let size = size_of::<Bucket<T>>() - size_of::<Bucket<T>>()
267                    + vals.len() * size_of::<Bucket<T>>();
268                Layout::from_size_align_unchecked(size, align)
269            };
270
271            let ptr = alloc.alloc(layout) as *mut Bucket<T>;
272            if ptr.is_null() {
273                handle_alloc_error(layout);
274            }
275
276            let mut bucket = &mut *ptr;
277            bucket.count = AtomicUsize::new(1);
278            bucket.size = layout.size();
279
280            let ptr = &mut bucket.val as *mut T;
281            for i in 0..vals.len() {
282                let v = vals[i].clone();
283                let ptr = ptr.add(i);
284                ptr.write(v);
285            }
286
287            let slice_ref = core::slice::from_raw_parts_mut(ptr, vals.len());
288            Asc::<[T], A> {
289                ptr: &mut *slice_ref,
290                alloc,
291            }
292        }
293    }
294}
295
296impl<A> Asc<dyn Any, A>
297where
298    A: GlobalAlloc,
299{
300    /// Creates `Asc<dyn Any>` instance.
301    ///
302    /// # Examples
303    ///
304    /// ```
305    /// use std::alloc::System;
306    /// use counting_pointer::Asc;
307    ///
308    /// let _five = Asc::new_any(5, System);
309    /// ```
310    pub fn new_any<T>(val: T, alloc: A) -> Self
311    where
312        T: Any,
313    {
314        let bucket = unsafe {
315            let layout = Layout::new::<Bucket<T>>();
316            let ptr = alloc.alloc(layout) as *mut Bucket<T>;
317            if ptr.is_null() {
318                handle_alloc_error(layout);
319            }
320
321            ptr.write(Bucket::from(val));
322            &mut *ptr
323        };
324        Self {
325            ptr: &mut bucket.val,
326            alloc,
327        }
328    }
329}
330
331impl<T: ?Sized, A> fmt::Debug for Asc<T, A>
332where
333    A: fmt::Debug + GlobalAlloc,
334{
335    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
336        let ptr = format!("{:p}", self.ptr);
337        let alloc = format!("{:?}", self.alloc);
338
339        f.debug_struct("Asc")
340            .field("ptr", &ptr)
341            .field("alloc", &alloc)
342            .finish()
343    }
344}
345
346impl<T: ?Sized, A> PartialEq for Asc<T, A>
347where
348    T: PartialEq,
349    A: GlobalAlloc,
350{
351    fn eq(&self, other: &Self) -> bool {
352        let this: &T = self.borrow();
353        let other: &T = other.borrow();
354        this.eq(other)
355    }
356}
357
358impl<T: ?Sized, A> Eq for Asc<T, A>
359where
360    T: Eq,
361    A: GlobalAlloc,
362{
363}
364
365impl<T: ?Sized, A> PartialOrd for Asc<T, A>
366where
367    T: PartialOrd,
368    A: GlobalAlloc,
369{
370    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
371        let this: &T = self.borrow();
372        let other: &T = other.borrow();
373        this.partial_cmp(other)
374    }
375}
376
377impl<T: ?Sized, A> Ord for Asc<T, A>
378where
379    T: Ord,
380    A: GlobalAlloc,
381{
382    fn cmp(&self, other: &Self) -> cmp::Ordering {
383        let this: &T = self.borrow();
384        let other: &T = other.borrow();
385        this.cmp(other)
386    }
387}
388
389impl<T: ?Sized, A> Hash for Asc<T, A>
390where
391    T: Hash,
392    A: GlobalAlloc,
393{
394    fn hash<H>(&self, hasher: &mut H)
395    where
396        H: Hasher,
397    {
398        let inner: &T = self.borrow();
399        inner.hash(hasher);
400    }
401}
402
403impl<T: ?Sized, A> fmt::Display for Asc<T, A>
404where
405    T: fmt::Display,
406    A: GlobalAlloc,
407{
408    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409        let inner: &T = self.deref();
410        fmt::Display::fmt(inner, f)
411    }
412}
413
414impl<T: ?Sized, A> AsRef<T> for Asc<T, A>
415where
416    A: GlobalAlloc,
417{
418    fn as_ref(&self) -> &T {
419        self.deref()
420    }
421}
422
423impl<T: ?Sized, A> Borrow<T> for Asc<T, A>
424where
425    A: GlobalAlloc,
426{
427    fn borrow(&self) -> &T {
428        self.deref()
429    }
430}
431
432impl<T: ?Sized, A> Deref for Asc<T, A>
433where
434    A: GlobalAlloc,
435{
436    type Target = T;
437
438    fn deref(&self) -> &Self::Target {
439        unsafe { &*self.ptr }
440    }
441}
442
443impl<T, A> Asc<T, A>
444where
445    A: GlobalAlloc,
446{
447    /// Consumes `this`, returning `Asc<dyn Any, A>`
448    ///
449    /// # Examples
450    ///
451    /// ```
452    /// use counting_pointer::Asc;
453    ///
454    /// let sc: Asc<i32> = Asc::from(6);
455    /// let any = Asc::to_any(sc);
456    /// ```
457    pub fn to_any(this: Self) -> Asc<dyn Any, A>
458    where
459        T: Any,
460    {
461        let (ptr, alloc) = Self::decouple(this);
462        Asc::<dyn Any, A> { ptr, alloc }
463    }
464}
465
466impl<T: ?Sized, A> Asc<T, A>
467where
468    A: GlobalAlloc,
469{
470    /// Provides a raw pointer to the data.
471    ///
472    /// The counts are not affected in any way and the `Asc` is not consumed. The pointer is valid
473    /// for as long as another `Asc` instance is pointing to the address.
474    ///
475    /// # Examples
476    ///
477    /// ```
478    /// use counting_pointer::Asc;
479    ///
480    /// let x: Asc<String> = Asc::from(String::from("Hello"));
481    /// let x_ptr = Asc::as_ptr(&x);
482    /// assert_eq!("Hello", unsafe { &*x_ptr });
483    /// ```
484    pub fn as_ptr(this: &Self) -> *const T {
485        this.ptr
486    }
487
488    /// Returns the number of `Asc` pointers pointing to the same address.
489    ///
490    /// # Examples
491    ///
492    /// ```
493    /// use counting_pointer::Asc;
494    ///
495    /// let five: Asc<i32> = Asc::from(5);
496    /// assert_eq!(1, Asc::count(&five));
497    ///
498    /// let _also_five = five.clone();
499    /// assert_eq!(2, Asc::count(&five));
500    /// assert_eq!(2, Asc::count(&_also_five));
501    ///
502    /// drop(five);
503    /// assert_eq!(1, Asc::count(&_also_five));
504    /// ```
505    pub fn count(this: &Self) -> usize {
506        unsafe {
507            let val = &mut *this.ptr;
508            Bucket::count(val).load(Ordering::Relaxed)
509        }
510    }
511
512    /// Returns a mutable reference into the given `Asc` , if no other `Asc` instance is pointing to
513    /// the same address; otherwise returns `None` .
514    ///
515    /// See also [`make_mut`] , which will `clone` the inner value when some other `Asc` instances
516    /// are.
517    ///
518    /// [`make_mut`]: #method.make_mut
519    ///
520    /// # Examples
521    ///
522    /// ```
523    /// use counting_pointer::Asc;
524    ///
525    /// let mut x: Asc<i32> = Asc::from(3);
526    /// assert_eq!(3, *x);
527    ///
528    /// *Asc::get_mut(&mut x).unwrap() = 4;
529    /// assert_eq!(4, *x);
530    ///
531    /// let _y = x.clone();
532    /// let n = Asc::get_mut(&mut x);
533    /// assert!(n.is_none());
534    /// ```
535    pub fn get_mut(this: &mut Self) -> Option<&mut T> {
536        if Self::count(this) == 1 {
537            Some(unsafe { &mut *this.ptr })
538        } else {
539            None
540        }
541    }
542
543    /// Returns `true` if the two `Asc` instances point to the same address, or `false` .
544    ///
545    /// # Examples
546    ///
547    /// ```
548    /// use counting_pointer::Asc;
549    ///
550    /// let five: Asc<i32> = Asc::from(5);
551    /// let same_five = five.clone();
552    /// let other_five: Asc<i32> = Asc::from(5);
553    ///
554    /// assert_eq!(true, Asc::ptr_eq(&five, &same_five));
555    /// assert_eq!(false, Asc::ptr_eq(&five, &other_five));
556    /// ```
557    pub fn ptr_eq(this: &Self, other: &Self) -> bool {
558        Asc::as_ptr(this) == Asc::as_ptr(other)
559    }
560
561    /// Consumes `this` , returning the wrapped pointer and the allocator.
562    ///
563    /// To avoid memory leak, the returned pointer must be converted back to an `Asc` using
564    /// [`from_raw_alloc`] .
565    ///
566    /// Using this function and [`from_raw_alloc`] , user can create an `Asc<T: ?Sized>` instance.
567    ///
568    /// [`from_raw_alloc`]: #method.from_raw_alloc
569    ///
570    /// # Examples
571    ///
572    /// ```
573    /// use counting_pointer::Asc;
574    ///
575    /// let asc: Asc<String> = Asc::from("Foo".to_string());
576    /// let (ptr, alloc) = Asc::into_raw_alloc(asc);
577    /// let _asc: Asc<dyn AsRef<str>> = unsafe { Asc::from_raw_alloc(ptr, alloc) };
578    /// ```
579    pub fn into_raw_alloc(this: Self) -> (*const T, A) {
580        let (ptr, alloc) = Self::decouple(this);
581        (ptr, alloc)
582    }
583
584    /// Constructs a new instance from a raw pointer and allocator.
585    ///
586    /// The raw pointer must have been previously returned by a call to [`into_raw_alloc`] .
587    ///
588    /// Using this function and [`into_raw_alloc`] , user can create an `Asc<T: ?Sized>` instance.
589    ///
590    /// # Safety
591    ///
592    /// It may lead to memory unsafety to use improperly, even if the returned value will never be
593    /// accessed.
594    ///
595    /// [`into_raw_alloc`]: #method.into_raw_alloc
596    ///
597    /// # Examples
598    ///
599    /// ```
600    /// use counting_pointer::Asc;
601    ///
602    /// let asc: Asc<String> = Asc::from("Foo".to_string());
603    /// let (ptr, alloc) = Asc::into_raw_alloc(asc);
604    /// let _asc: Asc<dyn AsRef<str>> = unsafe { Asc::from_raw_alloc(ptr, alloc) };
605    /// ```
606    pub unsafe fn from_raw_alloc(ptr: *const T, alloc: A) -> Self {
607        Self {
608            ptr: ptr as *mut T,
609            alloc,
610        }
611    }
612
613    fn decouple(this: Self) -> (*mut T, A) {
614        let alloc = unsafe {
615            let mut alloc = MaybeUninit::<A>::uninit();
616            let ptr = alloc.as_mut_ptr();
617            ptr.copy_from_nonoverlapping(&this.alloc, 1);
618            alloc.assume_init()
619        };
620
621        let ret = (this.ptr, alloc);
622        mem::forget(this);
623        ret
624    }
625}
626
627impl<T: Clone, A: Clone> Asc<T, A>
628where
629    A: GlobalAlloc,
630{
631    /// Makes a mutable reference into the given `Asc` .
632    ///
633    /// If another `Asc` instance is pointing to the same address, `make_mut` will `clone` the inner
634    /// value to a new allocation to ensure unique ownership.
635    ///
636    /// See also [`get_mut`] , which will fail rather than cloning.
637    ///
638    /// [`get_mut`]: #method.get_mut
639    ///
640    /// # Examples
641    ///
642    /// ```
643    /// use counting_pointer::Asc;
644    ///
645    /// let mut data: Asc<i32> = Asc::from(5);
646    /// assert_eq!(5, *data);
647    ///
648    /// *Asc::make_mut(&mut data) += 1; // Won't clone anything.
649    /// assert_eq!(6, *data);
650    ///
651    /// let mut data2 = data.clone();  // Won't clone the inner data.
652    /// *Asc::make_mut(&mut data) += 1; // Clones inner data.
653    /// assert_eq!(7, *data);
654    /// assert_eq!(6, *data2);
655    /// ```
656    pub fn make_mut(this: &mut Self) -> &mut T {
657        if Self::count(this) != 1 {
658            let val: &T = this.deref();
659            *this = Asc::new(val.clone(), this.alloc.clone());
660        }
661
662        unsafe { &mut *this.ptr }
663    }
664}
665
666impl<A> Asc<dyn Any, A>
667where
668    A: GlobalAlloc,
669{
670    /// Attempts to downcast the `Asc<dyn Any, A>` to a concrete type.
671    ///
672    /// # Examples
673    ///
674    /// ```
675    /// use std::alloc::System;
676    /// use std::any::Any;
677    /// use counting_pointer::Asc;
678    ///
679    /// let sc = Asc::new_any(8 as i32, System);
680    ///
681    /// let success = Asc::downcast::<i32>(sc.clone()).unwrap();
682    /// assert_eq!(8, *success);
683    ///
684    /// let fail = Asc::downcast::<String>(sc.clone());
685    /// assert_eq!(true, fail.is_err());
686    /// ```
687    pub fn downcast<T: Any>(self) -> Result<Asc<T, A>, Self> {
688        let val: &mut dyn Any = unsafe { &mut *self.ptr };
689        match val.downcast_mut() {
690            None => Err(self),
691            Some(t) => {
692                let (_, alloc) = Self::decouple(self);
693                Ok(Asc::<T, A> {
694                    ptr: t as *mut T,
695                    alloc,
696                })
697            }
698        }
699    }
700}
701
702#[cfg(test)]
703mod tests {
704    use super::*;
705    use gharial::{GAlloc, GBox};
706
707    #[test]
708    fn new() {
709        let five = GBox::from(5);
710        let _five = Asc::new(five, GAlloc::default());
711    }
712
713    #[test]
714    fn clone() {
715        let five = GBox::from(5);
716
717        let five = Asc::new(five, GAlloc::default());
718        let _cloned = five.clone();
719    }
720
721    #[test]
722    fn make_mut() {
723        let inner = GBox::from(5);
724
725        let mut data = Asc::new(inner, GAlloc::default());
726        {
727            let _mr = Asc::make_mut(&mut data);
728        }
729
730        let _data2 = data.clone();
731        {
732            let _mr = Asc::make_mut(&mut data);
733        }
734    }
735
736    #[test]
737    fn downcast() {
738        let inner = GBox::from(8);
739
740        let sc = Asc::new_any(inner, GAlloc::default());
741
742        let ok = Asc::downcast::<GBox<i32>>(sc.clone());
743        assert_eq!(true, ok.is_ok());
744
745        let fail = Asc::downcast::<String>(sc.clone());
746        assert_eq!(true, fail.is_err());
747    }
748
749    #[test]
750    fn to_any() {
751        let inner = GBox::from(6);
752
753        let sc = Asc::new(inner, GAlloc::default());
754        let _any = Asc::to_any(sc);
755    }
756
757    #[test]
758    fn from_slice_alloc() {
759        let inners: [GBox<i32>; 2] = [GBox::from(6), GBox::from(4)];
760
761        let _sc = Asc::from_slice_alloc(&inners, GAlloc::default());
762    }
763
764    #[test]
765    fn raw_alloc() {
766        let asc: Asc<GBox<i32>> = Asc::from(GBox::from(0));
767        let (ptr, alloc) = Asc::into_raw_alloc(asc);
768        let _sc = unsafe { Asc::from_raw_alloc(ptr, alloc) };
769    }
770}