Broadcast events asynchronously.

This commit is contained in:
akwizgran
2018-11-07 13:26:00 +00:00
parent 8b3164e107
commit c3b5b04b71
15 changed files with 104 additions and 8 deletions

View File

@@ -1,10 +1,13 @@
package org.briarproject.bramble.system; 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.AndroidExecutor;
import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.LocationUtils;
import org.briarproject.bramble.api.system.ResourceProvider; import org.briarproject.bramble.api.system.ResourceProvider;
import org.briarproject.bramble.api.system.SecureRandomProvider; import org.briarproject.bramble.api.system.SecureRandomProvider;
import java.util.concurrent.Executor;
import javax.inject.Singleton; import javax.inject.Singleton;
import dagger.Module; import dagger.Module;
@@ -32,6 +35,13 @@ public class AndroidSystemModule {
return androidExecutor; return androidExecutor;
} }
@Provides
@Singleton
@EventExecutor
Executor provideEventExecutor(AndroidExecutor androidExecutor) {
return androidExecutor::runOnUiThread;
}
@Provides @Provides
@Singleton @Singleton
ResourceProvider provideResourceProvider(AndroidResourceProvider provider) { ResourceProvider provideResourceProvider(AndroidResourceProvider provider) {

View File

@@ -16,7 +16,8 @@ public interface EventBus {
void removeListener(EventListener l); 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); void broadcast(Event e);
} }

View File

@@ -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.
* <p>
* 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 {
}

View File

@@ -12,5 +12,6 @@ public interface EventListener {
* Called when an event is broadcast. Implementations of this method must * Called when an event is broadcast. Implementations of this method must
* not block. * not block.
*/ */
@EventExecutor
void eventOccurred(Event e); void eventOccurred(Event e);
} }

View File

@@ -160,13 +160,15 @@ class DatabaseComponentImpl<T> implements DatabaseComponent {
public void endTransaction(Transaction transaction) { public void endTransaction(Transaction transaction) {
try { try {
T txn = txnClass.cast(transaction.unbox()); 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 { } finally {
if (transaction.isReadOnly()) lock.readLock().unlock(); if (transaction.isReadOnly()) lock.readLock().unlock();
else lock.writeLock().unlock(); else lock.writeLock().unlock();
} }
if (transaction.isCommitted())
for (Event e : transaction.getEvents()) eventBus.broadcast(e);
} }
@Override @Override

View File

@@ -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;
});
}
}

View File

@@ -7,6 +7,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import javax.annotation.concurrent.ThreadSafe; import javax.annotation.concurrent.ThreadSafe;
@@ -16,6 +17,11 @@ class EventBusImpl implements EventBus {
private final Collection<EventListener> listeners = private final Collection<EventListener> listeners =
new CopyOnWriteArrayList<>(); new CopyOnWriteArrayList<>();
private final Executor eventExecutor;
EventBusImpl(Executor eventExecutor) {
this.eventExecutor = eventExecutor;
}
@Override @Override
public void addListener(EventListener l) { public void addListener(EventListener l) {
@@ -29,6 +35,8 @@ class EventBusImpl implements EventBus {
@Override @Override
public void broadcast(Event e) { public void broadcast(Event e) {
for (EventListener l : listeners) l.eventOccurred(e); eventExecutor.execute(() -> {
for (EventListener l : listeners) l.eventOccurred(e);
});
} }
} }

View File

@@ -1,6 +1,9 @@
package org.briarproject.bramble.event; package org.briarproject.bramble.event;
import org.briarproject.bramble.api.event.EventBus; import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventExecutor;
import java.util.concurrent.Executor;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -12,7 +15,7 @@ public class EventModule {
@Provides @Provides
@Singleton @Singleton
EventBus provideEventBus() { EventBus provideEventBus(@EventExecutor Executor eventExecutor) {
return new EventBusImpl(); return new EventBusImpl(eventExecutor);
} }
} }

View File

@@ -2,6 +2,7 @@ package org.briarproject.bramble.test;
import org.briarproject.bramble.BrambleJavaModule; import org.briarproject.bramble.BrambleJavaModule;
import org.briarproject.bramble.battery.DefaultBatteryManagerModule; import org.briarproject.bramble.battery.DefaultBatteryManagerModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.event.EventModule;
import org.briarproject.bramble.plugin.PluginModule; import org.briarproject.bramble.plugin.PluginModule;
import org.briarproject.bramble.plugin.tor.BridgeTest; import org.briarproject.bramble.plugin.tor.BridgeTest;
@@ -17,8 +18,9 @@ import dagger.Component;
BrambleJavaModule.class, BrambleJavaModule.class,
TestLifecycleModule.class, TestLifecycleModule.class,
DefaultBatteryManagerModule.class, DefaultBatteryManagerModule.class,
PluginModule.class, // needed for BackoffFactory DefaultEventExecutorModule.class,
EventModule.class, EventModule.class,
PluginModule.class, // needed for BackoffFactory
SystemModule.class, SystemModule.class,
}) })
public interface BrambleJavaIntegrationTestComponent { public interface BrambleJavaIntegrationTestComponent {

View File

@@ -8,6 +8,7 @@ import org.briarproject.bramble.crypto.CryptoExecutorModule;
import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.crypto.CryptoModule;
import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.data.DataModule;
import org.briarproject.bramble.db.DatabaseModule; import org.briarproject.bramble.db.DatabaseModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.event.EventModule;
import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.lifecycle.LifecycleModule; import org.briarproject.bramble.lifecycle.LifecycleModule;
@@ -46,6 +47,7 @@ import dagger.Component;
FeedModule.class, FeedModule.class,
DataModule.class, DataModule.class,
DatabaseModule.class, DatabaseModule.class,
DefaultEventExecutorModule.class,
EventModule.class, EventModule.class,
IdentityModule.class, IdentityModule.class,
LifecycleModule.class, LifecycleModule.class,

View File

@@ -6,6 +6,7 @@ import org.briarproject.bramble.crypto.CryptoExecutorModule;
import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.crypto.CryptoModule;
import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.data.DataModule;
import org.briarproject.bramble.db.DatabaseModule; import org.briarproject.bramble.db.DatabaseModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.event.EventModule;
import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.lifecycle.LifecycleModule; import org.briarproject.bramble.lifecycle.LifecycleModule;
@@ -45,6 +46,7 @@ import dagger.Component;
CryptoExecutorModule.class, CryptoExecutorModule.class,
DataModule.class, DataModule.class,
DatabaseModule.class, DatabaseModule.class,
DefaultEventExecutorModule.class,
EventModule.class, EventModule.class,
ForumModule.class, ForumModule.class,
GroupInvitationModule.class, GroupInvitationModule.class,

View File

@@ -6,6 +6,7 @@ import org.briarproject.bramble.crypto.CryptoExecutorModule;
import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.crypto.CryptoModule;
import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.data.DataModule;
import org.briarproject.bramble.db.DatabaseModule; import org.briarproject.bramble.db.DatabaseModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.event.EventModule;
import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.sync.SyncModule; import org.briarproject.bramble.sync.SyncModule;
@@ -37,6 +38,7 @@ import dagger.Component;
CryptoExecutorModule.class, CryptoExecutorModule.class,
DataModule.class, DataModule.class,
DatabaseModule.class, DatabaseModule.class,
DefaultEventExecutorModule.class,
EventModule.class, EventModule.class,
ForumModule.class, ForumModule.class,
IdentityModule.class, IdentityModule.class,

View File

@@ -13,6 +13,7 @@ import org.briarproject.bramble.contact.ContactModule;
import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.crypto.CryptoModule;
import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.data.DataModule;
import org.briarproject.bramble.db.DatabaseModule; import org.briarproject.bramble.db.DatabaseModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.event.EventModule;
import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.lifecycle.LifecycleModule; import org.briarproject.bramble.lifecycle.LifecycleModule;
@@ -46,6 +47,7 @@ import dagger.Component;
CryptoModule.class, CryptoModule.class,
DataModule.class, DataModule.class,
DatabaseModule.class, DatabaseModule.class,
DefaultEventExecutorModule.class,
EventModule.class, EventModule.class,
IdentityModule.class, IdentityModule.class,
LifecycleModule.class, LifecycleModule.class,

View File

@@ -15,6 +15,7 @@ import org.briarproject.bramble.crypto.CryptoExecutorModule;
import org.briarproject.bramble.crypto.CryptoModule; import org.briarproject.bramble.crypto.CryptoModule;
import org.briarproject.bramble.data.DataModule; import org.briarproject.bramble.data.DataModule;
import org.briarproject.bramble.db.DatabaseModule; import org.briarproject.bramble.db.DatabaseModule;
import org.briarproject.bramble.event.DefaultEventExecutorModule;
import org.briarproject.bramble.event.EventModule; import org.briarproject.bramble.event.EventModule;
import org.briarproject.bramble.identity.IdentityModule; import org.briarproject.bramble.identity.IdentityModule;
import org.briarproject.bramble.lifecycle.LifecycleModule; import org.briarproject.bramble.lifecycle.LifecycleModule;
@@ -63,6 +64,7 @@ import dagger.Component;
CryptoExecutorModule.class, CryptoExecutorModule.class,
DataModule.class, DataModule.class,
DatabaseModule.class, DatabaseModule.class,
DefaultEventExecutorModule.class,
EventModule.class, EventModule.class,
ForumModule.class, ForumModule.class,
GroupInvitationModule.class, GroupInvitationModule.class,

View File

@@ -21,6 +21,7 @@ import org.briarproject.bramble.api.system.Clock
import org.briarproject.bramble.api.system.LocationUtils import org.briarproject.bramble.api.system.LocationUtils
import org.briarproject.bramble.api.system.ResourceProvider import org.briarproject.bramble.api.system.ResourceProvider
import org.briarproject.bramble.battery.DefaultBatteryManagerModule import org.briarproject.bramble.battery.DefaultBatteryManagerModule
import org.briarproject.bramble.event.DefaultEventExecutorModule
import org.briarproject.bramble.network.JavaNetworkModule import org.briarproject.bramble.network.JavaNetworkModule
import org.briarproject.bramble.plugin.tor.CircumventionModule import org.briarproject.bramble.plugin.tor.CircumventionModule
import org.briarproject.bramble.plugin.tor.CircumventionProvider import org.briarproject.bramble.plugin.tor.CircumventionProvider
@@ -47,6 +48,7 @@ import javax.net.SocketFactory
JavaSystemModule::class, JavaSystemModule::class,
CircumventionModule::class, CircumventionModule::class,
DefaultBatteryManagerModule::class, DefaultBatteryManagerModule::class,
DefaultEventExecutorModule::class,
HeadlessBlogModule::class, HeadlessBlogModule::class,
HeadlessContactModule::class, HeadlessContactModule::class,
HeadlessEventModule::class, HeadlessEventModule::class,