From c3b5b04b71ed4c715131a306bfb4a47166ce7a9d Mon Sep 17 00:00:00 2001 From: akwizgran Date: Wed, 7 Nov 2018 13:26:00 +0000 Subject: [PATCH] Broadcast events asynchronously. --- .../bramble/system/AndroidSystemModule.java | 10 ++++++ .../bramble/api/event/EventBus.java | 3 +- .../bramble/api/event/EventExecutor.java | 25 +++++++++++++++ .../bramble/api/event/EventListener.java | 1 + .../bramble/db/DatabaseComponentImpl.java | 8 +++-- .../event/DefaultEventExecutorModule.java | 32 +++++++++++++++++++ .../bramble/event/EventBusImpl.java | 10 +++++- .../bramble/event/EventModule.java | 7 ++-- .../BrambleJavaIntegrationTestComponent.java | 4 ++- .../FeedManagerIntegrationTestComponent.java | 2 ++ .../IntroductionIntegrationTestComponent.java | 2 ++ .../MessageSizeIntegrationTestComponent.java | 2 ++ ...plexMessagingIntegrationTestComponent.java | 2 ++ .../test/BriarIntegrationTestComponent.java | 2 ++ .../briar/headless/HeadlessModule.kt | 2 ++ 15 files changed, 104 insertions(+), 8 deletions(-) create mode 100644 bramble-api/src/main/java/org/briarproject/bramble/api/event/EventExecutor.java create mode 100644 bramble-core/src/main/java/org/briarproject/bramble/event/DefaultEventExecutorModule.java diff --git a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java index 2f7ea5543..89bf2a321 100644 --- a/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java +++ b/bramble-android/src/main/java/org/briarproject/bramble/system/AndroidSystemModule.java @@ -1,10 +1,13 @@ package org.briarproject.bramble.system; +import org.briarproject.bramble.api.event.EventExecutor; import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; import org.briarproject.bramble.api.system.SecureRandomProvider; +import java.util.concurrent.Executor; + import javax.inject.Singleton; import dagger.Module; @@ -32,6 +35,13 @@ public class AndroidSystemModule { return androidExecutor; } + @Provides + @Singleton + @EventExecutor + Executor provideEventExecutor(AndroidExecutor androidExecutor) { + return androidExecutor::runOnUiThread; + } + @Provides @Singleton ResourceProvider provideResourceProvider(AndroidResourceProvider provider) { diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventBus.java b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventBus.java index af00f8b1b..d27449833 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventBus.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventBus.java @@ -16,7 +16,8 @@ public interface EventBus { void removeListener(EventListener l); /** - * Notifies all listeners of an event. + * Asynchronously notifies all listeners of an event. Listeners are + * notified on the {@link EventExecutor}. */ void broadcast(Event e); } diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventExecutor.java b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventExecutor.java new file mode 100644 index 000000000..3e1125f8f --- /dev/null +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventExecutor.java @@ -0,0 +1,25 @@ +package org.briarproject.bramble.api.event; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import javax.inject.Qualifier; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Annotation for injecting the executor for broadcasting events. Also used for + * annotating methods that should run on the event executor. + *

+ * The contract of this executor is that tasks are run in the order they're + * submitted, tasks are not run concurrently, and submitting a task will never + * block. Tasks must not block. Tasks submitted during shutdown are discarded. + */ +@Qualifier +@Target({FIELD, METHOD, PARAMETER}) +@Retention(RUNTIME) +public @interface EventExecutor { +} diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventListener.java b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventListener.java index 6dd330ead..20989bfc3 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventListener.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/event/EventListener.java @@ -12,5 +12,6 @@ public interface EventListener { * Called when an event is broadcast. Implementations of this method must * not block. */ + @EventExecutor void eventOccurred(Event e); } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 97e7670c9..17525ed12 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -160,13 +160,15 @@ class DatabaseComponentImpl implements DatabaseComponent { public void endTransaction(Transaction transaction) { try { T txn = txnClass.cast(transaction.unbox()); - if (!transaction.isCommitted()) db.abortTransaction(txn); + if (transaction.isCommitted()) { + for (Event e : transaction.getEvents()) eventBus.broadcast(e); + } else { + db.abortTransaction(txn); + } } finally { if (transaction.isReadOnly()) lock.readLock().unlock(); else lock.writeLock().unlock(); } - if (transaction.isCommitted()) - for (Event e : transaction.getEvents()) eventBus.broadcast(e); } @Override diff --git a/bramble-core/src/main/java/org/briarproject/bramble/event/DefaultEventExecutorModule.java b/bramble-core/src/main/java/org/briarproject/bramble/event/DefaultEventExecutorModule.java new file mode 100644 index 000000000..5fc21cc86 --- /dev/null +++ b/bramble-core/src/main/java/org/briarproject/bramble/event/DefaultEventExecutorModule.java @@ -0,0 +1,32 @@ +package org.briarproject.bramble.event; + +import org.briarproject.bramble.api.event.EventExecutor; + +import java.util.concurrent.Executor; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +import static java.util.concurrent.Executors.newSingleThreadExecutor; + +/** + * Default implementation of {@link EventExecutor} that uses a dedicated thread + * to notify listeners of events. Applications may prefer to supply an + * implementation that uses an existing thread, such as the UI thread. + */ +@Module +public class DefaultEventExecutorModule { + + @Provides + @Singleton + @EventExecutor + Executor provideEventExecutor() { + return newSingleThreadExecutor(r -> { + Thread t = new Thread(r); + t.setDaemon(true); + return t; + }); + } +} diff --git a/bramble-core/src/main/java/org/briarproject/bramble/event/EventBusImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/event/EventBusImpl.java index b08493cd0..150852114 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/event/EventBusImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/event/EventBusImpl.java @@ -7,6 +7,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import java.util.Collection; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; import javax.annotation.concurrent.ThreadSafe; @@ -16,6 +17,11 @@ class EventBusImpl implements EventBus { private final Collection listeners = new CopyOnWriteArrayList<>(); + private final Executor eventExecutor; + + EventBusImpl(Executor eventExecutor) { + this.eventExecutor = eventExecutor; + } @Override public void addListener(EventListener l) { @@ -29,6 +35,8 @@ class EventBusImpl implements EventBus { @Override public void broadcast(Event e) { - for (EventListener l : listeners) l.eventOccurred(e); + eventExecutor.execute(() -> { + for (EventListener l : listeners) l.eventOccurred(e); + }); } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/event/EventModule.java b/bramble-core/src/main/java/org/briarproject/bramble/event/EventModule.java index 3cd8bcdef..8aa1fea06 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/event/EventModule.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/event/EventModule.java @@ -1,6 +1,9 @@ package org.briarproject.bramble.event; import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.event.EventExecutor; + +import java.util.concurrent.Executor; import javax.inject.Singleton; @@ -12,7 +15,7 @@ public class EventModule { @Provides @Singleton - EventBus provideEventBus() { - return new EventBusImpl(); + EventBus provideEventBus(@EventExecutor Executor eventExecutor) { + return new EventBusImpl(eventExecutor); } } diff --git a/bramble-java/src/test/java/org/briarproject/bramble/test/BrambleJavaIntegrationTestComponent.java b/bramble-java/src/test/java/org/briarproject/bramble/test/BrambleJavaIntegrationTestComponent.java index 0b775f964..e16e71284 100644 --- a/bramble-java/src/test/java/org/briarproject/bramble/test/BrambleJavaIntegrationTestComponent.java +++ b/bramble-java/src/test/java/org/briarproject/bramble/test/BrambleJavaIntegrationTestComponent.java @@ -2,6 +2,7 @@ package org.briarproject.bramble.test; import org.briarproject.bramble.BrambleJavaModule; import org.briarproject.bramble.battery.DefaultBatteryManagerModule; +import org.briarproject.bramble.event.DefaultEventExecutorModule; import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.plugin.PluginModule; import org.briarproject.bramble.plugin.tor.BridgeTest; @@ -17,8 +18,9 @@ import dagger.Component; BrambleJavaModule.class, TestLifecycleModule.class, DefaultBatteryManagerModule.class, - PluginModule.class, // needed for BackoffFactory + DefaultEventExecutorModule.class, EventModule.class, + PluginModule.class, // needed for BackoffFactory SystemModule.class, }) public interface BrambleJavaIntegrationTestComponent { diff --git a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java index 11667b6d1..aefdf9360 100644 --- a/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/feed/FeedManagerIntegrationTestComponent.java @@ -8,6 +8,7 @@ import org.briarproject.bramble.crypto.CryptoExecutorModule; import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.db.DatabaseModule; +import org.briarproject.bramble.event.DefaultEventExecutorModule; import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.lifecycle.LifecycleModule; @@ -46,6 +47,7 @@ import dagger.Component; FeedModule.class, DataModule.class, DatabaseModule.class, + DefaultEventExecutorModule.class, EventModule.class, IdentityModule.class, LifecycleModule.class, diff --git a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java index 1ef0a9210..815da25ea 100644 --- a/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/introduction/IntroductionIntegrationTestComponent.java @@ -6,6 +6,7 @@ import org.briarproject.bramble.crypto.CryptoExecutorModule; import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.db.DatabaseModule; +import org.briarproject.bramble.event.DefaultEventExecutorModule; import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.lifecycle.LifecycleModule; @@ -45,6 +46,7 @@ import dagger.Component; CryptoExecutorModule.class, DataModule.class, DatabaseModule.class, + DefaultEventExecutorModule.class, EventModule.class, ForumModule.class, GroupInvitationModule.class, diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java index f56035fb6..833aed5e2 100644 --- a/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/MessageSizeIntegrationTestComponent.java @@ -6,6 +6,7 @@ import org.briarproject.bramble.crypto.CryptoExecutorModule; import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.db.DatabaseModule; +import org.briarproject.bramble.event.DefaultEventExecutorModule; import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.sync.SyncModule; @@ -37,6 +38,7 @@ import dagger.Component; CryptoExecutorModule.class, DataModule.class, DatabaseModule.class, + DefaultEventExecutorModule.class, EventModule.class, ForumModule.class, IdentityModule.class, diff --git a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java index 6835add8c..efba3db0b 100644 --- a/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/messaging/SimplexMessagingIntegrationTestComponent.java @@ -13,6 +13,7 @@ import org.briarproject.bramble.contact.ContactModule; import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.db.DatabaseModule; +import org.briarproject.bramble.event.DefaultEventExecutorModule; import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.lifecycle.LifecycleModule; @@ -46,6 +47,7 @@ import dagger.Component; CryptoModule.class, DataModule.class, DatabaseModule.class, + DefaultEventExecutorModule.class, EventModule.class, IdentityModule.class, LifecycleModule.class, diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java index 11ef2fe81..f0c0e69ff 100644 --- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java +++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTestComponent.java @@ -15,6 +15,7 @@ import org.briarproject.bramble.crypto.CryptoExecutorModule; import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.db.DatabaseModule; +import org.briarproject.bramble.event.DefaultEventExecutorModule; import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.lifecycle.LifecycleModule; @@ -63,6 +64,7 @@ import dagger.Component; CryptoExecutorModule.class, DataModule.class, DatabaseModule.class, + DefaultEventExecutorModule.class, EventModule.class, ForumModule.class, GroupInvitationModule.class, diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.kt b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.kt index a5d567547..53ce493d3 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.kt +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.kt @@ -21,6 +21,7 @@ import org.briarproject.bramble.api.system.Clock import org.briarproject.bramble.api.system.LocationUtils import org.briarproject.bramble.api.system.ResourceProvider import org.briarproject.bramble.battery.DefaultBatteryManagerModule +import org.briarproject.bramble.event.DefaultEventExecutorModule import org.briarproject.bramble.network.JavaNetworkModule import org.briarproject.bramble.plugin.tor.CircumventionModule import org.briarproject.bramble.plugin.tor.CircumventionProvider @@ -47,6 +48,7 @@ import javax.net.SocketFactory JavaSystemModule::class, CircumventionModule::class, DefaultBatteryManagerModule::class, + DefaultEventExecutorModule::class, HeadlessBlogModule::class, HeadlessContactModule::class, HeadlessEventModule::class,