Add rudimentary support for move-only types as values in HashMap
authorandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Sep 2013 16:13:47 +0000 (16:13 +0000)
committerandersca@apple.com <andersca@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 12 Sep 2013 16:13:47 +0000 (16:13 +0000)
https://bugs.webkit.org/show_bug.cgi?id=121226

Reviewed by Andreas Kling.

Source/WTF:

* wtf/HashMap.h:
Change a bunch of functions to so they can take both rvalue and lvalue references and use std::forward.

* wtf/HashTraits.h:
(WTF::KeyValuePair::KeyValuePair):
Change constructors to accept both lvalues and rvalues.

Tools:

* TestWebKitAPI/Tests/WTF/HashMap.cpp:
(TestWebKitAPI::TEST):
Add a HashMap<unsigned, MoveOnly> test.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@155621 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WTF/ChangeLog
Source/WTF/wtf/HashMap.h
Source/WTF/wtf/HashTraits.h
Tools/ChangeLog
Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp

index c51fd4c..f4a9498 100644 (file)
@@ -1,3 +1,17 @@
+2013-09-12  Anders Carlsson  <andersca@apple.com>
+
+        Add rudimentary support for move-only types as values in HashMap
+        https://bugs.webkit.org/show_bug.cgi?id=121226
+
+        Reviewed by Andreas Kling.
+
+        * wtf/HashMap.h:
+        Change a bunch of functions to so they can take both rvalue and lvalue references and use std::forward.
+
+        * wtf/HashTraits.h:
+        (WTF::KeyValuePair::KeyValuePair):
+        Change constructors to accept both lvalues and rvalues.
+
 2013-09-12  Mikhail Pozdnyakov  <mikhail.pozdnyakov@intel.com>
 
         Remove home-brewed nullptr
index 3f8c378..74a788c 100644 (file)
@@ -99,7 +99,7 @@ namespace WTF {
         // replaces value but not key if key is already present
         // return value is a pair of the iterator to the key location, 
         // and a boolean that's true if a new value was actually added
-        AddResult set(const KeyType&, MappedPassInType);
+        template<typename V> AddResult set(const KeyType&, V&&);
 
         // does nothing if key is already present
         // return value is a pair of the iterator to the key location, 
@@ -134,7 +134,8 @@ namespace WTF {
         static bool isValidKey(const KeyType&);
 
     private:
-        AddResult inlineAdd(const KeyType&, MappedPassInReferenceType);
+        template<typename T>
+        AddResult inlineAdd(const KeyType&, T&&);
 
         HashTableType m_impl;
     };
@@ -226,10 +227,10 @@ namespace WTF {
     struct HashMapTranslator {
         template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); }
         template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); }
-        template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped)
+        template<typename T, typename U, typename V> static void translate(T& location, const U& key, V&& mapped)
         {
             location.key = key;
-            ValueTraits::ValueTraits::store(mapped, location.value);
+            location.value = std::forward<V>(mapped);
         }
     };
 
@@ -333,19 +334,21 @@ namespace WTF {
         return m_impl.template contains<HashMapTranslatorAdapter<ValueTraits, HashTranslator>>(value);
     }
 
-    template<typename T, typename U, typename V, typename W, typename X>
-    auto HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, MappedPassInReferenceType mapped) -> AddResult
+    template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
+    template<typename T>
+    auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::inlineAdd(const KeyType& key, T&& mapped) -> AddResult
     {
-        return m_impl.template add<HashMapTranslator<ValueTraits, HashFunctions>>(key, mapped);
+        return m_impl.template add<HashMapTranslator<ValueTraits, HashFunctions>>(key, std::forward<T>(mapped));
     }
 
-    template<typename T, typename U, typename V, typename W, typename X>
-    auto HashMap<T, U, V, W, X>::set(const KeyType& key, MappedPassInType mapped) -> AddResult
+    template<typename KeyArg, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg>
+    template<typename T>
+    auto HashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>::set(const KeyType& key, T&& mapped) -> AddResult
     {
-        AddResult result = inlineAdd(key, mapped);
+        AddResult result = inlineAdd(key, std::forward<T>(mapped));
         if (!result.isNewEntry) {
             // The inlineAdd call above found an existing hash table entry; we need to set the mapped value.
-            MappedTraits::store(mapped, result.iterator->value);
+            result.iterator->value = std::forward<T>(mapped);
         }
         return result;
     }
index 05f656b..8fde1c2 100644 (file)
@@ -201,16 +201,17 @@ namespace WTF {
         {
         }
 
-        KeyValuePair(const KeyTypeArg& key, const ValueTypeArg& value)
-            : key(key)
-            , value(value)
+        template<typename K, typename V>
+        KeyValuePair(K&& key, V&& value)
+            : key(std::forward<K>(key))
+            , value(std::forward<V>(value))
         {
         }
 
         template <typename OtherKeyType, typename OtherValueType>
-        KeyValuePair(const KeyValuePair<OtherKeyType, OtherValueType>& other)
-            : key(other.key)
-            , value(other.value)
+        KeyValuePair(KeyValuePair<OtherKeyType, OtherValueType>&& other)
+            : key(std::forward<OtherKeyType>(other.key))
+            , value(std::forward<OtherValueType>(other.value))
         {
         }
 
index 5286572..41ae312 100644 (file)
@@ -1,3 +1,14 @@
+2013-09-12  Anders Carlsson  <andersca@apple.com>
+
+        Add rudimentary support for move-only types as values in HashMap
+        https://bugs.webkit.org/show_bug.cgi?id=121226
+
+        Reviewed by Andreas Kling.
+
+        * TestWebKitAPI/Tests/WTF/HashMap.cpp:
+        (TestWebKitAPI::TEST):
+        Add a HashMap<unsigned, MoveOnly> test.
+
 2013-09-12  Gabor Abraham  <abrhm@inf.u-szeged.hu>
 
         Auto GDB backtrace generation for EFL/GTK/Qt bots.
index db6ca81..ec13334 100644 (file)
 
 #include "config.h"
 
+#include "MoveOnly.h"
 #include <wtf/HashMap.h>
 
 namespace TestWebKitAPI {
 
 typedef WTF::HashMap<int, int> IntHashMap;
 
-TEST(WTF, HashTableIteratorComparison)
+TEST(WTF_HashMap, HashTableIteratorComparison)
 {
     IntHashMap map;
     map.add(1, 2);
@@ -60,7 +61,7 @@ static int bucketForKey(double key)
     return DefaultHash<double>::Hash::hash(key) & (TestDoubleHashTraits::minimumTableSize - 1);
 }
 
-TEST(WTF, DoubleHashCollisions)
+TEST(WTF_HashMap, DoubleHashCollisions)
 {
     // The "clobber" key here is one that ends up stealing the bucket that the -0 key
     // originally wants to be in. This makes the 0 and -0 keys collide and the test then
@@ -81,4 +82,24 @@ TEST(WTF, DoubleHashCollisions)
     ASSERT_EQ(map.get(negativeZeroKey), 3);
 }
 
+TEST(WTF_HashMap, MoveOnly)
+{
+    HashMap<unsigned, MoveOnly> moveOnlyValues;
+
+    for (size_t i = 0; i < 100; ++i) {
+        MoveOnly moveOnly(i + 1);
+        moveOnlyValues.set(i + 1, std::move(moveOnly));
+    }
+
+    for (size_t i = 0; i < 100; ++i) {
+        auto it = moveOnlyValues.find(i + 1);
+        ASSERT_FALSE(it == moveOnlyValues.end());
+    }
+
+    for (size_t i = 0; i < 100; ++i)
+        ASSERT_TRUE(moveOnlyValues.remove(i + 1));
+
+    ASSERT_TRUE(moveOnlyValues.isEmpty());
+}
+
 } // namespace TestWebKitAPI