Beispiel #1
0
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);
    }
  }