auto merge of #8297 : brson/rust/dlist-dtor, r=brson
The compiler-generated dtor for DList recurses deeply to drop Nodes. For big lists this can overflow the stack. This is a problem for the new scheduler, where split stacks are not implemented. Thanks @blake2-ppc
This commit is contained in:
commit
6c12ca3ac2
@ -92,6 +92,11 @@ impl<T> Rawlink<T> {
|
||||
Some(unsafe { cast::transmute(self.p) })
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the `Rawlink` and replace with `Rawlink::none()`
|
||||
fn take(&mut self) -> Rawlink<T> {
|
||||
util::replace(self, Rawlink::none())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for Rawlink<T> {
|
||||
@ -280,13 +285,16 @@ impl<T> DList<T> {
|
||||
/// Add all elements from `other` to the end of the list
|
||||
///
|
||||
/// O(1)
|
||||
pub fn append(&mut self, other: DList<T>) {
|
||||
pub fn append(&mut self, mut other: DList<T>) {
|
||||
match self.list_tail.resolve() {
|
||||
None => *self = other,
|
||||
Some(tail) => {
|
||||
match other {
|
||||
DList{list_head: None, _} => return,
|
||||
DList{list_head: Some(node), list_tail: o_tail, length: o_length} => {
|
||||
// Carefully empty `other`.
|
||||
let o_tail = other.list_tail.take();
|
||||
let o_length = other.length;
|
||||
match other.list_head.take() {
|
||||
None => return,
|
||||
Some(node) => {
|
||||
tail.next = link_with_prev(node, self.list_tail);
|
||||
self.list_tail = o_tail;
|
||||
self.length += o_length;
|
||||
@ -404,6 +412,32 @@ impl<T: Ord> DList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe_destructor]
|
||||
impl<T> Drop for DList<T> {
|
||||
fn drop(&self) {
|
||||
let mut_self = unsafe {
|
||||
cast::transmute_mut(self)
|
||||
};
|
||||
// Dissolve the dlist in backwards direction
|
||||
// Just dropping the list_head can lead to stack exhaustion
|
||||
// when length is >> 1_000_000
|
||||
let mut tail = mut_self.list_tail;
|
||||
loop {
|
||||
match tail.resolve() {
|
||||
None => break,
|
||||
Some(prev) => {
|
||||
prev.next.take(); // release ~Node<T>
|
||||
tail = prev.prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
mut_self.length = 0;
|
||||
mut_self.list_head = None;
|
||||
mut_self.list_tail = Rawlink::none();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<'self, A> Iterator<&'self A> for DListIterator<'self, A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'self A> {
|
||||
|
Loading…
Reference in New Issue
Block a user