Skip to content

Commit

Permalink
perf: simplify CacheApiSettings singleton creation (#316)
Browse files Browse the repository at this point in the history
  • Loading branch information
iProdigy authored Sep 29, 2024
1 parent 3a2266e commit 1675da2
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
*/
@Slf4j
public final class CacheApiSettings {
private static volatile CacheApiSettings INSTANCE;

private final Map<Class<? extends CacheProvider>, CacheProvider> providers = Collections.synchronizedMap(new IdentityHashMap<>(16));
private final AtomicReference<Class<? extends CacheProvider>> defaultCacheProvider = new AtomicReference<>();

Expand All @@ -38,7 +36,7 @@ public final class CacheApiSettings {
private volatile MisconfigurationPolicy defaultMisconfigurationPolicy = MisconfigurationPolicy.IGNORE;

private CacheApiSettings() {
// restrict instantiation
this.populateProviders();
}

/**
Expand Down Expand Up @@ -102,31 +100,14 @@ public void registerCacheProvider(@NonNull Class<? extends CacheProvider> cacheP
}
}

/**
* @return the cache api settings singleton
*/
@NotNull
public static CacheApiSettings getInstance() {
if (INSTANCE == null) {
synchronized (CacheApiSettings.class) {
if (INSTANCE == null) {
CacheApiSettings cacheApiSettings = new CacheApiSettings();
populateProviders(cacheApiSettings);
INSTANCE = cacheApiSettings;
}
}
}
return INSTANCE;
}

private static void populateProviders(CacheApiSettings cacheApiSettings) {
private void populateProviders() {
log.debug("Xanthic: Registering canonical cache providers from the classpath...");

AtomicInteger registered = new AtomicInteger();
Consumer<String> loadImpl = (providerClass) -> {
try {
Class<? extends CacheProvider> clazz = Class.forName(providerClass).asSubclass(CacheProvider.class);
cacheApiSettings.registerCacheProvider(clazz, null); // lazy, init if needed
registerCacheProvider(clazz, null); // lazy, init if needed
registered.incrementAndGet();
} catch (ClassNotFoundException cx) {
log.trace("Xanthic: Could not find optional cache provider " + providerClass);
Expand All @@ -148,4 +129,16 @@ private static void populateProviders(CacheApiSettings cacheApiSettings) {

log.debug("Xanthic: Loaded {} canonical cache provider(s) on settings construction!", registered.get());
}

/**
* @return the cache api settings singleton
*/
@NotNull
public static CacheApiSettings getInstance() {
return SingletonHolder.INSTANCE;
}

private static class SingletonHolder {
private static final CacheApiSettings INSTANCE = new CacheApiSettings();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
import org.junit.jupiter.api.Test;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import static org.junit.jupiter.api.Assertions.assertThrows;

Expand All @@ -23,10 +26,19 @@ public class CacheRegistrationTest {
@SneakyThrows
void beforeEachTest() {
// reset cache settings singleton
Field instanceField = CacheApiSettings.class.getDeclaredField("INSTANCE");
instanceField.setAccessible(true);
instanceField.set(null, null);
CacheApiSettings.getInstance();
CacheApiSettings instance = CacheApiSettings.getInstance();

Field providers = CacheApiSettings.class.getDeclaredField("providers");
providers.setAccessible(true);
((Map<?, ?>) providers.get(instance)).clear();

Field defaultProvider = CacheApiSettings.class.getDeclaredField("defaultCacheProvider");
defaultProvider.setAccessible(true);
((AtomicReference<?>) defaultProvider.get(instance)).set(null);

Method populate = CacheApiSettings.class.getDeclaredMethod("populateProviders");
populate.setAccessible(true);
populate.invoke(instance);
}

@Test
Expand Down

0 comments on commit 1675da2

Please sign in to comment.