Commit 594f4d72 authored by Giuseppe Ottaviano's avatar Giuseppe Ottaviano Committed by Facebook Github Bot

Round-trip iteration order for F14Vector{Map,Set}

Summary: `F14Vector{Map,Set}` have specified iteration order: inverse insertion order. When serialized, however, the order does not round-trip (in fact, it flips). This diff introduces an extension point to specify the iteration order for serialization, and it specializes it for F14 to make the iteration order round-trip.

Reviewed By: vitaut

Differential Revision: D17108774

fbshipit-source-id: 466b746baacff861242729bfa62447c138094cee
parent 55e5070f
...@@ -810,3 +810,23 @@ template <> ...@@ -810,3 +810,23 @@ template <>
struct is_unsigned<unsigned __int128> : ::std::true_type {}; struct is_unsigned<unsigned __int128> : ::std::true_type {};
FOLLY_NAMESPACE_STD_END FOLLY_NAMESPACE_STD_END
#endif // FOLLY_SUPPLY_MISSING_INT128_TRAITS #endif // FOLLY_SUPPLY_MISSING_INT128_TRAITS
namespace folly {
/**
* Extension point for containers to provide an order such that if entries are
* inserted into a new instance in that order, iteration order of the new
* instance matches the original's. This can be useful for containers that have
* defined but non-FIFO iteration order, such as F14Vector*.
*
* Should return an iterable view (a type that provides begin() and end()).
*
* Containers should provide overloads in their own namespace; resolution is
* expected to be done via ADL.
*/
template <typename Container>
const Container& order_preserving_reinsertion_view(const Container& container) {
return container;
}
} // namespace folly
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <stdexcept> #include <stdexcept>
#include <folly/Range.h>
#include <folly/Traits.h> #include <folly/Traits.h>
#include <folly/lang/Exception.h> #include <folly/lang/Exception.h>
#include <folly/lang/SafeAssert.h> #include <folly/lang/SafeAssert.h>
...@@ -1139,6 +1140,12 @@ class F14VectorMap : public f14::detail::F14VectorMapImpl< ...@@ -1139,6 +1140,12 @@ class F14VectorMap : public f14::detail::F14VectorMapImpl<
} }
}; };
template <typename K, typename M, typename H, typename E, typename A>
Range<typename F14VectorMap<K, M, H, E, A>::const_reverse_iterator>
order_preserving_reinsertion_view(const F14VectorMap<K, M, H, E, A>& c) {
return {c.rbegin(), c.rend()};
}
template < template <
typename Key, typename Key,
typename Mapped, typename Mapped,
......
...@@ -975,6 +975,12 @@ class F14VectorSet ...@@ -975,6 +975,12 @@ class F14VectorSet
} }
}; };
template <typename K, typename H, typename E, typename A>
Range<typename F14VectorSet<K, H, E, A>::const_reverse_iterator>
order_preserving_reinsertion_view(const F14VectorSet<K, H, E, A>& c) {
return {c.rbegin(), c.rend()};
}
template <typename Key, typename Hasher, typename KeyEqual, typename Alloc> template <typename Key, typename Hasher, typename KeyEqual, typename Alloc>
class F14FastSet class F14FastSet
: public std::conditional_t< : public std::conditional_t<
......
...@@ -842,6 +842,20 @@ TEST(F14VectorMap, reverse_iterator) { ...@@ -842,6 +842,20 @@ TEST(F14VectorMap, reverse_iterator) {
} }
} }
TEST(F14VectorMap, OrderPreservingReinsertionView) {
F14VectorMap<int, int> m1;
for (size_t i = 0; i < 5; ++i) {
m1.emplace(i, i);
}
F14VectorMap<int, int> m2;
for (const auto& kv : order_preserving_reinsertion_view(m1)) {
m2.insert(kv);
}
EXPECT_EQ(asVector(m1), asVector(m2));
}
TEST(F14ValueMap, eraseWhileIterating) { TEST(F14ValueMap, eraseWhileIterating) {
runEraseWhileIterating<F14ValueMap<int, int>>(); runEraseWhileIterating<F14ValueMap<int, int>>();
} }
......
...@@ -764,6 +764,20 @@ TEST(F14VectorMap, reverse_iterator) { ...@@ -764,6 +764,20 @@ TEST(F14VectorMap, reverse_iterator) {
} }
} }
TEST(F14VectorSet, OrderPreservingReinsertionView) {
F14VectorSet<int> s1;
for (size_t i = 0; i < 5; ++i) {
s1.emplace(i);
}
F14VectorSet<int> s2;
for (const auto& k : order_preserving_reinsertion_view(s1)) {
s2.insert(k);
}
EXPECT_EQ(asVector(s1), asVector(s2));
}
TEST(F14ValueSet, eraseWhileIterating) { TEST(F14ValueSet, eraseWhileIterating) {
runEraseWhileIterating<F14ValueSet<int>>(); runEraseWhileIterating<F14ValueSet<int>>();
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <cstddef> #include <cstddef>
#include <ostream> #include <ostream>
#include <type_traits>
#include <vector> #include <vector>
#include <folly/container/detail/F14Policy.h> #include <folly/container/detail/F14Policy.h>
...@@ -106,5 +107,11 @@ inline std::ostream& operator<<(std::ostream& xo, F14TableStats const& stats) { ...@@ -106,5 +107,11 @@ inline std::ostream& operator<<(std::ostream& xo, F14TableStats const& stats) {
return xo; return xo;
} }
template <typename Container>
std::vector<typename std::decay_t<Container>::value_type> asVector(
const Container& c) {
return {c.begin(), c.end()};
}
} // namespace f14 } // namespace f14
} // namespace folly } // namespace folly
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