LLVM_ATTRIBUTE_ALWAYS_INLINE static const Metadata *findHashableBaseTypeImpl(const Metadata *type) { // Check the cache first. if (HashableConformanceEntry *entry = HashableConformances.find(HashableConformanceKey{type})) { return entry->baseTypeThatConformsToHashable; } if (!KnownToConformToHashable && !swift_conformsToProtocol(type, &HashableProtocolDescriptor)) { // Don't cache the negative response because we don't invalidate // this cache when a new conformance is loaded dynamically. return nullptr; } // By this point, `type` is known to conform to `Hashable`. const Metadata *baseTypeThatConformsToHashable = type; while (true) { const Metadata *superclass = _swift_class_getSuperclass(baseTypeThatConformsToHashable); if (!superclass) break; if (!swift_conformsToProtocol(superclass, &HashableProtocolDescriptor)) break; baseTypeThatConformsToHashable = superclass; } HashableConformances.getOrInsert(HashableConformanceKey{type}, baseTypeThatConformsToHashable); return baseTypeThatConformsToHashable; }
TEST(Concurrent, ConcurrentMap) { const int numElem = 100; struct Entry { size_t Key; Entry(size_t key) : Key(key) {} int compareWithKey(size_t key) const { return (key == Key ? 0 : (key < Key ? -1 : 1)); } static size_t getExtraAllocationSize(size_t key) { return 0; } }; ConcurrentMap<Entry> Map; // Add a bunch of numbers to the map concurrently. auto results = RaceTest<int*>( [&]() -> int* { for (int i = 0; i < numElem; i++) { size_t hash = (i * 123512) % 0xFFFF ; Map.getOrInsert(hash); } return nullptr; } ); // Check that all of the values that we inserted are in the map. for (int i=0; i < numElem; i++) { size_t hash = (i * 123512) % 0xFFFF ; EXPECT_TRUE(Map.find(hash)); } }
void cacheSuccess(const void *type, const ProtocolDescriptor *proto, const WitnessTable *witness) { auto result = Cache.getOrInsert(ConformanceCacheKey(type, proto), witness, uintptr_t(0)); // If the entry was already present, we may need to update it. if (!result.second) { result.first->makeSuccessful(witness); } }
void cacheFailure(const void *type, const ProtocolDescriptor *proto) { uintptr_t failureGeneration = SectionsToScan.size(); auto result = Cache.getOrInsert(ConformanceCacheKey(type, proto), (const WitnessTable *) nullptr, failureGeneration); // If the entry was already present, we may need to update it. if (!result.second) { result.first->updateFailureGeneration(failureGeneration); } }