-
Notifications
You must be signed in to change notification settings - Fork 53
Add Arena::clone_from & Entry::clone_from #46
base: master
Are you sure you want to change the base?
Conversation
Note: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for opening this PR.
@Yamakaky is on to something: there is the property that self.items.len() == self.items.capacity()
so that all capacity is available for insertion and is represented in the free list if it isn't occupied. So if self.items
has more capacity than other.items
does, then it should fill the free list with the additional capacity.
Can you also debug_assert!
this property at the end of clone_from
?
Thanks!
self.items.reserve_exact(additional_capacity); | ||
let start = self.items.len(); | ||
let end = self.items.len() + additional_capacity; | ||
let old_head = self.free_list_head; | ||
self.items.reserve_exact(additional_capacity); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a functional change or did it just slip into the commit?
Since |
Actually, this PR has 2 commits, and the first one did exactly what you said (that is why there is a "leftover line" in the overall view). However I reverted the part where I filled the existing capacity with If we start with the
The capacity can still be greater than what we actually expect (although it's a "better try" than the For the determinism part, with the first commit only (so what you described), the behavior of this struct may change depending on whether or not the destination Arena (the one we re-use the allocation from) had bigger capacity than the source or not. If it's bigger, then the free_head is overwritten, and suddenly we have 2 This is fine until we start using the This can be a very nasty problem to debug since you expect 2 cloned structs to behave the same same ways, and for no gain in performance either: we if go over capacity and the Vec behind it already has a capacity of |
An aspect of the
Clone
trait which is not much known isclone_from
, which is there to allow a struct to re-use pre-allocated memory for a clone. For instance if we were to have 2 generational_arenas almost identical, and we need to clone one to the other,instead of doing
arena2 = arena1.clone()
, we could doarena2.clone_from(&arena1)
to re-use allocated space from arena2 and simply copy the content from arena1 where possible.This pull request implements the
clone_from
aspect for bothArena
andEntry
, so that theT
can also fully use the capabilities ofclone_from
they may have (for instance if an Entry is/contains aVec
).