Last active
December 9, 2024 02:54
-
-
Save sizovs/c79b985f2afca1430c000b00935ae987 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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