Skip to content

Commit 8127962

Browse files
authored
Fix EventBus instances being unexpectedly started up after shutdown in certain conditions, fixes #102 (#103)
1 parent 409eb28 commit 8127962

File tree

4 files changed

+45
-1
lines changed

4 files changed

+45
-1
lines changed

eventbus-test/src/test/java/net/minecraftforge/eventbus/test/IndividualEventListenerTests.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package net.minecraftforge.eventbus.test;
66

7+
import net.minecraftforge.eventbus.api.bus.BusGroup;
78
import net.minecraftforge.eventbus.api.bus.CancellableEventBus;
89
import net.minecraftforge.eventbus.api.bus.EventBus;
910
import net.minecraftforge.eventbus.api.event.RecordEvent;
@@ -316,4 +317,43 @@ record CancellableTestEvent() implements Cancellable, RecordEvent {
316317
CancellableTestEvent.BUS.removeListener(listener);
317318
Assertions.assertFalse(CancellableTestEvent.BUS.hasListeners(), "CancellableTestEvent.BUS should no longer have listeners");
318319
}
320+
321+
/**
322+
* Tests that {@link BusGroup#shutdown()} and {@link BusGroup#startup()} work as expected.
323+
*/
324+
@Test
325+
public void testShutdownAndStartup() {
326+
record TestEvent() implements RecordEvent {
327+
static final BusGroup TEST_GROUP = BusGroup.create(TestEvent.class.getName() + "testShutdown");
328+
static final EventBus<TestEvent> BUS = EventBus.create(TEST_GROUP, TestEvent.class);
329+
}
330+
331+
var called = new AtomicBoolean();
332+
Assertions.assertFalse(called.get(), "Listeners should not have been called yet");
333+
var listener1 = TestEvent.BUS.addListener(event -> called.set(true));
334+
var listener2 = TestEvent.BUS.addListener(event -> called.set(true));
335+
Assertions.assertFalse(called.get(), "Listeners should not have been called yet");
336+
TestEvent.BUS.post(new TestEvent());
337+
Assertions.assertTrue(called.get(), "Listeners should have been called");
338+
339+
called.set(false);
340+
TestEvent.TEST_GROUP.shutdown();
341+
TestEvent.BUS.post(new TestEvent());
342+
Assertions.assertFalse(called.get(), "Listeners should not have been called after shutdown");
343+
344+
TestEvent.BUS.removeListener(listener1);
345+
TestEvent.BUS.post(new TestEvent());
346+
Assertions.assertFalse(called.get(), "Listener2 should not have been called after removal of Listener1");
347+
348+
TestEvent.BUS.removeListener(listener2);
349+
TestEvent.BUS.addListener(listener1);
350+
TestEvent.BUS.post(new TestEvent());
351+
Assertions.assertFalse(called.get(), "Listener1 should not have been called after adding Listener2 back when the bus is shutdown");
352+
353+
TestEvent.TEST_GROUP.startup();
354+
TestEvent.BUS.post(new TestEvent());
355+
Assertions.assertTrue(called.get(), "Listener1 should have been called after startup");
356+
357+
TestEvent.TEST_GROUP.dispose();
358+
}
319359
}

src/main/java/net/minecraftforge/eventbus/internal/AbstractEventBusImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,9 @@ default void startup() {
139139

140140
synchronized (backingList()) {
141141
// Force invalidate the invoker to remove the no-op invoker that might've been set by shutdown()
142-
alreadyInvalidated().set(false);
142+
// Note: Opaque suffices here as this write immediately precedes the read made in invalidateInvoker() inside
143+
// the same synchronised block
144+
alreadyInvalidated().setOpaque(false);
143145
invalidateInvoker();
144146

145147
children().forEach(AbstractEventBusImpl::startup);

src/main/java/net/minecraftforge/eventbus/internal/CancellableEventBusImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ public boolean hasListeners() {
122122

123123
@Override // overrides from AbstractEventBusImpl
124124
public void invalidateInvoker() {
125+
if (alreadyInvalidated.getAcquire()) return;
125126
invokerCallSite.setTarget(backingList.isEmpty() ? MH_NO_OP_PREDICATE : MH_NULL_PREDICATE);
126127
}
127128

src/main/java/net/minecraftforge/eventbus/internal/EventBusImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public boolean hasListeners() {
8787

8888
@Override // overrides from AbstractEventBusImpl
8989
public void invalidateInvoker() {
90+
if (alreadyInvalidated.getAcquire()) return;
9091
invokerCallSite.setTarget(backingList.isEmpty() ? MH_NO_OP_CONSUMER : MH_NULL_CONSUMER);
9192
}
9293

0 commit comments

Comments
 (0)