Topic: John does things differently

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2018-06-02 18:44:35 +02:00
parent 9e278c88e6
commit 0b1c7cc35f

View File

@ -10,6 +10,10 @@ import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class Topic { public class Topic {
private static final int NON_INIT = 0; private static final int NON_INIT = 0;
@ -20,27 +24,24 @@ public class Topic {
private List<WeakReference<Subscriber>> subscribers; private List<WeakReference<Subscriber>> subscribers;
private Object[] results; private Object[] results;
public void subscribe(Subscriber sub) { public Topic() {
if (subscribers == null) { subscribers = new SyncArrayList<>();
subscribers = new LinkedList<>();
}
synchronized (subscribers) {
subscribers.add(new WeakReference<>(sub));
}
} }
public void unsubscribe() { public synchronized void subscribe(Subscriber sub) {
subscribers = null; subscribers.add(new WeakReference<>(sub));
} }
public void unsubscribe(Subscriber sub) { public synchronized void unsubscribe() {
synchronized (subscribers) { subscribers = new SyncArrayList<>();
for (Iterator<WeakReference<Subscriber>> i = subscribers.iterator(); i.hasNext(); ) { }
WeakReference<Subscriber> subscriber = i.next();
if (subscriber.get() == null || subscriber.get() == sub) { public synchronized void unsubscribe(Subscriber sub) {
i.remove(); List<WeakReference<Subscriber>> subs = subscribers;
} subscribers = new ArrayList<>();
} for (WeakReference<Subscriber> subscriber : subs) {
if (subscriber.get() != null && subscriber.get() != sub)
subscribers.add(subscriber);
} }
} }
@ -61,15 +62,11 @@ public class Topic {
if (record) if (record)
state = PUBLISHED; state = PUBLISHED;
this.results = results; this.results = results;
if (subscribers != null) { // Snapshot
List<WeakReference<Subscriber>> subscribersCopy = new LinkedList<>(); List<WeakReference<Subscriber>> subs = subscribers;
synchronized (subscribers) { for (WeakReference<Subscriber> subscriber : subs) {
subscribersCopy.addAll(subscribers); if (subscriber != null && subscriber.get() != null)
} subscriber.get().onTopicPublished(this);
for (WeakReference<Subscriber> subscriber : subscribersCopy) {
if (subscriber.get() != null)
subscriber.get().onTopicPublished(this);
}
} }
} }
@ -94,15 +91,19 @@ public class Topic {
topic.subscribe(this); topic.subscribe(this);
} }
} }
default void unsubscribeTopics() { default void unsubscribeTopics() {
for (Topic event : getSubscription()) { for (Topic event : getSubscription()) {
event.unsubscribe(this); event.unsubscribe(this);
} }
} }
void onTopicPublished(Topic topic); void onTopicPublished(Topic topic);
Topic[] getSubscription(); Topic[] getSubscription();
} }
private static class SyncArrayList<E> extends ArrayList<E> {
@Override
public synchronized boolean add(E e) {
return super.add(e);
}
}
} }