Cleaned up synchrony start/shutdown. Removed start (it was unnecessary), and shutdown now waits for threads to stop
This commit is contained in:
parent
89f47fdd8a
commit
0ae980319b
@ -233,7 +233,6 @@ class MessageBus implements IMessageBus {
|
|||||||
public
|
public
|
||||||
void start() {
|
void start() {
|
||||||
errorHandler.init();
|
errorHandler.init();
|
||||||
asyncPublication.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,8 +22,10 @@ import dorkbox.util.messagebus.subscription.Subscription;
|
|||||||
import dorkbox.util.messagebus.synchrony.disruptor.MessageType;
|
import dorkbox.util.messagebus.synchrony.disruptor.MessageType;
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.locks.LockSupport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is similar to the disruptor, however the downside of this implementation is that, while faster than the no-gc version, it
|
* This is similar to the disruptor, however the downside of this implementation is that, while faster than the no-gc version, it
|
||||||
@ -38,6 +40,7 @@ class AsyncABQ implements Synchrony {
|
|||||||
|
|
||||||
private final ArrayBlockingQueue<MessageHolder> dispatchQueue;
|
private final ArrayBlockingQueue<MessageHolder> dispatchQueue;
|
||||||
private final Collection<Thread> threads;
|
private final Collection<Thread> threads;
|
||||||
|
private final Collection<Boolean> shutdown;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the consumers during shutdown, that it's on purpose.
|
* Notifies the consumers during shutdown, that it's on purpose.
|
||||||
@ -63,14 +66,21 @@ class AsyncABQ implements Synchrony {
|
|||||||
while (!AsyncABQ.this.shuttingDown) {
|
while (!AsyncABQ.this.shuttingDown) {
|
||||||
process(IN_QUEUE, syncPublication1, errorHandler1);
|
process(IN_QUEUE, syncPublication1, errorHandler1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized (shutdown) {
|
||||||
|
shutdown.add(Boolean.TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.threads = new ArrayDeque<Thread>(numberOfThreads);
|
this.threads = new ArrayDeque<Thread>(numberOfThreads);
|
||||||
|
this.shutdown = new ArrayList<Boolean>();
|
||||||
|
|
||||||
final NamedThreadFactory threadFactory = new NamedThreadFactory("MessageBus");
|
final NamedThreadFactory threadFactory = new NamedThreadFactory("MessageBus");
|
||||||
for (int i = 0; i < numberOfThreads; i++) {
|
for (int i = 0; i < numberOfThreads; i++) {
|
||||||
Thread runner = threadFactory.newThread(runnable);
|
Thread thread = threadFactory.newThread(runnable);
|
||||||
this.threads.add(runner);
|
this.threads.add(thread);
|
||||||
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +118,7 @@ class AsyncABQ implements Synchrony {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
if (event != null) {
|
if (event != null && !this.shuttingDown) {
|
||||||
switch (messageType) {
|
switch (messageType) {
|
||||||
case MessageType.ONE: {
|
case MessageType.ONE: {
|
||||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.")
|
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.")
|
||||||
@ -134,7 +144,6 @@ class AsyncABQ implements Synchrony {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void publish(final Subscription[] subscriptions, final Object message1) throws Throwable {
|
void publish(final Subscription[] subscriptions, final Object message1) throws Throwable {
|
||||||
@ -174,17 +183,14 @@ class AsyncABQ implements Synchrony {
|
|||||||
this.dispatchQueue.put(take);
|
this.dispatchQueue.put(take);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public
|
public
|
||||||
void start() {
|
boolean hasPendingMessages() {
|
||||||
if (shuttingDown) {
|
return !this.dispatchQueue.isEmpty();
|
||||||
throw new Error("Unable to restart the MessageBus");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Thread t : this.threads) {
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
|
@Override
|
||||||
public
|
public
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
this.shuttingDown = true;
|
this.shuttingDown = true;
|
||||||
@ -192,10 +198,14 @@ class AsyncABQ implements Synchrony {
|
|||||||
for (Thread t : this.threads) {
|
for (Thread t : this.threads) {
|
||||||
t.interrupt();
|
t.interrupt();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public
|
while (true) {
|
||||||
boolean hasPendingMessages() {
|
synchronized (shutdown) {
|
||||||
return !this.dispatchQueue.isEmpty();
|
if (shutdown.size() == threads.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LockSupport.parkNanos(100L); // wait 100ms for threads to quit
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,10 @@ import dorkbox.util.messagebus.subscription.Subscription;
|
|||||||
import dorkbox.util.messagebus.synchrony.disruptor.MessageType;
|
import dorkbox.util.messagebus.synchrony.disruptor.MessageType;
|
||||||
|
|
||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.locks.LockSupport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is similar in behavior to the disruptor in that it does not generate garbage, however the downside of this implementation is it is
|
* This is similar in behavior to the disruptor in that it does not generate garbage, however the downside of this implementation is it is
|
||||||
@ -42,6 +44,7 @@ class AsyncABQ_noGc implements Synchrony {
|
|||||||
private final ArrayBlockingQueue<MessageHolder> gcQueue;
|
private final ArrayBlockingQueue<MessageHolder> gcQueue;
|
||||||
|
|
||||||
private final Collection<Thread> threads;
|
private final Collection<Thread> threads;
|
||||||
|
private final Collection<Boolean> shutdown;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the consumers during shutdown, that it's on purpose.
|
* Notifies the consumers during shutdown, that it's on purpose.
|
||||||
@ -75,14 +78,21 @@ class AsyncABQ_noGc implements Synchrony {
|
|||||||
while (!AsyncABQ_noGc.this.shuttingDown) {
|
while (!AsyncABQ_noGc.this.shuttingDown) {
|
||||||
process(IN_QUEUE, OUT_QUEUE, syncPublication1, errorHandler1);
|
process(IN_QUEUE, OUT_QUEUE, syncPublication1, errorHandler1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
synchronized (shutdown) {
|
||||||
|
shutdown.add(Boolean.TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.threads = new ArrayDeque<Thread>(numberOfThreads);
|
this.threads = new ArrayDeque<Thread>(numberOfThreads);
|
||||||
|
this.shutdown = new ArrayList<Boolean>();
|
||||||
|
|
||||||
final NamedThreadFactory threadFactory = new NamedThreadFactory("MessageBus");
|
final NamedThreadFactory threadFactory = new NamedThreadFactory("MessageBus");
|
||||||
for (int i = 0; i < numberOfThreads; i++) {
|
for (int i = 0; i < numberOfThreads; i++) {
|
||||||
Thread runner = threadFactory.newThread(runnable);
|
Thread thread = threadFactory.newThread(runnable);
|
||||||
this.threads.add(runner);
|
this.threads.add(thread);
|
||||||
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +136,7 @@ class AsyncABQ_noGc implements Synchrony {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
if (event != null) {
|
if (event != null && !this.shuttingDown) {
|
||||||
switch (messageType) {
|
switch (messageType) {
|
||||||
case MessageType.ONE: {
|
case MessageType.ONE: {
|
||||||
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.")
|
errorHandler.handlePublicationError(new PublicationError().setMessage("Error during invocation of message handler.")
|
||||||
@ -191,17 +201,14 @@ class AsyncABQ_noGc implements Synchrony {
|
|||||||
this.dispatchQueue.put(take);
|
this.dispatchQueue.put(take);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public
|
public
|
||||||
void start() {
|
boolean hasPendingMessages() {
|
||||||
if (shuttingDown) {
|
return !this.dispatchQueue.isEmpty();
|
||||||
throw new Error("Unable to restart the MessageBus");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Thread t : this.threads) {
|
|
||||||
t.start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
|
@Override
|
||||||
public
|
public
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
this.shuttingDown = true;
|
this.shuttingDown = true;
|
||||||
@ -209,10 +216,14 @@ class AsyncABQ_noGc implements Synchrony {
|
|||||||
for (Thread t : this.threads) {
|
for (Thread t : this.threads) {
|
||||||
t.interrupt();
|
t.interrupt();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public
|
while (true) {
|
||||||
boolean hasPendingMessages() {
|
synchronized (shutdown) {
|
||||||
return !this.dispatchQueue.isEmpty();
|
if (shutdown.size() == threads.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LockSupport.parkNanos(100L); // wait 100ms for threads to quit
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,23 +166,7 @@ class AsyncDisruptor implements Synchrony {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public
|
@Override
|
||||||
void start() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
|
||||||
void shutdown() {
|
|
||||||
for (WorkProcessor<?> processor : workProcessors) {
|
|
||||||
processor.halt();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (MessageHandler handler : handlers) {
|
|
||||||
while (!handler.isShutdown()) {
|
|
||||||
LockSupport.parkNanos(100L); // wait 100ms for handlers to quit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public
|
public
|
||||||
boolean hasPendingMessages() {
|
boolean hasPendingMessages() {
|
||||||
// from workerPool.drainAndHalt()
|
// from workerPool.drainAndHalt()
|
||||||
@ -196,4 +180,18 @@ class AsyncDisruptor implements Synchrony {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public
|
||||||
|
void shutdown() {
|
||||||
|
for (WorkProcessor<?> processor : workProcessors) {
|
||||||
|
processor.halt();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (MessageHandler handler : handlers) {
|
||||||
|
while (!handler.isShutdown()) {
|
||||||
|
LockSupport.parkNanos(100L); // wait 100ms for handlers to quit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,11 +51,6 @@ class Sync implements Synchrony {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public
|
|
||||||
void start() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void shutdown() {
|
void shutdown() {
|
||||||
|
@ -26,7 +26,6 @@ interface Synchrony {
|
|||||||
void publish(final Subscription[] subscriptions, Object message1, Object message2) throws Throwable ;
|
void publish(final Subscription[] subscriptions, Object message1, Object message2) throws Throwable ;
|
||||||
void publish(final Subscription[] subscriptions, Object message1, Object message2, Object message3) throws Throwable ;
|
void publish(final Subscription[] subscriptions, Object message1, Object message2, Object message3) throws Throwable ;
|
||||||
|
|
||||||
void start();
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
boolean hasPendingMessages();
|
boolean hasPendingMessages();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user