mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[frozen-multimap] Add support for erasing once we have finished constructing the map.
I implemented this in a similar way to the way blotting is implemented in a blot map vector: 1. I changed this to store (Key, Optional<Value>) pairs. 2. I made it so that once frozen, we can "erase" things from the multimap by setting all Optional<Value> to none. 3. I changed the range we vend to be an OptionalTransformRange instead of just a TransformRange so we skip all keys with .none values, meaning that a user will get the nice behavior that getRange() still works after erasing. One interesting thing to note is that one /cannot/ erase elements when initializing the frozen multi-map since we haven't sorted it yet. At first this seems weird, but it actually fits with the use case of this data structure: building up state by processing IR in a readonly way and then later working with it in a worklist like way (and perhaps checking for unhandled cases at the end of processing). The nice thing additional thing is that I was able to ensure that the actual exposed API did not change in terms of how one uses it. I just changed the underlying iterators/etc.
This commit is contained in:
@@ -223,3 +223,101 @@ TEST(FrozenMultiMapCustomTest, RandomAgainstStdMultiMap) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FrozenMultiMapCustomTest, SimpleErase1) {
|
||||
Canary::resetIDs();
|
||||
FrozenMultiMap<Canary, Canary> map;
|
||||
|
||||
auto key1 = Canary();
|
||||
auto key2 = Canary();
|
||||
map.insert(key1, Canary());
|
||||
map.insert(key1, Canary());
|
||||
map.insert(key1, Canary());
|
||||
map.insert(key2, Canary());
|
||||
map.insert(key2, Canary());
|
||||
|
||||
map.setFrozen();
|
||||
|
||||
EXPECT_EQ(map.size(), 5u);
|
||||
|
||||
EXPECT_TRUE(map.erase(key2));
|
||||
EXPECT_FALSE(map.erase(key2));
|
||||
|
||||
{
|
||||
auto range = map.getRange();
|
||||
EXPECT_EQ(std::distance(range.begin(), range.end()), 1);
|
||||
|
||||
{
|
||||
auto begin = range.begin();
|
||||
auto end = range.end();
|
||||
++begin;
|
||||
EXPECT_EQ(std::distance(begin, end), 0);
|
||||
}
|
||||
|
||||
auto iter = range.begin();
|
||||
{
|
||||
auto p = *iter;
|
||||
EXPECT_EQ(p.first.getID(), key1.getID());
|
||||
EXPECT_EQ(p.second.size(), 3u);
|
||||
EXPECT_EQ(p.second[0].getID(), 2u);
|
||||
EXPECT_EQ(p.second[1].getID(), 3u);
|
||||
EXPECT_EQ(p.second[2].getID(), 4u);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(map.erase(key1));
|
||||
EXPECT_FALSE(map.erase(key1));
|
||||
|
||||
{
|
||||
auto range = map.getRange();
|
||||
EXPECT_EQ(std::distance(range.begin(), range.end()), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(FrozenMultiMapCustomTest, SimpleErase2) {
|
||||
Canary::resetIDs();
|
||||
FrozenMultiMap<Canary, Canary> map;
|
||||
|
||||
auto key1 = Canary();
|
||||
auto key2 = Canary();
|
||||
map.insert(key1, Canary());
|
||||
map.insert(key1, Canary());
|
||||
map.insert(key1, Canary());
|
||||
map.insert(key2, Canary());
|
||||
map.insert(key2, Canary());
|
||||
|
||||
map.setFrozen();
|
||||
|
||||
EXPECT_EQ(map.size(), 5u);
|
||||
|
||||
EXPECT_TRUE(map.erase(key1));
|
||||
|
||||
{
|
||||
auto range = map.getRange();
|
||||
EXPECT_EQ(std::distance(range.begin(), range.end()), 1);
|
||||
|
||||
{
|
||||
auto begin = range.begin();
|
||||
auto end = range.end();
|
||||
++begin;
|
||||
EXPECT_EQ(std::distance(begin, end), 0);
|
||||
}
|
||||
|
||||
auto iter = range.begin();
|
||||
{
|
||||
auto p = *iter;
|
||||
EXPECT_EQ(p.first.getID(), key2.getID());
|
||||
EXPECT_EQ(p.second.size(), 2u);
|
||||
EXPECT_EQ(p.second[0].getID(), 5u);
|
||||
EXPECT_EQ(p.second[1].getID(), 6u);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(map.erase(key2));
|
||||
EXPECT_FALSE(map.erase(key2));
|
||||
|
||||
{
|
||||
auto range = map.getRange();
|
||||
EXPECT_EQ(std::distance(range.begin(), range.end()), 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user