Minimize SkTHash object copying

AKA ref-constify the world.

R=mtklein@google.com

Review URL: https://codereview.chromium.org/919193002
diff --git a/tests/HashTest.cpp b/tests/HashTest.cpp
index 3dd2df4..00857f6 100644
--- a/tests/HashTest.cpp
+++ b/tests/HashTest.cpp
@@ -3,7 +3,7 @@
 #include "SkTHash.h"
 #include "Test.h"
 
-namespace { uint32_t hash_int(int k) { return SkChecksum::Mix(k); } }
+namespace { uint32_t hash_int(const int& k) { return SkChecksum::Mix(k); } }
 
 static void set_negative_key(int key, double* d) { *d = -key; }
 
@@ -41,7 +41,7 @@
     REPORTER_ASSERT(r, map.count() == N);
 }
 
-namespace { uint32_t hash_string(SkString s) { return (uint32_t)s.size(); } }
+namespace { uint32_t hash_string(const SkString& s) { return SkToInt(s.size()); } }
 
 DEF_TEST(HashSet, r) {
     SkTHashSet<SkString, hash_string> set;
@@ -55,3 +55,66 @@
     REPORTER_ASSERT(r, set.contains(SkString("World")));
     REPORTER_ASSERT(r, !set.contains(SkString("Goodbye")));
 }
+
+namespace {
+
+class CopyCounter {
+public:
+    CopyCounter() : fID(0), fCounter(NULL) {}
+
+    CopyCounter(uint32_t id, uint32_t* counter) : fID(id), fCounter(counter) {}
+
+    CopyCounter(const CopyCounter& other)
+        : fID(other.fID)
+        , fCounter(other.fCounter) {
+        SkASSERT(fCounter);
+        *fCounter += 1;
+    }
+
+    void operator=(const CopyCounter& other) {
+        fID = other.fID;
+        fCounter = other.fCounter;
+        *fCounter += 1;
+    }
+
+    bool operator==(const CopyCounter& other) const {
+        return fID == other.fID;
+    }
+
+private:
+    uint32_t  fID;
+    uint32_t* fCounter;
+};
+
+uint32_t hash_copy_counter(const CopyCounter&) {
+    return 0; // let them collide, what do we care?
+}
+
+}
+
+DEF_TEST(HashSetCopyCounter, r) {
+    SkTHashSet<CopyCounter, hash_copy_counter> set;
+
+    uint32_t globalCounter = 0;
+    CopyCounter copyCounter1(1, &globalCounter);
+    CopyCounter copyCounter2(2, &globalCounter);
+    REPORTER_ASSERT(r, globalCounter == 0);
+
+    set.add(copyCounter1);
+    REPORTER_ASSERT(r, globalCounter == 1);
+    REPORTER_ASSERT(r, set.contains(copyCounter1));
+    REPORTER_ASSERT(r, globalCounter == 1);
+    set.add(copyCounter1);
+    // We allow copies for same-value adds for now.
+    REPORTER_ASSERT(r, globalCounter == 2);
+
+    set.add(copyCounter2);
+    REPORTER_ASSERT(r, globalCounter == 3);
+    REPORTER_ASSERT(r, set.contains(copyCounter1));
+    REPORTER_ASSERT(r, set.contains(copyCounter2));
+    REPORTER_ASSERT(r, globalCounter == 3);
+    set.add(copyCounter1);
+    set.add(copyCounter2);
+    // We allow copies for same-value adds for now.
+    REPORTER_ASSERT(r, globalCounter == 5);
+}