Skip to content

Instantly share code, notes, and snippets.

@sizovs
Last active December 9, 2024 02:54
Show Gist options
  • Save sizovs/c79b985f2afca1430c000b00935ae987 to your computer and use it in GitHub Desktop.
Save sizovs/c79b985f2afca1430c000b00935ae987 to your computer and use it in GitHub Desktop.
import com.google.common.reflect.TypeToken;
import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static java.lang.Thread.currentThread;
import static java.util.concurrent.Executors.newWorkStealingPool;
class Events {
private final Handlers syncHandlers = new Handlers(directExecutor());
private final Handlers asyncHandlers = new Handlers(newWorkStealingPool());
public <E extends Event> void publish(E event) {
syncHandlers.invokeMatching(event);
asyncHandlers.invokeMatching(event);
}
public <T extends Event> void registerSync(Handler<T> handler) {
syncHandlers.add(handler);
}
public <T extends Event> void registerAsync(Handler<T> handler) {
asyncHandlers.add(handler);
}
}
interface Event {
}
interface Handler<E extends Event> {
void handle(E event);
default boolean matches(E event) {
var eventTypeToken = new TypeToken<E>(getClass()) {
};
return eventTypeToken.getRawType().equals(event.getClass()) || eventTypeToken.isSupertypeOf(event.getClass());
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
class Handlers {
private final Collection<Handler> handlers = new CopyOnWriteArrayList<>();
private final Executor pool;
Handlers(Executor pool) {
this.pool = pool;
}
void add(Handler handler) {
handlers.add(handler);
}
void invokeMatching(Event event) {
handlers
.stream()
.filter(handler -> handler.matches(event))
.forEach(handler -> pool.execute(() -> handler.handle(event)));
}
}
class Demo {
record Ping(String sender) implements Event {
}
static class Pong implements Handler<Ping> {
@Override
public void handle(Ping event) {
System.out.printf("%s: ping received from %s in %s\n", getClass().getName(), event.sender(), currentThread().getName());
}
}
static class AnotherPong implements Handler<Ping> {
@Override
public void handle(Ping event) {
System.out.printf("%s: ping received from %s in %s\n", getClass().getName(), event.sender(), currentThread().getName());
}
}
public static void main(String[] args) {
var events = new Events();
events.registerSync(new Pong());
events.registerSync(new AnotherPong());
events.registerAsync(new Pong());
events.publish(new Ping("Java Dev"));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment