1
- use crate :: erts:: { AllocInProcess , Term } ;
1
+ use core:: alloc:: { AllocErr , Layout } ;
2
+ use core:: mem;
3
+ use core:: ptr:: NonNull ;
4
+
5
+ use crate :: erts:: { self , HeapAlloc , HeapFragment , ProcessControlBlock , Term } ;
2
6
3
7
/// This trait represents cloning, like `Clone`, but specifically
4
8
/// in the context of terms which need to be cloned into the heap
@@ -15,7 +19,44 @@ use crate::erts::{AllocInProcess, Term};
15
19
/// just be aware that any uses of `Clone` will allocate on the global heap
16
20
pub trait CloneToProcess {
17
21
/// Returns boxed copy of this value, performing any heap allocations
18
- /// using the process heap of `process`, or using heap fragments if
22
+ /// using the process heap of `process`, possibly using heap fragments if
19
23
/// there is not enough space for the cloned value
20
- fn clone_to_process < A : AllocInProcess > ( & self , process : & mut A ) -> Term ;
24
+ fn clone_to_process ( & self , process : & ProcessControlBlock ) -> Term {
25
+ let mut heap = process. acquire_heap ( ) ;
26
+ match self . clone_to_heap ( & mut heap) {
27
+ Ok ( term) => term,
28
+ Err ( _) => {
29
+ drop ( heap) ;
30
+ let ( term, mut frag) = self . clone_to_fragment ( ) . unwrap ( ) ;
31
+ process. attach_fragment ( unsafe { frag. as_mut ( ) } ) ;
32
+ term
33
+ }
34
+ }
35
+ }
36
+
37
+ /// Returns boxed copy of this value, performing any heap allocations
38
+ /// using the given heap. If cloning requires allocation that exceeds
39
+ /// the amount of memory available, this returns `Err(AllocErr)`, otherwise
40
+ /// it returns `Ok(Term)`
41
+ fn clone_to_heap < A : HeapAlloc > ( & self , heap : & mut A ) -> Result < Term , AllocErr > ;
42
+
43
+ /// Returns boxed copy of this value and the heap fragment it was allocated into
44
+ ///
45
+ /// If unable to allocate a heap fragment that fits this value, `Err(AllocErr)` is returned
46
+ fn clone_to_fragment ( & self ) -> Result < ( Term , NonNull < HeapFragment > ) , AllocErr > {
47
+ let need = self . size_in_words ( ) ;
48
+ let layout = unsafe {
49
+ let size = need * mem:: size_of :: < usize > ( ) ;
50
+ Layout :: from_size_align_unchecked ( size, mem:: align_of :: < Term > ( ) )
51
+ } ;
52
+ let mut frag = unsafe { HeapFragment :: new ( layout) ? } ;
53
+ let frag_ref = unsafe { frag. as_mut ( ) } ;
54
+ let term = self . clone_to_heap ( frag_ref) ?;
55
+ Ok ( ( term, frag) )
56
+ }
57
+
58
+ /// Returns the size in words needed to allocate this value
59
+ fn size_in_words ( & self ) -> usize {
60
+ erts:: to_word_size ( mem:: size_of_val ( self ) )
61
+ }
21
62
}
0 commit comments