perf(util/list): avoid recursion in map and destructor

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-11-18 16:47:52 -08:00
parent d67bf995ed
commit 76252816ac
3 changed files with 54 additions and 2 deletions

View file

@ -131,6 +131,21 @@ static void tst10(int sz, int num) {
}
}
static void tst11(int sz, int num) {
list<int> l;
for (int i = 0; i < sz; i++) {
l = cons(i, l);
}
list<int> l2;
{
timeit timer(std::cout, "map");
for (int i = 0; i < num; i++) {
l2 = map(l, [&](int v) { return v; });
}
}
lean_assert(l == l2);
}
int main() {
tst1();
tst2();
@ -142,5 +157,6 @@ int main() {
tst8();
tst9(100);
tst10(1000, 5);
tst11(1000, 5);
return has_violations() ? 1 : 0;
}

View file

@ -30,6 +30,7 @@ public:
};
private:
cell * m_ptr;
cell * steal_ptr() { cell * r = m_ptr; m_ptr = nullptr; return r; }
public:
list():m_ptr(nullptr) {}
list(T const & h, list const & t):m_ptr(new cell(h, t)) {}
@ -44,7 +45,22 @@ public:
}
}
explicit list(cell * c):m_ptr(c) { if (m_ptr) m_ptr->inc_ref(); }
~list() { if (m_ptr) m_ptr->dec_ref(); }
~list() {
if (m_ptr && m_ptr->dec_ref_core()) {
cell * it = m_ptr;
while (true) {
lean_assert(it);
lean_assert(it->get_rc() == 0);
cell * next = it->m_tail.steal_ptr();
delete it;
if (next && next->dec_ref_core()) {
it = next;
} else {
break;
}
}
}
}
list & operator=(list const & s) { LEAN_COPY_REF(list, s); }
list & operator=(list && s) { LEAN_MOVE_REF(list, s); }

View file

@ -22,6 +22,18 @@ void to_buffer(list<T> const & l, buffer<T> & r) {
}
}
/**
\brief Copy the cells in the list \c l to the buffer \c r.
*/
template<typename T>
void to_buffer(list<T> const & l, buffer<typename list<T>::cell *> & r) {
typename list<T>::cell * it = l.raw();
while (it) {
r.push_back(it);
it = it->tail().raw();
}
}
/**
\brief Auxiliary function for reverse function.
*/
@ -114,7 +126,15 @@ list<T> map(list<T> const & l, F f) {
if (is_nil(l)) {
return l;
} else {
return list<T>(f(head(l)), map(tail(l), f));
buffer<typename list<T>::cell*> tmp;
to_buffer(l, tmp);
unsigned i = tmp.size();
list<T> r;
while (i > 0) {
--i;
r = cons(f(tmp[i]->head()), r);
}
return l;
}
}