Skip to content

Commit

Permalink
Rework SPI
Browse files Browse the repository at this point in the history
  • Loading branch information
vietj committed Feb 28, 2024
1 parent 96a0929 commit dc57f97
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 139 deletions.
16 changes: 8 additions & 8 deletions src/main/java/io/vertx/core/impl/ContextBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
*/
package io.vertx.core.impl;

import io.vertx.core.spi.context.locals.AccessMode;
import io.vertx.core.spi.context.locals.ContextKey;
import io.vertx.core.spi.context.storage.AccessMode;
import io.vertx.core.spi.context.storage.ContextLocal;

import java.util.function.Supplier;

Expand All @@ -28,8 +28,8 @@ class ContextBase {
this.locals = locals;
}

public final <T> T getLocal(ContextKey<T> key, AccessMode accessMode) {
ContextKeyImpl<T> internalKey = (ContextKeyImpl<T>) key;
public final <T> T getLocal(ContextLocal<T> key, AccessMode accessMode) {
ContextLocalImpl<T> internalKey = (ContextLocalImpl<T>) key;
int index = internalKey.index;
if (index >= locals.length) {
throw new IllegalArgumentException();
Expand All @@ -38,8 +38,8 @@ public final <T> T getLocal(ContextKey<T> key, AccessMode accessMode) {
return (T) res;
}

public final <T> T getLocal(ContextKey<T> key, AccessMode accessMode, Supplier<? extends T> initialValueSupplier) {
ContextKeyImpl<T> internalKey = (ContextKeyImpl<T>) key;
public final <T> T getLocal(ContextLocal<T> key, AccessMode accessMode, Supplier<? extends T> initialValueSupplier) {
ContextLocalImpl<T> internalKey = (ContextLocalImpl<T>) key;
int index = internalKey.index;
if (index >= locals.length) {
throw new IllegalArgumentException("Invalid key index: " + index);
Expand All @@ -48,8 +48,8 @@ public final <T> T getLocal(ContextKey<T> key, AccessMode accessMode, Supplier<?
return (T) res;
}

public final <T> void putLocal(ContextKey<T> key, AccessMode accessMode, T value) {
ContextKeyImpl<T> internalKey = (ContextKeyImpl<T>) key;
public final <T> void putLocal(ContextLocal<T> key, AccessMode accessMode, T value) {
ContextLocalImpl<T> internalKey = (ContextLocalImpl<T>) key;
int index = internalKey.index;
if (index >= locals.length) {
throw new IllegalArgumentException();
Expand Down
57 changes: 9 additions & 48 deletions src/main/java/io/vertx/core/impl/ContextInternal.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
import io.vertx.core.impl.future.PromiseImpl;
import io.vertx.core.impl.future.PromiseInternal;
import io.vertx.core.impl.future.SucceededFuture;
import io.vertx.core.spi.context.locals.AccessMode;
import io.vertx.core.spi.context.locals.ContextKey;
import io.vertx.core.spi.context.storage.AccessMode;
import io.vertx.core.spi.context.storage.ContextLocal;
import io.vertx.core.spi.tracing.VertxTracer;

import java.util.concurrent.*;
Expand All @@ -35,7 +35,7 @@
*/
public interface ContextInternal extends Context {

ContextKey<ConcurrentMap<Object, Object>> LOCAL_MAP = new ContextKeyImpl<>(0);
ContextLocal<ConcurrentMap<Object, Object>> LOCAL_MAP = new ContextLocalImpl<>(0);

/**
* @return the current context
Expand Down Expand Up @@ -309,7 +309,7 @@ default boolean remove(Object key) {
* @return the {@link ConcurrentMap} used to store local context data
*/
default ConcurrentMap<Object, Object> localContextData() {
return getLocal(LOCAL_MAP, ConcurrentHashMap::new);
return LOCAL_MAP.get(this, ConcurrentHashMap::new);
}

/**
Expand All @@ -320,49 +320,10 @@ default ConcurrentMap<Object, Object> localContextData() {
* @return the local data
*/
@GenIgnore
default <T> T getLocal(ContextKey<T> key) {
default <T> T getLocal(ContextLocal<T> key) {
return getLocal(key, AccessMode.CONCURRENT);
}

/**
* Get some local data from the context, when it does not exist the {@code initialValueSupplier} is called to obtain
* the initial value.
*
* <p> The {@code initialValueSupplier} might be called multiple times when multiple threads call this method concurrently.
*
* @param key the key of the data
* @param initialValueSupplier the supplier of the initial value optionally called
* @param <T> the type of the data
* @return the local data
*/
@GenIgnore
default <T> T getLocal(ContextKey<T> key, Supplier<? extends T> initialValueSupplier) {
return getLocal(key, AccessMode.CONCURRENT, initialValueSupplier);
}

/**
* Put some local data in the context.
* <p>
* This can be used to share data between different handlers that share a context
*
* @param key the key of the data
* @param value the data
*/
@GenIgnore
default <T> void putLocal(ContextKey<T> key, T value) {
putLocal(key, AccessMode.CONCURRENT, value);
}

/**
* Remove some local data from the context.
*
* @param key the key to remove
*/
@GenIgnore
default <T> void removeLocal(ContextKey<T> key) {
putLocal(key, AccessMode.CONCURRENT, null);
}

/**
* Get some local data from the context.
*
Expand All @@ -371,7 +332,7 @@ default <T> void removeLocal(ContextKey<T> key) {
* @return the local data
*/
@GenIgnore
<T> T getLocal(ContextKey<T> key, AccessMode accessMode);
<T> T getLocal(ContextLocal<T> key, AccessMode accessMode);

/**
* Get some local data from the context, when it does not exist the {@code initialValueSupplier} is called to obtain
Expand All @@ -385,7 +346,7 @@ default <T> void removeLocal(ContextKey<T> key) {
* @return the local data
*/
@GenIgnore
<T> T getLocal(ContextKey<T> key, AccessMode accessMode, Supplier<? extends T> initialValueSupplier);
<T> T getLocal(ContextLocal<T> key, AccessMode accessMode, Supplier<? extends T> initialValueSupplier);

/**
* Put some local data in the context.
Expand All @@ -396,15 +357,15 @@ default <T> void removeLocal(ContextKey<T> key) {
* @param value the data
*/
@GenIgnore
<T> void putLocal(ContextKey<T> key, AccessMode accessMode, T value);
<T> void putLocal(ContextLocal<T> key, AccessMode accessMode, T value);

/**
* Remove some local data from the context.
*
* @param key the key to remove
*/
@GenIgnore
default <T> void removeLocal(ContextKey<T> key, AccessMode accessMode) {
default <T> void removeLocal(ContextLocal<T> key, AccessMode accessMode) {
putLocal(key, accessMode, null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@
*/
package io.vertx.core.impl;

import io.vertx.core.spi.context.locals.ContextKey;
import io.vertx.core.spi.context.storage.ContextLocal;

/**
* @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
*/
public class ContextKeyImpl<T> implements ContextKey<T> {
public class ContextLocalImpl<T> implements ContextLocal<T> {

final int index;

public ContextKeyImpl(int index) {
public ContextLocalImpl(int index) {
this.index = index;
}

public ContextKeyImpl() {
public ContextLocalImpl() {
this.index = KeySeq.next();
}
}
36 changes: 0 additions & 36 deletions src/main/java/io/vertx/core/spi/context/locals/ContextKey.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package io.vertx.core.spi.context.locals;
package io.vertx.core.spi.context.storage;

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
Expand Down
132 changes: 132 additions & 0 deletions src/main/java/io/vertx/core/spi/context/storage/ContextLocal.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright (c) 2011-2023 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package io.vertx.core.spi.context.storage;

import io.vertx.codegen.annotations.GenIgnore;
import io.vertx.core.Context;
import io.vertx.core.impl.ContextInternal;
import io.vertx.core.impl.ContextLocalImpl;

import java.util.function.Supplier;

/**
* A context local storage to address local context data.
*
* @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
*/
public interface ContextLocal<T> {

/**
* Registers a context local.
*
* <p>Locals should be registered before creating a {@link io.vertx.core.Vertx} instance, once registered a local cannot be unregistered.
*
* <p>It is recommended to initialize locals as static fields of a {@link io.vertx.core.spi.VertxServiceProvider}, since providers
* are discovered before the capture of known locals.
*
* @param type the type of context data
* @return the context key
*/
static <T> ContextLocal<T> registerLocal(Class<T> type) {
return new ContextLocalImpl<>();
}

/**
* Get some local data from the context.
*
* @return the local data
*/
@GenIgnore
default T get(Context context) {
return get(context, AccessMode.CONCURRENT);
}

/**
* Get some local data from the context, when it does not exist the {@code initialValueSupplier} is called to obtain
* the initial value.
*
* <p> The {@code initialValueSupplier} might be called multiple times when multiple threads call this method concurrently.
*
* @param initialValueSupplier the supplier of the initial value optionally called
* @return the local data
*/
@GenIgnore
default T get(Context context, Supplier<? extends T> initialValueSupplier) {
return get(context, AccessMode.CONCURRENT, initialValueSupplier);
}

/**
* Put some local data in the context.
* <p>
* This can be used to share data between different handlers that share a context
*
* @param value the data
*/
@GenIgnore
default void put(Context context, T value) {
put(context, AccessMode.CONCURRENT, value);
}

/**
* Remove some local data from the context.
*
*/
@GenIgnore
default void remove(Context context) {
put(context, AccessMode.CONCURRENT, null);
}

/**
* Get some local data from the context.
*
* @return the local data
*/
@GenIgnore
default T get(Context context, AccessMode accessMode) {
return ((ContextInternal)context).getLocal(this, accessMode);
}

/**
* Get some local data from the context, when it does not exist the {@code initialValueSupplier} is called to obtain
* the initial value.
*
* <p> The {@code initialValueSupplier} might be called multiple times when multiple threads call this method concurrently.
*
* @param initialValueSupplier the supplier of the initial value optionally called
* @return the local data
*/
@GenIgnore
default T get(Context context, AccessMode accessMode, Supplier<? extends T> initialValueSupplier) {
return ((ContextInternal)context).getLocal(this, accessMode, initialValueSupplier);
}

/**
* Put some local data in the context.
* <p>
* This can be used to share data between different handlers that share a context
*
* @param value the data
*/
@GenIgnore
default void put(Context context, AccessMode accessMode, T value) {
((ContextInternal)context).putLocal(this, accessMode, value);
}

/**
* Remove some local data from the context.
*
*/
@GenIgnore
default void remove(Context context, AccessMode accessMode) {
put(context, accessMode, null);
}

}
Loading

0 comments on commit dc57f97

Please sign in to comment.