Commit 4a9c9ff3 authored by btolsch's avatar btolsch Committed by Commit Bot

Add small_map::emplace

This also replaces some uses of small_map::insert with emplace.

Bug: None
Change-Id: I857ca36847eefe7dcc4a7f90d12c0d99ccf2afd8
Reviewed-on: https://chromium-review.googlesource.com/567599
Commit-Queue: Brandon Tolsch <btolsch@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarDerek Cheng <imcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#486254}
parent eff595d3
......@@ -452,6 +452,34 @@ class small_map {
}
}
// Invalidates iterators.
template <typename... Args>
std::pair<iterator, bool> emplace(Args&&... args) {
key_equal compare;
if (size_ >= 0) {
value_type x(std::forward<Args>(args)...);
for (int i = 0; i < size_; i++) {
if (compare(array_[i]->first, x.first)) {
return std::make_pair(iterator(array_ + i), false);
}
}
if (size_ == kArraySize) {
ConvertToRealMap(); // Invalidates all iterators!
std::pair<typename NormalMap::iterator, bool> ret =
map_->emplace(std::move(x));
return std::make_pair(iterator(ret.first), ret.second);
} else {
array_[size_].Init(std::move(x));
return std::make_pair(iterator(array_ + size_++), true);
}
} else {
std::pair<typename NormalMap::iterator, bool> ret =
map_->emplace(std::forward<Args>(args)...);
return std::make_pair(iterator(ret.first), ret.second);
}
}
iterator begin() {
if (size_ >= 0) {
return iterator(array_);
......
......@@ -509,12 +509,15 @@ TEST(SmallMap, SubclassInitializationWithFunctionObject) {
EXPECT_EQ(1u, m.count(-1));
}
namespace {
// This class acts as a basic implementation of a move-only type. The canonical
// example of such a type is scoped_ptr/unique_ptr.
template <typename V>
class MoveOnlyType {
public:
MoveOnlyType() : value_(0) {}
explicit MoveOnlyType(int value) : value_(value) {}
explicit MoveOnlyType(V value) : value_(value) {}
MoveOnlyType(MoveOnlyType&& other) {
*this = std::move(other);
......@@ -529,26 +532,28 @@ class MoveOnlyType {
MoveOnlyType(const MoveOnlyType&) = delete;
MoveOnlyType& operator=(const MoveOnlyType&) = delete;
int value() const { return value_; }
V value() const { return value_; }
private:
int value_;
V value_;
};
} // namespace
TEST(SmallMap, MoveOnlyValueType) {
small_map<std::map<int, MoveOnlyType>, 2> m;
small_map<std::map<int, MoveOnlyType<int>>, 2> m;
m[0] = MoveOnlyType(1);
m[1] = MoveOnlyType(2);
m[0] = MoveOnlyType<int>(1);
m[1] = MoveOnlyType<int>(2);
m.erase(m.begin());
// small_map will move m[1] to an earlier index in the internal array.
EXPECT_EQ(m.size(), 1u);
EXPECT_EQ(m[1].value(), 2);
m[0] = MoveOnlyType(1);
m[0] = MoveOnlyType<int>(1);
// small_map must move the values from the array into the internal std::map.
m[2] = MoveOnlyType(3);
m[2] = MoveOnlyType<int>(3);
EXPECT_EQ(m.size(), 3u);
EXPECT_EQ(m[0].value(), 1);
......@@ -563,4 +568,36 @@ TEST(SmallMap, MoveOnlyValueType) {
EXPECT_EQ(m[2].value(), 3);
}
TEST(SmallMap, Emplace) {
small_map<std::map<size_t, MoveOnlyType<size_t>>> sm;
// loop through the transition from small map to map.
for (size_t i = 1; i <= 10; ++i) {
// insert an element
auto ret = sm.emplace(i, MoveOnlyType<size_t>(100 * i));
EXPECT_TRUE(ret.second);
EXPECT_TRUE(ret.first == sm.find(i));
EXPECT_EQ(ret.first->first, i);
EXPECT_EQ(ret.first->second.value(), 100 * i);
// try to insert it again with different value, fails, but we still get an
// iterator back with the original value.
ret = sm.emplace(i, MoveOnlyType<size_t>(i));
EXPECT_FALSE(ret.second);
EXPECT_TRUE(ret.first == sm.find(i));
EXPECT_EQ(ret.first->first, i);
EXPECT_EQ(ret.first->second.value(), 100 * i);
// check the state of the map.
for (size_t j = 1; j <= i; ++j) {
const auto it = sm.find(j);
EXPECT_TRUE(it != sm.end());
EXPECT_EQ(it->first, j);
EXPECT_EQ(it->second.value(), j * 100);
}
EXPECT_EQ(sm.size(), i);
EXPECT_FALSE(sm.empty());
}
}
} // namespace base
......@@ -73,11 +73,10 @@ GetInterfaceGuidMacMap() {
base::small_map<std::map<GUID, std::string, GuidOperatorLess>> guid_mac_map;
for (ULONG i = 0; i < interface_table->NumEntries; ++i) {
const auto* interface_row = &interface_table->Table[i];
guid_mac_map.insert(std::make_pair(
interface_row->InterfaceGuid,
std::string{
reinterpret_cast<const char*>(interface_row->PhysicalAddress),
interface_row->PhysicalAddressLength}));
guid_mac_map.emplace(interface_row->InterfaceGuid,
std::string{reinterpret_cast<const char*>(
interface_row->PhysicalAddress),
interface_row->PhysicalAddressLength});
}
return guid_mac_map;
......@@ -153,7 +152,7 @@ base::small_map<std::map<std::string, std::string>> GetMacSsidMap() {
if (ssid.empty()) {
continue;
}
mac_ssid_map.insert(std::make_pair(mac_entry->second, std::move(ssid)));
mac_ssid_map.emplace(mac_entry->second, std::move(ssid));
}
return mac_ssid_map;
}
......
......@@ -106,9 +106,8 @@ class PresentationFrame {
base::small_map<
std::map<std::string, std::unique_ptr<PresentationMediaSinksObserver>>>
url_to_sinks_observer_;
std::unordered_map<
MediaRoute::Id,
std::unique_ptr<PresentationConnectionStateSubscription>>
std::unordered_map<MediaRoute::Id,
std::unique_ptr<PresentationConnectionStateSubscription>>
connection_state_subscriptions_;
std::unordered_map<MediaRoute::Id,
std::unique_ptr<BrowserPresentationConnectionProxy>>
......@@ -207,8 +206,7 @@ void PresentationFrame::Reset() {
void PresentationFrame::AddPresentation(
const content::PresentationInfo& presentation_info,
const MediaRoute& route) {
presentation_id_to_route_.insert(
std::make_pair(presentation_info.presentation_id, route));
presentation_id_to_route_.emplace(presentation_info.presentation_id, route);
}
void PresentationFrame::ConnectToPresentation(
......@@ -247,8 +245,7 @@ void PresentationFrame::ConnectToPresentation(
auto* proxy = new BrowserPresentationConnectionProxy(
router_, route_id, std::move(receiver_connection_request),
std::move(controller_connection_ptr));
browser_connection_proxies_.insert(
std::make_pair(route_id, base::WrapUnique(proxy)));
browser_connection_proxies_.emplace(route_id, base::WrapUnique(proxy));
}
}
......@@ -285,9 +282,9 @@ void PresentationFrame::ListenForConnectionStateChange(
return;
}
connection_state_subscriptions_.insert(std::make_pair(
connection_state_subscriptions_.emplace(
route_id, router_->AddPresentationConnectionStateChangedCallback(
route_id, state_changed_cb)));
route_id, state_changed_cb));
}
PresentationServiceDelegateImpl*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment