Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(12)

Side by Side Diff: third_party/WebKit/Source/wtf/HashMapTest.cpp

Issue 1764973002: WTF::HashTable: Implement move semantics for keys and values. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved. 2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 295
296 TEST(HashMapTest, ValueTypeDestructed) 296 TEST(HashMapTest, ValueTypeDestructed)
297 { 297 {
298 InstanceCounter::counter = 0; 298 InstanceCounter::counter = 0;
299 HashMap<int, InstanceCounter> map; 299 HashMap<int, InstanceCounter> map;
300 map.set(1, InstanceCounter()); 300 map.set(1, InstanceCounter());
301 map.clear(); 301 map.clear();
302 EXPECT_EQ(0, InstanceCounter::counter); 302 EXPECT_EQ(0, InstanceCounter::counter);
303 } 303 }
304 304
305 class MoveOnly {
306 public:
307 // kEmpty and kDeleted have special meanings when MoveOnly is used as the ke y of a hash table.
308 enum {
309 kEmpty = 0,
310 kDeleted = -1,
311 kMovedOut = -2
312 };
313
314 explicit MoveOnly(int value = kEmpty) : m_value(value) { }
315 MoveOnly(MoveOnly&& other)
316 : m_value(other.m_value)
317 {
318 other.m_value = kMovedOut;
319 }
320 MoveOnly& operator=(MoveOnly&& other)
321 {
322 m_value = other.m_value;
323 other.m_value = kMovedOut;
324 return *this;
325 }
326
327 int value() const { return m_value; }
328
329 private:
330 MoveOnly(const MoveOnly&) = delete;
331 MoveOnly& operator=(const MoveOnly&) = delete;
332
333 int m_value;
334 };
335
336 struct MoveOnlyHashTraits : public GenericHashTraits<MoveOnly> {
337 // This is actually true, but we pretend that it's false to disable the opti mization.
338 static const bool emptyValueIsZero = false;
339
340 static const bool hasIsEmptyValueFunction = true;
341 static bool isEmptyValue(const MoveOnly& value) { return value.value() == Mo veOnly::kEmpty; }
342 static void constructDeletedValue(MoveOnly& slot, bool) { slot = MoveOnly(Mo veOnly::kDeleted); }
343 static bool isDeletedValue(const MoveOnly& value) { return value.value() == MoveOnly::kDeleted; }
344 };
345
346 struct MoveOnlyHash {
347 static unsigned hash(const MoveOnly& value) { return DefaultHash<int>::Hash: :hash(value.value()); }
348 static bool equal(const MoveOnly& left, const MoveOnly& right)
349 {
350 return DefaultHash<int>::Hash::equal(left.value(), right.value());
351 }
352 static const bool safeToCompareToEmptyOrDeleted = true;
353 };
354
355 } // anonymous namespace
356
357 template <>
358 struct HashTraits<MoveOnly> : public MoveOnlyHashTraits { };
359
360 template <>
361 struct DefaultHash<MoveOnly> {
362 using Hash = MoveOnlyHash;
363 };
364
365 namespace {
366
367 TEST(HashMapTest, MoveOnlyValueType)
368 {
369 using TheMap = HashMap<int, MoveOnly>;
370 TheMap map;
371 {
372 TheMap::AddResult addResult = map.add(1, MoveOnly(10));
373 EXPECT_TRUE(addResult.isNewEntry);
374 EXPECT_EQ(1, addResult.storedValue->key);
375 EXPECT_EQ(10, addResult.storedValue->value.value());
376 }
377 auto iter = map.find(1);
378 ASSERT_TRUE(iter != map.end());
379 EXPECT_EQ(1, iter->key);
380 EXPECT_EQ(10, iter->value.value());
381
382 iter = map.find(2);
383 EXPECT_TRUE(iter == map.end());
384
385 // Try to add more to trigger rehashing.
386 for (int i = 2; i < 32; ++i) {
387 TheMap::AddResult addResult = map.add(i, MoveOnly(i * 10));
388 EXPECT_TRUE(addResult.isNewEntry);
389 EXPECT_EQ(i, addResult.storedValue->key);
390 EXPECT_EQ(i * 10, addResult.storedValue->value.value());
391 }
392
393 iter = map.find(1);
394 ASSERT_TRUE(iter != map.end());
395 EXPECT_EQ(1, iter->key);
396 EXPECT_EQ(10, iter->value.value());
397
398 iter = map.find(7);
399 ASSERT_TRUE(iter != map.end());
400 EXPECT_EQ(7, iter->key);
401 EXPECT_EQ(70, iter->value.value());
402
403 {
404 TheMap::AddResult addResult = map.set(9, MoveOnly(999));
405 EXPECT_FALSE(addResult.isNewEntry);
406 EXPECT_EQ(9, addResult.storedValue->key);
407 EXPECT_EQ(999, addResult.storedValue->value.value());
408 }
409
410 map.remove(11);
411 iter = map.find(11);
412 EXPECT_TRUE(iter == map.end());
413
414 MoveOnly oneThirty(map.take(13));
415 EXPECT_EQ(130, oneThirty.value());
416 iter = map.find(13);
417 EXPECT_TRUE(iter == map.end());
418
419 map.clear();
420 }
421
422 TEST(HashMapTest, MoveOnlyKeyType)
423 {
424 // The content of this test is similar to the test above, except that the ty pes of key and value are swapped.
425 using TheMap = HashMap<MoveOnly, int>;
426 TheMap map;
427 {
428 TheMap::AddResult addResult = map.add(MoveOnly(1), 10);
429 EXPECT_TRUE(addResult.isNewEntry);
430 EXPECT_EQ(1, addResult.storedValue->key.value());
431 EXPECT_EQ(10, addResult.storedValue->value);
432 }
433 auto iter = map.find(MoveOnly(1));
434 ASSERT_TRUE(iter != map.end());
435 EXPECT_EQ(1, iter->key.value());
436 EXPECT_EQ(10, iter->value);
437
438 iter = map.find(MoveOnly(2));
439 EXPECT_TRUE(iter == map.end());
440
441 for (int i = 2; i < 32; ++i) {
442 TheMap::AddResult addResult = map.add(MoveOnly(i), i * 10);
443 EXPECT_TRUE(addResult.isNewEntry);
444 EXPECT_EQ(i, addResult.storedValue->key.value());
445 EXPECT_EQ(i * 10, addResult.storedValue->value);
446 }
447
448 iter = map.find(MoveOnly(1));
449 ASSERT_TRUE(iter != map.end());
450 EXPECT_EQ(1, iter->key.value());
451 EXPECT_EQ(10, iter->value);
452
453 iter = map.find(MoveOnly(7));
454 ASSERT_TRUE(iter != map.end());
455 EXPECT_EQ(7, iter->key.value());
456 EXPECT_EQ(70, iter->value);
457
458 {
459 TheMap::AddResult addResult = map.set(MoveOnly(9), 999);
460 EXPECT_FALSE(addResult.isNewEntry);
461 EXPECT_EQ(9, addResult.storedValue->key.value());
462 EXPECT_EQ(999, addResult.storedValue->value);
463 }
464
465 map.remove(MoveOnly(11));
466 iter = map.find(MoveOnly(11));
467 EXPECT_TRUE(iter == map.end());
468
469 int oneThirty = map.take(MoveOnly(13));
470 EXPECT_EQ(130, oneThirty);
471 iter = map.find(MoveOnly(13));
472 EXPECT_TRUE(iter == map.end());
473
474 map.clear();
475 }
476
305 } // anonymous namespace 477 } // anonymous namespace
306 478
307 } // namespace WTF 479 } // namespace WTF
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698