[Aptitude-devel] r3231 - in branches/aptitude-0.3/aptitude: . src/generic/problemresolver
Daniel Burrows
dburrows@costa.debian.org
Sun, 01 May 2005 15:39:16 +0000
Author: dburrows
Date: Sun May 1 15:39:13 2005
New Revision: 3231
Modified:
branches/aptitude-0.3/aptitude/ChangeLog
branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc
Log:
Fix a crash in the test code.
Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog (original)
+++ branches/aptitude-0.3/aptitude/ChangeLog Sun May 1 15:39:13 2005
@@ -1,5 +1,14 @@
2005-05-01 Daniel Burrows <dburrows@debian.org>
+ * src/generic/problemresolver/test.cc:
+
+ Fix a crash that occured when an error was encountered in
+ parsing a test file: the resolver copied the universe, which had
+ references to the package objects, and hence the packages got
+ double-deleted. Now universes are reference-counted and it's
+ the references that are copied around, so the problem should go
+ away.
+
* src/generic/problemresolver/problemresolver.h:
When dumping version scores, actually write the scores instead
Modified: branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc (original)
+++ branches/aptitude-0.3/aptitude/src/generic/problemresolver/test.cc Sun May 1 15:39:13 2005
@@ -682,7 +682,120 @@
}
};
-typedef generic_problem_resolver<dummy_universe> dummy_resolver;
+// A refcounting wrapper for a dummy_universe; used to sanitize memory
+// management without copying all over (and because the resolver
+// expects to be able to have a full copy of its argument type)
+class dummy_universe_ref
+{
+ struct _rep
+ {
+ int refcount;
+ dummy_universe *universe;
+
+ /** Start with 1 ref since our creator holds a ref. */
+ _rep(dummy_universe *_universe)
+ :refcount(1), universe(_universe)
+ {
+ }
+
+ void incref() {++refcount;}
+ void decref() {--refcount; if(refcount==0) delete this;}
+ };
+
+ _rep *rep;
+public:
+ typedef dummy_universe::package package;
+ typedef dummy_universe::version version;
+ typedef dummy_universe::dep dep;
+ typedef dummy_universe::package_iterator package_iterator;
+ typedef dummy_universe::dep_iterator dep_iterator;
+ typedef dummy_universe::broken_dep_iterator broken_dep_iterator;
+
+ dummy_universe_ref()
+ :rep(NULL)
+ {
+ }
+
+ dummy_universe_ref(const dummy_universe_ref &other)
+ :rep(other.rep)
+ {
+ }
+
+ /** Assumes this is the first reference to the universe. */
+ dummy_universe_ref(dummy_universe *universe)
+ :rep(new _rep(universe))
+ {
+ }
+
+ ~dummy_universe_ref()
+ {
+ if(rep)
+ rep->decref();
+ }
+
+ dummy_universe_ref &operator=(const dummy_universe_ref &other)
+ {
+ if(other.rep)
+ other.rep->incref();
+ if(rep)
+ rep->decref();
+ rep=other.rep;
+
+ return *this;
+ }
+
+ operator void*() const
+ {
+ return (void *) (rep && rep->universe);
+ }
+
+ void add_package(string name,
+ vector<string> the_versions,
+ string curname) const
+ {
+ rep->universe->add_package(name, the_versions, curname);
+ }
+
+ void add_dep(string pkg_name, string pkg_ver,
+ const vector<pair<string, string> > &target_names,
+ bool is_conflict)
+ {
+ rep->universe->add_dep(pkg_name, pkg_ver,
+ target_names, is_conflict);
+ }
+
+ package find_package(string pkg_name) const
+ {
+ return rep->universe->find_package(pkg_name);
+ }
+
+ vector<package>::size_type get_package_count() const
+ {
+ return rep->universe->get_package_count();
+ }
+
+ vector<version>::size_type get_version_count() const
+ {
+ return rep->universe->get_version_count();
+ }
+
+ package_iterator packages_begin() const
+ {
+ return rep->universe->packages_begin();
+ }
+
+ dep_iterator deps_begin() const
+ {
+ return rep->universe->deps_begin();
+ }
+
+ broken_dep_iterator broken_begin() const
+ {
+ return rep->universe->broken_begin();
+ }
+};
+
+typedef generic_problem_resolver<dummy_universe_ref> dummy_resolver;
ostream &operator<<(ostream &out, const dummy_resolver::dep &d)
{
@@ -743,9 +856,9 @@
}
/** Parses a universe to the closing ']'. */
-dummy_universe *parse_universe(istream &in)
+dummy_universe_ref parse_universe(istream &in)
{
- dummy_universe *rval=new dummy_universe;
+ dummy_universe_ref rval=new dummy_universe;
in >> ws;
while(in)
@@ -803,7 +916,7 @@
if(vernames.empty())
throw ParseError("Package "+pkgname+" has no versions");
- rval->add_package(pkgname, vernames, curname);
+ rval.add_package(pkgname, vernames, curname);
}
else if(s == "DEP")
{
@@ -853,8 +966,8 @@
throw ParseError("Unexpected EOF in dependency target list following package "+pkgname+" version "+vername);
}
- rval->add_dep(source.first, source.second, targets,
- is_conflict);
+ rval.add_dep(source.first, source.second, targets,
+ is_conflict);
}
else
throw ParseError("Expected PACKAGE or DEP, got "+s);
@@ -868,7 +981,7 @@
/** Reads the list of scores into the resolver. */
void read_scores(istream &f,
- dummy_universe *universe, dummy_resolver &resolver)
+ dummy_universe_ref universe, dummy_resolver &resolver)
{
if(!universe)
throw ParseError("Internal error: NULL universe in read_scores");
@@ -892,7 +1005,7 @@
f >> pkgname >> ws;
- dummy_universe::package pkg=universe->find_package(pkgname);
+ dummy_universe::package pkg=universe.find_package(pkgname);
if(f.eof())
throw ParseError("Expected '<' following package name, got EOF");
@@ -942,7 +1055,7 @@
}
/** Reads the tail of a non-ANY SOLN form. */
-map<dummy_universe::package, dummy_resolver::version> read_solution(istream &f, dummy_universe *universe)
+map<dummy_universe::package, dummy_resolver::version> read_solution(istream &f, dummy_universe_ref universe)
{
if(!universe)
throw ParseError("Internal error: NULL universe passed to read_solution");
@@ -967,7 +1080,7 @@
if(f.eof())
throw ParseError("Expected version, got EOF");
- dummy_universe::package pkg=universe->find_package(s);
+ dummy_universe::package pkg=universe.find_package(s);
f >> s >> ws;
@@ -991,7 +1104,7 @@
void run_test_file(istream &f)
{
- dummy_universe *universe=NULL;
+ dummy_universe_ref universe=NULL;
f >> ws;
@@ -1017,13 +1130,10 @@
if(s != "[")
throw ParseError("Expected '[' following UNIVERSE, got " + s);
- dummy_universe *new_universe=parse_universe(f);
-
- delete universe;
- universe=new_universe;
+ universe=parse_universe(f);
cout << "Input universe:" << endl;
- dump_universe(*universe, cout);
+ dump_universe(universe, cout);
}
else if(s == "TEST")
{
@@ -1054,7 +1164,7 @@
dummy_resolver resolver(step_score, broken_score,
infinity, max_successors,
- goal_score, *universe);
+ goal_score, universe);
read_scores(f, universe, resolver);
@@ -1170,7 +1280,6 @@
}
catch(...)
{
- delete universe;
throw;
}
}