Files

137 lines
3.4 KiB
Java

record Message(String type, String value) {}
Map<String, BlockingQueue<Message>> mailboxes =
new ConcurrentHashMap<>();
BlockingQueue<Message> mailbox(String name) {
return mailboxes.computeIfAbsent(
name,
_ -> new LinkedBlockingQueue<>()
);
}
void listen(String mailboxName, Consumer<Message> receiver) {
try {
while (true)
receiver.accept(mailbox(mailboxName).take());
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
}
}
String rot13(String text) {
var result = new StringBuilder();
for (var character : text.toCharArray()) {
if (character >= 'a' && character <= 'z')
character = (char) ('a' + (character - 'a' + 13) % 26);
else if (character >= 'A' && character <= 'Z')
character = (char) ('A' + (character - 'A' + 13) % 26);
result.append(character);
}
return result.toString();
}
void runConsoleIn() {
try {
while (true) {
var text = IO.readln();
if (text == null)
return;
mailbox("consoleIn.outbox")
.put(new Message("TEXT", text));
}
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
}
}
Map<String, Thread> rot13Subscriptions = new HashMap<>();
Map<String, Thread> consoleOutSubscriptions = new HashMap<>();
void subscribe(
Map<String, Thread> subscriptions,
String mailboxName,
Consumer<Message> receiver) {
subscriptions.computeIfAbsent(
mailboxName,
name -> Thread.ofVirtual().start(() -> listen(name, receiver))
);
}
void processWithRot13(Message message) {
if (!message.type().equals("TEXT"))
return;
try {
mailbox("rot13.outbox").put(
new Message("TEXT", rot13(message.value()))
);
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
}
}
void runRot13() {
try {
while (true) {
var message = mailbox("rot13.inbox").take();
if (message.type().equals("TOPIC"))
subscribe(
rot13Subscriptions,
message.value(),
this::processWithRot13
);
else
processWithRot13(message);
}
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
}
}
void print(Message message) {
if (message.type().equals("TEXT"))
IO.println(message.value());
}
void runConsoleOut() {
try {
while (true) {
var message = mailbox("consoleOut.inbox").take();
if (message.type().equals("TOPIC"))
subscribe(
consoleOutSubscriptions,
message.value(),
this::print
);
else
print(message);
}
} catch (InterruptedException _) {
Thread.currentThread().interrupt();
}
}
void main() throws Exception {
Thread.ofVirtual().start(this::runConsoleIn);
Thread.ofVirtual().start(this::runRot13);
Thread.ofVirtual().start(this::runConsoleOut);
mailbox("rot13.inbox").put(
new Message("TOPIC", "consoleIn.outbox")
);
mailbox("consoleOut.inbox").put(
new Message("TOPIC", "rot13.outbox")
);
Thread.currentThread().join();
}