summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/id_map.h11
-rw-r--r--base/id_map_unittest.cc73
2 files changed, 84 insertions, 0 deletions
diff --git a/base/id_map.h b/base/id_map.h
index bb9f05b..d3fc7b8 100644
--- a/base/id_map.h
+++ b/base/id_map.h
@@ -92,6 +92,17 @@ class IDMap : public base::NonThreadSafe {
}
}
+ void Clear() {
+ DCHECK(CalledOnValidThread());
+ if (iteration_depth_ == 0) {
+ Releaser<OS, 0>::release_all(&data_);
+ } else {
+ for (typename HashTable::iterator i = data_.begin();
+ i != data_.end(); ++i)
+ removed_ids_.insert(i->first);
+ }
+ }
+
bool IsEmpty() const {
DCHECK(CalledOnValidThread());
return size() == 0u;
diff --git a/base/id_map_unittest.cc b/base/id_map_unittest.cc
index c4838ee..80c4c66 100644
--- a/base/id_map_unittest.cc
+++ b/base/id_map_unittest.cc
@@ -191,6 +191,42 @@ TEST_F(IDMapTest, AssignIterator) {
EXPECT_EQ(0, map.iteration_depth());
}
+TEST_F(IDMapTest, IteratorRemainsValidWhenClearing) {
+ IDMap<TestObject> map;
+
+ const int kCount = 5;
+ TestObject obj[kCount];
+ int32 ids[kCount];
+
+ for (int i = 0; i < kCount; i++)
+ ids[i] = map.Add(&obj[i]);
+
+ int counter = 0;
+ for (IDMap<TestObject>::const_iterator iter(&map);
+ !iter.IsAtEnd(); iter.Advance()) {
+ switch (counter) {
+ case 0:
+ EXPECT_EQ(ids[0], iter.GetCurrentKey());
+ EXPECT_EQ(&obj[0], iter.GetCurrentValue());
+ break;
+ case 1:
+ EXPECT_EQ(ids[1], iter.GetCurrentKey());
+ EXPECT_EQ(&obj[1], iter.GetCurrentValue());
+ map.Clear();
+ EXPECT_TRUE(map.IsEmpty());
+ EXPECT_EQ(0U, map.size());
+ break;
+ default:
+ FAIL() << "should not have that many elements";
+ break;
+ }
+ counter++;
+ }
+
+ EXPECT_TRUE(map.IsEmpty());
+ EXPECT_EQ(0U, map.size());
+}
+
TEST_F(IDMapTest, OwningPointersDeletesThemOnRemove) {
const int kCount = 3;
@@ -229,6 +265,43 @@ TEST_F(IDMapTest, OwningPointersDeletesThemOnRemove) {
EXPECT_EQ(owned_del_count, kCount);
}
+TEST_F(IDMapTest, OwningPointersDeletesThemOnClear) {
+ const int kCount = 3;
+
+ int external_del_count = 0;
+ DestructorCounter* external_obj[kCount];
+
+ int owned_del_count = 0;
+ DestructorCounter* owned_obj[kCount];
+
+ IDMap<DestructorCounter> map_external;
+ IDMap<DestructorCounter, IDMapOwnPointer> map_owned;
+
+ for (int i = 0; i < kCount; ++i) {
+ external_obj[i] = new DestructorCounter(&external_del_count);
+ map_external.Add(external_obj[i]);
+
+ owned_obj[i] = new DestructorCounter(&owned_del_count);
+ map_owned.Add(owned_obj[i]);
+ }
+
+ EXPECT_EQ(external_del_count, 0);
+ EXPECT_EQ(owned_del_count, 0);
+
+ map_external.Clear();
+ map_owned.Clear();
+
+ EXPECT_EQ(external_del_count, 0);
+ EXPECT_EQ(owned_del_count, kCount);
+
+ for (int i = 0; i < kCount; ++i) {
+ delete external_obj[i];
+ }
+
+ EXPECT_EQ(external_del_count, kCount);
+ EXPECT_EQ(owned_del_count, kCount);
+}
+
TEST_F(IDMapTest, OwningPointersDeletesThemOnDestruct) {
const int kCount = 3;