@Test void testInterningConcurrent() { Map<String, Long> allocations; try (FDBRecordContext context = database.openContext()) { StringInterningLayer interningLayer = new StringInterningLayer(testSubspace); List<CompletableFuture<Pair<String, Long>>> futures = IntStream.range(0, 50) .mapToObj(i -> String.format("intern-%d", i)) .map(value -> interningLayer.intern(context, value).thenApply(interned -> Pair.of(value, interned.getValue()))) .collect(Collectors.toList()); allocations = AsyncUtil.getAll(futures).join().stream() .collect(Collectors.toMap(Pair::getLeft, Pair::getRight)); for (int i = 0; i < 50; i++) { String toIntern = "intern-" + i; Long value = interningLayer.intern(context, toIntern).join().getValue(); assertThat("value is in mapping", allocations.get(toIntern), is(value)); } } }
protected CompletableFuture<ResolverResult> intern(@Nonnull FDBRecordContext context, @Nonnull final String toIntern) { CompletableFuture<Optional<ResolverResult>> readResult; synchronized (this) { readResult = read(context, toIntern); } return readResult .thenApply(maybeRead -> maybeRead.map(CompletableFuture::completedFuture)) .thenCompose(value -> value.orElseGet(() -> createMapping(context, toIntern, null))); }
StringInterningLayer { protected CompletableFuture<ResolverResult> intern(@Nonnull FDBRecordContext context, @Nonnull final String toIntern) { CompletableFuture<Optional<ResolverResult>> readResult; synchronized (this) { readResult = read(context, toIntern); } return readResult .thenApply(maybeRead -> maybeRead.map(CompletableFuture::completedFuture)) .thenCompose(value -> value.orElseGet(() -> createMapping(context, toIntern, null))); } }
StringInterningLayer { protected CompletableFuture<ResolverResult> intern(@Nonnull FDBRecordContext context, @Nonnull final String toIntern) { CompletableFuture<Optional<ResolverResult>> readResult; synchronized (this) { readResult = read(context, toIntern); } return readResult .thenApply(maybeRead -> maybeRead.map(CompletableFuture::completedFuture)) .thenCompose(value -> value.orElseGet(() -> createMapping(context, toIntern, null))); } StringInterningLayer(@Nonnull Subspace baseSubspace);  StringInterningLayer(@Nonnull Subspace baseSubspace, boolean isRootLevel); private  StringInterningLayer(@Nonnull Subspace mappingSubspace,
                                 @Nonnull Subspace reverseMappingSubspace,
                                 @Nonnull Subspace counterSubspace,
                                 boolean isRootLevel); }
StringInterningLayer { protected CompletableFuture<ResolverResult> intern(@Nonnull FDBRecordContext context, @Nonnull final String toIntern) { CompletableFuture<Optional<ResolverResult>> readResult; synchronized (this) { readResult = read(context, toIntern); } return readResult .thenApply(maybeRead -> maybeRead.map(CompletableFuture::completedFuture)) .thenCompose(value -> value.orElseGet(() -> createMapping(context, toIntern, null))); } StringInterningLayer(@Nonnull Subspace baseSubspace);  StringInterningLayer(@Nonnull Subspace baseSubspace, boolean isRootLevel); private  StringInterningLayer(@Nonnull Subspace mappingSubspace,
                                 @Nonnull Subspace reverseMappingSubspace,
                                 @Nonnull Subspace counterSubspace,
                                 boolean isRootLevel);  }
StringInterningLayer { protected CompletableFuture<ResolverResult> intern(@Nonnull FDBRecordContext context, @Nonnull final String toIntern) { CompletableFuture<Optional<ResolverResult>> readResult; synchronized (this) { readResult = read(context, toIntern); } return readResult .thenApply(maybeRead -> maybeRead.map(CompletableFuture::completedFuture)) .thenCompose(value -> value.orElseGet(() -> createMapping(context, toIntern, null))); } StringInterningLayer(@Nonnull Subspace baseSubspace);  StringInterningLayer(@Nonnull Subspace baseSubspace, boolean isRootLevel); private  StringInterningLayer(@Nonnull Subspace mappingSubspace,
                                 @Nonnull Subspace reverseMappingSubspace,
                                 @Nonnull Subspace counterSubspace,
                                 boolean isRootLevel);   }