Changeset 242387 in webkit
- Timestamp:
- Mar 4, 2019, 1:52:32 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 10 edited
-
Source/WTF/ChangeLog (modified) (1 diff)
-
Source/WTF/WTF.xcodeproj/project.pbxproj (modified) (2 diffs)
-
Source/WTF/wtf/CMakeLists.txt (modified) (1 diff)
-
Source/WTF/wtf/Forward.h (modified) (1 diff)
-
Source/WTF/wtf/HashSet.h (modified) (2 diffs)
-
Source/WTF/wtf/HashTable.h (modified) (6 diffs)
-
Source/WTF/wtf/HashTraits.h (modified) (4 diffs)
-
Source/WTF/wtf/WeakHashSet.h (added)
-
Source/WTF/wtf/WeakPtr.h (modified) (3 diffs)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r242360 r242387 1 2019-02-28 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add WeakHashSet 4 https://bugs.webkit.org/show_bug.cgi?id=195152 5 6 Reviewed by Antti Koivisto. 7 8 Added WeakHashSet which is a HashSet of WeakPtr. When the object pointed by WeakPtr is deleted, 9 WeakHashSet treats the key to be no longer in the set. That is, WeakHashSet::contains returns false 10 and const_iterator skips such a WeakPtr in the set. 11 12 We decided not to make HashSet<WeahPtr<T>> work because it involves weird semantics such as making 13 find(X) delete the table entry as remove(find(X)) would be a no-op otherwise as find(X) would return 14 necessarily need to return HashSet<WeakPtr<T>>::end(). 15 16 Furthermore, we cannot determine the true size of this set in O(1) because the objected pointed by 17 some of WeakPtr in the set may have already been deleted. This has implications that we can't have 18 size(), isEmpty(), random(), etc... as O(1) operation. 19 20 WeakHashSet is implemented as HashSet<WeakReference<T>>. HashTable::rehash has been updated to delete 21 WeakReference<T>'s whose m_ptr has become null, and HashTable::expand first deletes any such entry 22 before deciding an actual expansion is needed. This is accomplished via newly added hash trait, 23 hasIsReleasedWeakValueFunction, and HashTraits<Ref<WeakReference<T>>>::isReleasedWeakValue which 24 returns true for when WeakReference<T> pointed by Ref<WeakReference<T>> has null m_ptr, not to be 25 confused with Ref<WeakReference<T>> itself pointing to a null WeakReference<T>. 26 27 * WTF.xcodeproj/project.pbxproj: 28 * wtf/CMakeLists.txt: 29 * wtf/Forward.h: 30 * wtf/HashSet.h: 31 (WTF::HashSet<T, U, V>::checkConsistency const): Added. 32 * wtf/HashTable.h: 33 (WTF::HashTable::isReleasedWeakBucket): Added. 34 (WTF::HashTable::expand): Delete WeakReference<T> with null m_ptr first. This updates m_keyCount 35 and may make mustRehashInPlace() return true. 36 (WTF::HashTable::deleteReleasedWeakBuckets): Added. 37 (WTF::HashTable::rehash): Delete WeakReference<T> with null m_ptr. Also refactored the code a bit 38 to avoid keep repeating oldTable[i]. 39 * wtf/HashTraits.h: 40 (WTF::HashTraits<T>::isHashTraitsReleasedWeakValue): Added. 41 (WTF::RefHashTraits<T>): Extracted from HashTraits<Ref<P>> to share code with 42 HashTraits<Ref<WeakReference<T>>>. 43 (WTF::HashTraitsReleasedWeakValueChecker<Traits, hasIsReleasedWeakValueFunction>): Added. 44 (WTF::isHashTraitsReleasedWeakValue<Traits, hasIsReleasedWeakValueFunction>): Added. 45 * wtf/WeakHashSet.h: Added. 46 (WTF::WeakHashSet): Added. 47 (WTF::WeakHashSet::WeakHashSetConstIterator::WeakHashSetConstIterator): 48 (WTF::WeakHashSet::WeakHashSetConstIterator::get const): 49 (WTF::WeakHashSet::WeakHashSetConstIterator::operator* const): 50 (WTF::WeakHashSet::WeakHashSetConstIterator::operator-> const): 51 (WTF::WeakHashSet::WeakHashSetConstIterator::operator++): 52 (WTF::WeakHashSet::WeakHashSetConstIterator::skipEmptyBuckets): 53 (WTF::WeakHashSet::WeakHashSetConstIterator::operator== const): 54 (WTF::WeakHashSet::WeakHashSetConstIterator::operator!= const): 55 (WTF::WeakHashSet::WeakHashSet): 56 (WTF::WeakHashSet::begin const): 57 (WTF::WeakHashSet::end const): 58 (WTF::WeakHashSet::add): 59 (WTF::WeakHashSet::remove): 60 (WTF::WeakHashSet::contains const): 61 (WTF::WeakHashSet::capacity const): 62 (WTF::WeakHashSet::computeSize const): Deletes any WeakReference<T> with null m_ptr first. 63 (WTF::WeakHashSet::checkConsistency const): 64 (WTF::HashTraits<Ref<WeakReference<T>>>): Added. This hash traits triggers the new code in HashTable's 65 expand and rehash methods to delete WeakReference<T> with null m_ptr. 66 (WTF::HashTraits<Ref<WeakReference<T>>>::isReleasedWeakValue): 67 * wtf/WeakPtr.h: 68 (WTF::WeakReference::~WeakReference): Added so that we can keep track the number of live WeakReference 69 in API tests by template specializations. 70 1 71 2019-03-03 Darin Adler <darin@apple.com> 2 72 -
trunk/Source/WTF/WTF.xcodeproj/project.pbxproj
r242330 r242387 440 440 974CFC8D16A4F327006D5404 /* WeakPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakPtr.h; sourceTree = "<group>"; }; 441 441 996B17841EBA441C007E10EB /* DebugUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebugUtilities.h; sourceTree = "<group>"; }; 442 9B67F3F12228D5310030DE9C /* WeakHashSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WeakHashSet.h; sourceTree = "<group>"; }; 442 443 9BC70F04176C379D00101DEC /* AtomicStringTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AtomicStringTable.cpp; sourceTree = "<group>"; }; 443 444 9BD8F40A176C2AD80002D865 /* AtomicStringTable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AtomicStringTable.h; sourceTree = "<group>"; }; … … 1184 1185 0F66B2881DC97BAB004A1D3F /* WallTime.cpp */, 1185 1186 0F66B2891DC97BAB004A1D3F /* WallTime.h */, 1187 9B67F3F12228D5310030DE9C /* WeakHashSet.h */, 1186 1188 83ABB3C020B3823200BA3306 /* WeakObjCPtr.h */, 1187 1189 974CFC8D16A4F327006D5404 /* WeakPtr.h */, -
trunk/Source/WTF/wtf/CMakeLists.txt
r242330 r242387 259 259 WTFSemaphore.h 260 260 WallTime.h 261 WeakHashSet.h 261 262 WeakPtr.h 262 263 WeakRandom.h -
trunk/Source/WTF/wtf/Forward.h
r238771 r242387 60 60 template<typename> class StringBuffer; 61 61 template<typename, typename = void> class StringTypeAdapter; 62 template<typename T> class WeakPtr; 62 63 63 64 template<typename> struct DefaultHash { using Hash = void; }; -
trunk/Source/WTF/wtf/HashSet.h
r237461 r242387 128 128 bool operator!=(const OtherCollection&) const; 129 129 130 void checkConsistency() const; 131 130 132 private: 131 133 HashTableType m_impl; … … 383 385 } 384 386 387 template<typename T, typename U, typename V> 388 inline void HashSet<T, U, V>::checkConsistency() const 389 { 390 m_impl.checkTableConsistency(); 391 } 392 385 393 } // namespace WTF 386 394 -
trunk/Source/WTF/wtf/HashTable.h
r237522 r242387 425 425 426 426 static bool isEmptyBucket(const ValueType& value) { return isHashTraitsEmptyValue<KeyTraits>(Extractor::extract(value)); } 427 static bool isReleasedWeakBucket(const ValueType& value) { return isHashTraitsReleasedWeakValue<KeyTraits>(Extractor::extract(value)); } 427 428 static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); } 428 429 static bool isEmptyOrDeletedBucket(const ValueType& value) { return isEmptyBucket(value) || isDeletedBucket(value); } … … 469 470 ValueType* expand(ValueType* entry = nullptr); 470 471 void shrink() { rehash(m_tableSize / 2, nullptr); } 472 473 void deleteReleasedWeakBuckets(); 471 474 472 475 ValueType* rehash(unsigned newTableSize, ValueType* entry); … … 1179 1182 auto HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::expand(ValueType* entry) -> ValueType* 1180 1183 { 1184 if (KeyTraits::hasIsReleasedWeakValueFunction) 1185 deleteReleasedWeakBuckets(); 1186 1181 1187 unsigned newSize; 1182 1188 if (m_tableSize == 0) … … 1191 1197 1192 1198 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> 1199 void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::deleteReleasedWeakBuckets() 1200 { 1201 for (unsigned i = 0; i < m_tableSize; ++i) { 1202 auto& entry = m_table[i]; 1203 if (isReleasedWeakBucket(entry)) { 1204 deleteBucket(entry); 1205 ++m_deletedCount; 1206 --m_keyCount; 1207 } 1208 } 1209 } 1210 1211 template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> 1193 1212 auto HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::rehash(unsigned newTableSize, ValueType* entry) -> ValueType* 1194 1213 { … … 1214 1233 Value* newEntry = nullptr; 1215 1234 for (unsigned i = 0; i != oldTableSize; ++i) { 1216 if (isDeletedBucket(oldTable[i])) { 1217 ASSERT(std::addressof(oldTable[i]) != entry); 1235 auto& oldEntry = oldTable[i]; 1236 if (isDeletedBucket(oldEntry)) { 1237 ASSERT(std::addressof(oldEntry) != entry); 1218 1238 continue; 1219 1239 } 1220 1240 1221 if (isEmptyBucket(old Table[i])) {1222 ASSERT(std::addressof(old Table[i]) != entry);1241 if (isEmptyBucket(oldEntry)) { 1242 ASSERT(std::addressof(oldEntry) != entry); 1223 1243 oldTable[i].~ValueType(); 1224 1244 continue; 1225 1245 } 1226 1246 1227 Value* reinsertedEntry = reinsert(WTFMove(oldTable[i])); 1228 oldTable[i].~ValueType(); 1229 if (std::addressof(oldTable[i]) == entry) { 1247 if (isReleasedWeakBucket(oldEntry)) { 1248 ASSERT(std::addressof(oldEntry) != entry); 1249 oldEntry.~ValueType(); 1250 --m_keyCount; 1251 continue; 1252 } 1253 1254 Value* reinsertedEntry = reinsert(WTFMove(oldEntry)); 1255 oldEntry.~ValueType(); 1256 if (std::addressof(oldEntry) == entry) { 1230 1257 ASSERT(!newEntry); 1231 1258 newEntry = reinsertedEntry; … … 1382 1409 } 1383 1410 1384 const_iterator it = find(Extractor::extract(*entry)); 1411 auto& key = Extractor::extract(*entry); 1412 const_iterator it = find(key); 1385 1413 ASSERT(entry == it.m_position); 1386 1414 ++count; 1387 1415 1388 ValueCheck<Key>::checkConsistency( it->key);1416 ValueCheck<Key>::checkConsistency(key); 1389 1417 } 1390 1418 -
trunk/Source/WTF/wtf/HashTraits.h
r239427 r242387 40 40 // The emptyValueIsZero flag is used to optimize allocation of empty hash tables with zeroed memory. 41 41 static const bool emptyValueIsZero = false; 42 42 43 43 // The hasIsEmptyValueFunction flag allows the hash table to automatically generate code to check 44 44 // for the empty value when it can be done with the equality operator, but allows custom functions 45 45 // for cases like String that need them. 46 46 static const bool hasIsEmptyValueFunction = false; 47 48 // Used by WeakPtr to indicate that the value may become deleted without being explicitly removed. 49 static const bool hasIsReleasedWeakValueFunction = false; 47 50 48 51 // The starting table size. Can be overridden when we know beforehand that … … 193 196 }; 194 197 195 template<typename P> struct HashTraits<Ref<P>>: SimpleClassHashTraits<Ref<P>> {198 template<typename P> struct RefHashTraits : SimpleClassHashTraits<Ref<P>> { 196 199 static const bool emptyValueIsZero = true; 197 200 static Ref<P> emptyValue() { return HashTableEmptyValue; } … … 215 218 static TakeType take(Ref<P>&& value) { return isEmptyValue(value) ? WTF::nullopt : Optional<Ref<P>>(WTFMove(value)); } 216 219 }; 220 221 template<typename P> struct HashTraits<Ref<P>> : RefHashTraits<P> { }; 217 222 218 223 template<> struct HashTraits<String> : SimpleClassHashTraits<String> { … … 235 240 { 236 241 return HashTraitsEmptyValueChecker<Traits, Traits::hasIsEmptyValueFunction>::isEmptyValue(value); 242 } 243 244 template<typename Traits, bool hasIsReleasedWeakValueFunction> struct HashTraitsReleasedWeakValueChecker; 245 template<typename Traits> struct HashTraitsReleasedWeakValueChecker<Traits, true> { 246 template<typename T> static bool isReleasedWeakValue(const T& value) { return Traits::isReleasedWeakValue(value); } 247 }; 248 template<typename Traits> struct HashTraitsReleasedWeakValueChecker<Traits, false> { 249 template<typename T> static bool isReleasedWeakValue(const T&) { return false; } 250 }; 251 template<typename Traits, typename T> inline bool isHashTraitsReleasedWeakValue(const T& value) 252 { 253 return HashTraitsReleasedWeakValueChecker<Traits, Traits::hasIsReleasedWeakValueFunction>::isReleasedWeakValue(value); 237 254 } 238 255 -
trunk/Source/WTF/wtf/WeakPtr.h
r237099 r242387 43 43 WTF_MAKE_FAST_ALLOCATED; 44 44 public: 45 ~WeakReference() { } // So that we can use a template specialization for testing purposes to detect leaks. 46 45 47 T* get() const { return m_ptr; } 46 48 … … 84 86 85 87 private: 88 template<typename U> friend class WeakHashSet; 86 89 template<typename U> friend class WeakPtr; 87 90 template<typename U> friend WeakPtr<U> makeWeakPtr(U&); … … 128 131 129 132 private: 133 template<typename U> friend class WeakHashSet; 134 130 135 mutable RefPtr<WeakReference<T>> m_ref; 131 136 }; -
trunk/Tools/ChangeLog
r242371 r242387 1 2019-02-28 Ryosuke Niwa <rniwa@webkit.org> 2 3 Add WeakHashSet 4 https://bugs.webkit.org/show_bug.cgi?id=195152 5 6 Reviewed by Antti Koivisto. 7 8 Added tests for WeakHashSet. 9 10 * TestWebKitAPI/Tests/WTF/WeakPtr.cpp: 11 (TestWebKitAPI::Base::Base): Moved. 12 (TestWebKitAPI::Derived::foo): Moved. 13 (WTF::WeakReference<TestWebKitAPI::Base>): Added to track the number of live WeakReference. 14 (WTF::WeakReference<TestWebKitAPI::Base>::WeakReference): 15 (WTF::WeakReference<TestWebKitAPI::Base>::~WeakReference): 16 (TestWebKitAPI::computeSizeOfWeakHashSet): Added. 17 1 18 2019-03-04 Chris Dumez <cdumez@apple.com> 2 19 -
trunk/Tools/TestWebKitAPI/Tests/WTF/WeakPtr.cpp
r235315 r242387 27 27 28 28 #include "Test.h" 29 #include <wtf/HashSet.h> 30 #include <wtf/WeakHashSet.h> 29 31 #include <wtf/WeakPtr.h> 32 33 static unsigned s_baseWeakReferences = 0; 34 35 namespace TestWebKitAPI { 36 37 class Base { 38 public: 39 Base() { } 40 41 int foo() 42 { 43 return 0; 44 } 45 46 auto& weakPtrFactory() const { return m_weakPtrFactory; } 47 48 private: 49 WeakPtrFactory<Base> m_weakPtrFactory; 50 }; 51 52 class Derived : public Base { 53 public: 54 Derived() { } 55 56 int foo() 57 { 58 return 1; 59 } 60 }; 61 62 } 63 64 namespace WTF { 65 66 template<> 67 WeakReference<TestWebKitAPI::Base>::WeakReference(TestWebKitAPI::Base* ptr) 68 : m_ptr(ptr) 69 { 70 ++s_baseWeakReferences; 71 } 72 template<> 73 WeakReference<TestWebKitAPI::Base>::~WeakReference() 74 { 75 --s_baseWeakReferences; 76 } 77 78 } 30 79 31 80 namespace TestWebKitAPI { … … 200 249 } 201 250 202 class Base {203 public:204 Base() { }205 206 int foo()207 {208 return 0;209 }210 211 auto& weakPtrFactory() const { return m_weakPtrFactory; }212 213 private:214 WeakPtrFactory<Base> m_weakPtrFactory;215 };216 217 class Derived : public Base {218 public:219 Derived() { }220 221 int foo()222 {223 return 1;224 }225 };226 227 251 TEST(WTF_WeakPtr, Downcasting) 228 252 { … … 323 347 } 324 348 349 template <typename T> 350 unsigned computeSizeOfWeakHashSet(const HashSet<WeakPtr<T>>& set) 351 { 352 unsigned size = 0; 353 for (auto& item : set) { 354 UNUSED_PARAM(item); 355 size++; 356 } 357 return size; 358 } 359 360 template <typename T> 361 unsigned computeSizeOfWeakHashSet(const WeakHashSet<T>& set) 362 { 363 unsigned size = 0; 364 for (auto& item : set) { 365 UNUSED_PARAM(item); 366 size++; 367 } 368 return size; 369 } 370 371 TEST(WTF_WeakPtr, WeakHashSetBasic) 372 { 373 { 374 WeakHashSet<Base> weakHashSet; 375 Base object; 376 EXPECT_FALSE(weakHashSet.contains(object)); 377 EXPECT_EQ(s_baseWeakReferences, 0u); 378 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u); 379 weakHashSet.add(object); 380 EXPECT_EQ(s_baseWeakReferences, 1u); 381 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 382 EXPECT_TRUE(weakHashSet.contains(object)); 383 weakHashSet.add(object); 384 EXPECT_TRUE(weakHashSet.contains(object)); 385 EXPECT_EQ(s_baseWeakReferences, 1u); 386 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 387 weakHashSet.checkConsistency(); 388 } 389 EXPECT_EQ(s_baseWeakReferences, 0u); 390 391 { 392 WeakHashSet<Base> weakHashSet; 393 Derived object; 394 EXPECT_FALSE(weakHashSet.contains(object)); 395 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u); 396 EXPECT_EQ(s_baseWeakReferences, 0u); 397 weakHashSet.add(object); 398 EXPECT_TRUE(weakHashSet.contains(object)); 399 EXPECT_EQ(s_baseWeakReferences, 1u); 400 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 401 weakHashSet.add(object); 402 EXPECT_TRUE(weakHashSet.contains(object)); 403 EXPECT_EQ(s_baseWeakReferences, 1u); 404 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 405 weakHashSet.checkConsistency(); 406 } 407 EXPECT_EQ(s_baseWeakReferences, 0u); 408 409 { 410 WeakHashSet<Base> weakHashSet; 411 { 412 Base object; 413 EXPECT_FALSE(weakHashSet.contains(object)); 414 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u); 415 EXPECT_EQ(s_baseWeakReferences, 0u); 416 weakHashSet.add(object); 417 EXPECT_TRUE(weakHashSet.contains(object)); 418 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 419 EXPECT_EQ(s_baseWeakReferences, 1u); 420 } 421 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u); 422 weakHashSet.checkConsistency(); 423 } 424 EXPECT_EQ(s_baseWeakReferences, 0u); 425 426 { 427 WeakHashSet<Base> weakHashSet; 428 { 429 Base object1; 430 Base object2; 431 EXPECT_FALSE(weakHashSet.contains(object1)); 432 EXPECT_FALSE(weakHashSet.contains(object2)); 433 EXPECT_EQ(s_baseWeakReferences, 0u); 434 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u); 435 weakHashSet.add(object1); 436 EXPECT_TRUE(weakHashSet.contains(object1)); 437 EXPECT_FALSE(weakHashSet.contains(object2)); 438 EXPECT_EQ(s_baseWeakReferences, 1u); 439 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 440 weakHashSet.add(object2); 441 EXPECT_TRUE(weakHashSet.contains(object1)); 442 EXPECT_TRUE(weakHashSet.contains(object2)); 443 EXPECT_EQ(s_baseWeakReferences, 2u); 444 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 2u); 445 weakHashSet.remove(object1); 446 EXPECT_FALSE(weakHashSet.contains(object1)); 447 EXPECT_TRUE(weakHashSet.contains(object2)); 448 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 449 } 450 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u); 451 weakHashSet.checkConsistency(); 452 } 453 EXPECT_EQ(s_baseWeakReferences, 0u); 454 455 { 456 WeakHashSet<Base> weakHashSet; 457 Base object1; 458 Base object2; 459 Base object3; 460 EXPECT_FALSE(weakHashSet.contains(object1)); 461 EXPECT_FALSE(weakHashSet.contains(object2)); 462 EXPECT_FALSE(weakHashSet.contains(object3)); 463 EXPECT_EQ(s_baseWeakReferences, 0u); 464 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u); 465 weakHashSet.add(object1); 466 weakHashSet.add(object2); 467 EXPECT_TRUE(weakHashSet.contains(object1)); 468 EXPECT_TRUE(weakHashSet.contains(object2)); 469 EXPECT_FALSE(weakHashSet.contains(object3)); 470 EXPECT_EQ(s_baseWeakReferences, 2u); 471 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 2u); 472 weakHashSet.remove(object1); 473 EXPECT_FALSE(weakHashSet.contains(object1)); 474 EXPECT_TRUE(weakHashSet.contains(object2)); 475 EXPECT_FALSE(weakHashSet.contains(object3)); 476 EXPECT_EQ(s_baseWeakReferences, 2u); // Because object2 holds onto WeakReference. 477 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 478 weakHashSet.remove(object3); 479 EXPECT_FALSE(weakHashSet.contains(object1)); 480 EXPECT_TRUE(weakHashSet.contains(object2)); 481 EXPECT_FALSE(weakHashSet.contains(object3)); 482 EXPECT_EQ(s_baseWeakReferences, 2u); 483 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 484 weakHashSet.add(object2); 485 EXPECT_FALSE(weakHashSet.contains(object1)); 486 EXPECT_TRUE(weakHashSet.contains(object2)); 487 EXPECT_FALSE(weakHashSet.contains(object3)); 488 EXPECT_EQ(s_baseWeakReferences, 2u); 489 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 1u); 490 weakHashSet.checkConsistency(); 491 } 492 EXPECT_EQ(s_baseWeakReferences, 0u); 493 } 494 495 TEST(WTF_WeakPtr, WeakHashSetExpansion) 496 { 497 unsigned initialCapacity; 498 const static unsigned maxLoadCap = 3; 499 { 500 WeakHashSet<Base> weakHashSet; 501 Base object; 502 EXPECT_EQ(s_baseWeakReferences, 0u); 503 weakHashSet.add(object); 504 EXPECT_EQ(s_baseWeakReferences, 1u); 505 initialCapacity = weakHashSet.capacity(); 506 } 507 EXPECT_EQ(s_baseWeakReferences, 0u); 508 509 for (unsigned i = 0; i < 1; ++i) { 510 WeakHashSet<Base> weakHashSet; 511 Vector<std::unique_ptr<Base>> objects; 512 Vector<std::unique_ptr<Base>> otherObjects; 513 514 EXPECT_EQ(weakHashSet.capacity(), 0u); 515 EXPECT_TRUE(initialCapacity / maxLoadCap); 516 for (unsigned i = 0; i < initialCapacity / maxLoadCap; ++i) { 517 auto object = std::make_unique<Base>(); 518 weakHashSet.add(*object); 519 objects.append(WTFMove(object)); 520 otherObjects.append(std::make_unique<Base>()); 521 weakHashSet.checkConsistency(); 522 } 523 EXPECT_EQ(s_baseWeakReferences, otherObjects.size()); 524 EXPECT_EQ(weakHashSet.capacity(), initialCapacity); 525 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), objects.size()); 526 for (unsigned i = 0; i < otherObjects.size(); ++i) { 527 EXPECT_TRUE(weakHashSet.contains(*objects[i])); 528 EXPECT_FALSE(weakHashSet.contains(*otherObjects[i])); 529 } 530 objects.clear(); 531 weakHashSet.checkConsistency(); 532 EXPECT_EQ(s_baseWeakReferences, otherObjects.size()); 533 EXPECT_EQ(weakHashSet.capacity(), initialCapacity); 534 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u); 535 for (auto& object : otherObjects) 536 EXPECT_FALSE(weakHashSet.contains(*object)); 537 for (auto& object : otherObjects) { 538 weakHashSet.add(*object); 539 weakHashSet.checkConsistency(); 540 } 541 EXPECT_EQ(weakHashSet.capacity(), initialCapacity); 542 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), otherObjects.size()); 543 for (auto& object : otherObjects) 544 EXPECT_TRUE(weakHashSet.contains(*object)); 545 } 546 EXPECT_EQ(s_baseWeakReferences, 0u); 547 548 for (unsigned i = 0; i < 10; ++i) { 549 WeakHashSet<Base> weakHashSet; 550 Vector<std::unique_ptr<Base>> objects; 551 EXPECT_EQ(weakHashSet.capacity(), 0u); 552 unsigned objectCount = initialCapacity * 2; 553 for (unsigned i = 0; i < objectCount; ++i) { 554 auto object = std::make_unique<Base>(); 555 weakHashSet.add(*object); 556 objects.append(WTFMove(object)); 557 weakHashSet.checkConsistency(); 558 } 559 unsigned originalCapacity = weakHashSet.capacity(); 560 EXPECT_EQ(s_baseWeakReferences, objects.size()); 561 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), objects.size()); 562 for (auto& object : objects) 563 EXPECT_TRUE(weakHashSet.contains(*object)); 564 objects.clear(); 565 weakHashSet.checkConsistency(); 566 EXPECT_EQ(s_baseWeakReferences, objectCount); 567 EXPECT_EQ(weakHashSet.capacity(), originalCapacity); 568 EXPECT_EQ(computeSizeOfWeakHashSet(weakHashSet), 0u); 569 } 570 } 571 325 572 } // namespace TestWebKitAPI
Note:
See TracChangeset
for help on using the changeset viewer.