Skip to content

Commit

Permalink
tracked: Lots of restructuring. More and better diagnostics. More sep…
Browse files Browse the repository at this point in the history
…arate compilation. B/D now suitable for derivation.

darcs-hash:20080124123556-ec8c9-e056ce12989ac1e188f4d9e6f2e958bc266aea99.gz
  • Loading branch information
Eelis committed Jan 24, 2008
1 parent 5cfccd3 commit 5fbc877
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 182 deletions.
28 changes: 18 additions & 10 deletions prelude/more_stdlib_ostreaming.hpp → prelude/more_ostreaming.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@

#ifndef MORE_STDLIB_OSTREAMING_HPP
#define MORE_STDLIB_OSTREAMING_HPP
#ifndef MORE_OSTREAMING_HPP
#define MORE_OSTREAMING_HPP

#include <ostream>
#include <valarray>
#include <utility>
#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/ref.hpp>

namespace boost
{
template <typename C, typename Tr, typename T>
std::basic_ostream<C, Tr> & operator<<(std::basic_ostream<C, Tr> & o, boost::reference_wrapper<T> const & rw)
{ T & r(rw); return o << r; }
}

template <typename C, typename Tr, typename A, typename B>
std::basic_ostream<C, Tr> & operator<< (std::basic_ostream<C, Tr> & o, std::pair<A, B> const & p)
Expand All @@ -18,7 +26,7 @@ std::basic_ostream<C, Tr> & operator<< (std::basic_ostream<C, Tr> & o, std::pair
#include <tr1/tuple>
#include <tuple>

namespace more_stdlib_ostreaming_detail
namespace more_ostreaming_detail
{
template <int O>
struct tuple_printer
Expand Down Expand Up @@ -48,15 +56,15 @@ std::basic_ostream<C, Tr> & operator<< (std::basic_ostream<C, Tr> & o, std::pair

template <typename C, typename Tr, typename... P>
std::basic_ostream<C, Tr> & operator<< (std::basic_ostream<C, Tr> & o, std::tr1::tuple<P...> const & t)
{ o << '('; more_stdlib_ostreaming_detail::tuple_printer<sizeof...(P)>::print(o, t); return o << ')'; }
{ o << '('; more_ostreaming_detail::tuple_printer<sizeof...(P)>::print(o, t); return o << ')'; }

template <typename C, typename Tr, typename... P>
std::basic_ostream<C, Tr> & operator<< (std::basic_ostream<C, Tr> & o, std::tuple<P...> const & t)
{ o << '('; more_stdlib_ostreaming_detail::tuple_printer<sizeof...(P)>::print(o, t); return o << ')'; }
{ o << '('; more_ostreaming_detail::tuple_printer<sizeof...(P)>::print(o, t); return o << ')'; }

#endif

namespace more_stdlib_ostreaming_detail
namespace more_ostreaming_detail
{
template <typename C, typename Tr, typename Range>
void print_range (std::basic_ostream<C, Tr> & o, Range const & r)
Expand All @@ -71,9 +79,9 @@ namespace more_stdlib_ostreaming_detail
}

template <typename C, typename Tr, typename R>
typename more_stdlib_ostreaming_detail::snd<typename R::iterator, std::basic_ostream<C, Tr> &>::type
typename more_ostreaming_detail::snd<typename R::iterator, std::basic_ostream<C, Tr> &>::type
operator<<(std::basic_ostream<C, Tr> & o, R const & r)
{ more_stdlib_ostreaming_detail::print_range(o, r); return o; }
{ more_ostreaming_detail::print_range(o, r); return o; }

// Since we defined our generic operator<< for ranges in the global namespace, boost::lexical_cast won't find it when used on range types defined in namespaces other than the global namespace. For now, our quick fix for standard library containers is the following:

Expand All @@ -82,7 +90,7 @@ namespace std { using ::operator<<; }
template <typename C, typename Tr, typename T, size_t N>
typename boost::disable_if<boost::is_same<T, char>, std::basic_ostream<C, Tr> &>::type
operator<<(std::basic_ostream<C, Tr> & o, T const (& a) [N])
{ more_stdlib_ostreaming_detail::print_range(o, a); return o; }
{ more_ostreaming_detail::print_range(o, a); return o; }

namespace std
{
Expand All @@ -97,7 +105,7 @@ namespace std

#endif // header guard

#ifdef MORE_STDLIB_OSTREAMING_TEST
#ifdef MORE_OSTREAMING_TEST

#include <vector>
#include <set>
Expand Down
2 changes: 1 addition & 1 deletion prelude/prelude.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

#include "tracked.hpp"
#include "using.hpp"
#include "more_stdlib_ostreaming.hpp"
#include "more_ostreaming.hpp"
#include "type_strings.hpp"
#include "delimited_ostream.hpp"
#include "bin_iomanip.hpp"
Expand Down
136 changes: 84 additions & 52 deletions prelude/tracked.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

#include "tracked.hpp"

#include <cassert>

namespace geordi { void abort (); }

namespace tracked
Expand All @@ -9,93 +11,123 @@ namespace tracked
{
bool muted = false;

id_t Idd::new_id = 0;

Idd::Idd (name_t const name): id(new_id++), name(name), status(fresh)
std::string unqualified(std::string const & s)
{
reg.s.insert(std::make_pair(id, name));
for (Allocations::iterator i = allocations.begin(); i != allocations.end(); ++i)
if (i->first.first <= this && this < i->first.second) { i->second.insert(id); break; }
std::string::size_type const i = s.find_last_of(":");
if (i == std::string::npos) return s;
return s.substr(i + 1);
}

Idd::Idd (Idd const & i, name_t const name): id(new_id++), name(name), status(fresh)
{ i.assert_not_pillaged("copy"); reg.s.insert(std::make_pair(id, name)); }

Idd & Idd::operator= (Idd const & i)
void Root::op_delete (void * const p, bool const array, std::size_t const s, std::string const & name)
{
assert_not_destructed("assign to");
i.assert_not_pillaged("assign from");
status = fresh;
return *this;
if (array) ::operator delete[](p);
else ::operator delete(p);
if (muted) return;
std::vector<boost::reference_wrapper<Entry const> > v;
for (Entries::const_iterator j = entries.begin(); j != entries.end(); ++j)
if (p <= j->p && j->p <= static_cast<char *>(p) + s) v.push_back(boost::cref(*j));
if (array) std::cout << " delete" << v << ' ';
else { assert(v.size() == 1); std::cout << " delete(" << v.front() << ") "; }
}

void Idd::assert_not_pillaged (std::string const & s) const
Root::Root() { make_entry(); }

Root::Root(Root const & i) { make_entry(); i.assert_status_below(pillaged, "copy"); }

Root & Root::operator=(Root const & r)
{
if (status == fresh) return;
std::cout << " Error: Tried to " << s << (status == pillaged ? " pillaged " : " destructed ") << name << id << '.';
geordi::abort();
assert_status_below(destructed, "assign to");
r.assert_status_below(pillaged, "assign from");
entry()->status = fresh;
return *this;
}

void Idd::assert_not_destructed (std::string const & s) const
void Root::assert_status_below(Status const st, std::string const & s) const
{
if (status != destructed) return;
std::cout << " Error: Tried to " << s << " destructed " << name << id << '.';
geordi::abort();
if (Entry * const e = entry())
{
if (e->status < st) return;
std::cout << " Error: Tried to " << s << (e->status == pillaged ? " pillaged " : " destructed ") << *e << '.';
geordi::abort();
}
else { std::cout << " Error: Tried to " << s << " non-existent object."; geordi::abort(); }
}

#ifdef __GXX_EXPERIMENTAL_CXX0X__

Idd::Idd (Idd && i, name_t const name): id(new_id++), name(name), status(fresh)
{ i.assert_not_pillaged("move"); i.status = pillaged; reg.s.insert(std::make_pair(id, name)); }
Root::Root(Root && r)
{ make_entry(); r.assert_status_below(pillaged, "move"); r.entry()->status = pillaged; }

Idd & Idd::operator= (Idd && i)
Root & Root::operator=(Root && r)
{
assert_not_destructed("move-assign to");
i.assert_not_pillaged("move");
status = fresh;
i.status = pillaged;
assert_status_below(destructed, "move-assign to");
r.assert_status_below(pillaged, "move");
entry()->status = fresh;
r.entry()->status = pillaged;
return *this;
}

#endif

Idd::~Idd () { assert_not_destructed("re-destruct"); status = destructed; reg.s.erase(id); }
Root::~Root () { assert_status_below(destructed, "re-destruct"); entry()->status = destructed; }

Allocations allocations;
Root::Entries Root::entries;
Root::LeakReporter Root::leakReporter; // Must come after entries, so it will be destructed first.

Idd::Reg Idd::reg;
void Root::make_entry() const
{
if (Entry * const e = entry())
if (e->status != destructed) { std::cout << "Error: Leaked: " << *e; geordi::abort(); }
entries.push_back(Entry(this));
}

Root::Entry * Root::entry() const
{
for (Entries::reverse_iterator i(entries.rbegin()); i != entries.rend(); ++i)
if (i->p == this) return &*i;
return 0;
}

unsigned int Root::id() const { return entry() - &entries.front(); }

Idd::Reg::~Reg ()
Root::LeakReporter::~LeakReporter()
{
if (s.empty()) return;
std::cout << " || leaked:";
for (map::const_iterator i = s.begin(); i != s.end(); ++i) std::cout << ' ' << i->second << i->first;
std::vector<boost::reference_wrapper<Entry const> > v;
for (Entries::const_iterator i = entries.begin(); i != entries.end(); ++i)
if (i->status != destructed) v.push_back(boost::cref(*i));
if (!v.empty()) { std::cout << " Leaked: " << v; geordi::abort(); }
}
}

} // namespace detail

// B:

B::B(): Idd('B') {}
B::B(B const & b): Idd(b, 'B'), Base(b) {}
B::B(int const i): Idd('B'), Base(i) {}
B::B(char const c): Idd('B'), Base(c) {}
B::B(std::string const & s): Idd('B'), Base(s) {}
B::B() {}
B::B(B const & b): Base(b) {}
B::B(int const i): Base(i) {}
B::B(char const c): Base(c) {}
B::B(std::string const & s): Base(s) {}
B & B::operator=(B const & b) { return Base::operator=(b); }
B::~B() {}

#ifdef __GXX_EXPERIMENTAL_CXX0X__
B::B(B && b): Idd(std::move(b), 'B'), Base(std::move(b)) {}
B & B::operator=(B && b) { Base::operator=(std::move(b)); return *this; }
B::B(B && b): Base(std::move<Base>(b)) {}
B & B::operator=(B && b) { return Base::operator=(std::move<Base>(b)); }
#endif

// D:

D::D(): Idd('D') {}
D::D(D const & d): Idd(d, 'D'), Base(d) {}
D::D(int const i): Idd('D'), Base(i) {}
D::D(char const c): Idd('D'), Base(c) {}
D::D(std::string const & s): Idd('D'), Base(s) {}
D::D() {}
D::D(D const & d): Base(d) {}
D::D(int const i): Base(i) {}
D::D(char const c): Base(c) {}
D::D(std::string const & s): Base(s) {}
D & D::operator=(D const & b) { return Base::operator=(b); }
D::~D() {}

#ifdef __GXX_EXPERIMENTAL_CXX0X__
D::D(D && d): Idd(std::move(d), 'D'), Base(std::move(d)) {}
D & D::operator=(D && d) { Base::operator=(std::move(d)); return *this; }
D::D(D && d): Base(std::move<Base>(d)) {}
D & D::operator=(D && d) { return Base::operator=(std::move<Base>(d)); }
#endif
}

} // namespace tracked
Loading

0 comments on commit 5fbc877

Please sign in to comment.