[DEV] correct the problem of Week pointers...

This commit is contained in:
Edouard DUPIN 2021-06-07 15:25:33 +02:00
parent e6905e78a7
commit 72ed422467
22 changed files with 2785 additions and 613 deletions

View File

@ -6,4 +6,5 @@ open module org.atriasoft.esignal {
exports org.atriasoft.esignal;
requires transitive org.atriasoft.etk;
requires com.github.spotbugs.annotations;
}

View File

@ -6,13 +6,9 @@ public class Connection implements AutoCloseable {
protected WeakReference<ConnectionRemoveInterface> connection;
public void connectionIsRemovedBySignal() {
connection = null;
this.connection = null;
}
public void disconnect() {
close();
}
public Connection( final ConnectionRemoveInterface object ) {
this.connection = new WeakReference<>(object);
}

View File

@ -4,66 +4,134 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.atriasoft.esignal.internal.ConnectedElement;
import org.atriasoft.esignal.internal.ConnectedElementDynamic;
import org.atriasoft.esignal.internal.ConnectedElementInterface;
import org.atriasoft.esignal.internal.ConnectedElementTRefConsumerWeakConnection;
import org.atriasoft.esignal.internal.ConnectedElementTRefConsumerWeakObject;
import org.atriasoft.esignal.internal.ConnectedElementTWeakConsumer;
import org.atriasoft.esignal.internal.ConnectedElementURefConsumerWeakObject;
import org.atriasoft.esignal.internal.ConnectedElementURefConsumerWeakObjectWeakConnection;
import edu.umd.cs.findbugs.annotations.CheckReturnValue;
/**
* Generic interface for a signaling model...
*
* @param <T> generic Runnable, Consumer, or BiConsumer template...
*/
public class GenericSignal<T> implements ConnectionRemoveInterface {
public class GenericSignal<T, U> implements ConnectionRemoveInterface {
// List of all connected Links
protected List<ConnectedElement<T>> data = new ArrayList<>();
protected List<ConnectedElementInterface<T, U>> data = new ArrayList<>();
/**
* Clear all connection on this signal.
*/
public void clear() {
List<ConnectedElement<T>> data2 = this.data;
List<ConnectedElementInterface<T, U>> data2 = this.data;
synchronized(this.data) {
this.data = new ArrayList<>();
}
final Iterator<ConnectedElement<T>> iterator = data2.iterator();
final Iterator<ConnectedElementInterface<T, U>> iterator = data2.iterator();
while (iterator.hasNext()) {
final ConnectedElement<T> elem = iterator.next();
final ConnectedElementInterface<T, U> elem = iterator.next();
elem.disconnect();
}
}
/**
* Connect a Function to this signal
* Connect a Function to this signal (the signal will keep only the weak pointer on the function)
* @param function Function to connect (Keep a WeakReference on it only)
* @apiNote Make some attention when you connect a global lamba, nothing can pertmit to remove it @see connectAutoRemoveObject()
* @apiNote Make some attention when you connect a global lamba, nothing can permit to remove it @see connectAutoRemoveObject()
*
* {@code
* // Create the connection
* // (1) create connection (direct):
* ConsumerXX tmp = this::onEventXXX;
* eventXXX.connectWeak(tmp);
* // (2) create connection (lambda):
* ConsumerXX tmp = (www) -> { ... };
* eventXXX.connectWeak(tmp);
*
* // Disconnect:
* // (1) remove connection (abstract way):
* tmp = null; // ==> the function scope will be removed only when the garbage collector is called.
* // (2) remove the connection from signal:
* eventXXX.disconnect(tmp);
* }
* @apiNote You can be called while the Garbage collected does not removed the reference on the function or the lambda...
*/
public void connect(final T function) {
public void connectWeak(final T function) {
synchronized(this.data) {
this.data.add(new ConnectedElement<T>(function));
}
}
/**
* Disconnect all connection that have this Object/function in reference
* @param obj Object to check the compatibility.
* @apiNote if you add a direct connection like {code connect(this::onEvent(...)) } you can not disconnect it
*/
public void disconnect(final T obj) {
synchronized(this.data) {
final Iterator<ConnectedElement<T>> iterator = this.data.iterator();
while (iterator.hasNext()) {
final ConnectedElement<T> elem = iterator.next();
if (elem.isCompatibleWith(obj)) {
iterator.remove();
}
}
this.data.add(new ConnectedElementTWeakConsumer<T, U>(function));
}
}
/**
* Connect to the signal with a @see Connection object that permit to remove the connection to the signal.
* @param function Function to connect (Keep a WeakReference on it only)
* @return The connection interface.
* {@code
* // Create the connection
* // (1) create connection (direct):
* Connection tmp = eventXXX.connect(this::onEventXXX);
* // (2) create connection (lambda):
* Connection tmp = eventXXX.connect((www) -> { ... });
*
* // Disconnect:
* // (1) remove connection (abstract way):
* tmp = null; // ==> the function scope will be removed only when the garbage collector is called.
* // (2) remove the connection from signal:
* tmp.close(); // use close instead of disconnect ==> permit to detect error (Connection is AutoClosable)
* // (3) remove the connection from signal:
* eventXXX.disconnect(tmp);
* }
*/
public Connection connectDynamic(final T function) {
@CheckReturnValue
public Connection connect(final T function) {
Connection out = new Connection(this);
synchronized(this.data) {
this.data.add(new ConnectedElementDynamic<T>(out, function));
this.data.add(new ConnectedElementTRefConsumerWeakConnection<T, U>(out, function));
}
return out;
}
/**
* Connect to the signal with Input object as first parameter with a @see Connection object that permit to remove the connection to the signal.
* This permit to remove hidden capture of the "this" in the lambda...
* @param function Function to connect (Keep a WeakReference on it only)
* @return The connection interface.
* {@code
* class MyClass {
* Connection tmp = null;
* MyClass() {
* // Create the connection
* // (1) create connection (direct):
* tmp = eventXXX.connect(this, this::onEventXXX);
* // (2) create connection (lambda):
* tmp = eventXXX.connect((self, www) -> { ... });
* }
* public static onEventXXX(Object self, ...) {
* MyClass mySelf = (MyClass) self;
* ...
* }
* // Disconnect:
* public void disconnect() {
* // (1) remove connection (abstract way):
* tmp = null; // ==> the function scope will be removed only when the garbage collector is called.
* // (2) remove the connection from signal:
* tmp.close(); // use close instead of disconnect ==> permit to detect error (Connection is AutoClosable)
* // (3) remove the connection from signal:
* eventXXX.disconnect(tmp);
* // OR
* eventXXX.disconnect(this);
* }
* }
* }
*/
@CheckReturnValue
public Connection connect(final Object object, final U function) {
Connection out = new Connection(this);
synchronized(this.data) {
this.data.add(new ConnectedElementURefConsumerWeakObjectWeakConnection<T, U>(out, object, function));
}
return out;
}
@ -74,16 +142,47 @@ public class GenericSignal<T> implements ConnectionRemoveInterface {
*/
public void connectAutoRemoveObject(final Object object, final T function) {
synchronized(this.data) {
this.data.add(new ConnectedElementDynamic<T>(object, function));
this.data.add(new ConnectedElementTRefConsumerWeakObject<T, U>(object, function));
}
}
/**
* Connect to the signal and automatically disconnect when the object is removed
* @param object Object to check if remove to continue keeping the signal active (Keep a WeakReference on it only)
* @param function Function to connect (Keep a WeakReference on it only)
*/
public void connectAuto(final Object object, final U function) {
synchronized(this.data) {
this.data.add(new ConnectedElementURefConsumerWeakObject<T, U>(object, function));
}
}
/**
* Disconnect all connection that have this Object/function in reference
* @param obj Object to check the compatibility.
* @apiNote if you add a direct connection like {code connect(this::onEvent(...)) } you can not disconnect it
*/
public void disconnect(final T obj) {
synchronized(this.data) {
final Iterator<ConnectedElementInterface<T, U>> iterator = this.data.iterator();
while (iterator.hasNext()) {
final ConnectedElementInterface<T, U> elem = iterator.next();
if (elem.isCompatibleWith(obj)) {
iterator.remove();
}
}
}
}
@Override
public void disconnect(final Connection connection) {
synchronized(this.data) {
final Iterator<ConnectedElement<T>> iterator = this.data.iterator();
final Iterator<ConnectedElementInterface<T, U>> iterator = this.data.iterator();
while (iterator.hasNext()) {
final ConnectedElement<T> elem = iterator.next();
final ConnectedElementInterface<T, U> elem = iterator.next();
if (elem.isCompatibleWith(connection)) {
elem.disconnect();
iterator.remove();
@ -96,11 +195,11 @@ public class GenericSignal<T> implements ConnectionRemoveInterface {
* Get a copy on the List of current connection and remove all the deprecated connection.
* @return The copy of the available connection (Note: the connection can be removed when return)
*/
protected List<ConnectedElement<T>> getACleanedList() {
protected List<ConnectedElementInterface<T, U>> getACleanedList() {
// first clean the list
cleanedList();
// get a copy of elements
List<ConnectedElement<T>> out = null;
List<ConnectedElementInterface<T, U>> out = null;
// clean the list:
synchronized(this.data) {
// simple optimization:
@ -118,11 +217,13 @@ public class GenericSignal<T> implements ConnectionRemoveInterface {
protected void cleanedList() {
// clean the list:
synchronized(this.data) {
final Iterator<ConnectedElement<T>> iterator = this.data.iterator();
final Iterator<ConnectedElementInterface<T, U>> iterator = this.data.iterator();
while (iterator.hasNext()) {
final ConnectedElement<T> elem = iterator.next();
Object tmpObject = elem.getConsumer();
if (tmpObject == null) {
final ConnectedElementInterface<T, U> elem = iterator.next();
if (elem.isObjectDependent() && elem.lockObjects() == null) {
elem.disconnect();
iterator.remove();
} else if (elem.getConsumer() == null && elem.getConsumer2() == null) {
elem.disconnect();
iterator.remove();
}
@ -144,5 +245,52 @@ public class GenericSignal<T> implements ConnectionRemoveInterface {
cleanedList();
return this.data.size();
}
/**
* Connect a class with his hunction name
* @param object
* @param function
* @return
*/
// @CheckReturnValue
// public <U> Connection connect(final U object, final String function) {
// Type typeParam = (Class) ((T) getClass());
// Method[] listMethod = object.getClass().getMethods();
// Method findElem = null;
// for (int iii=0; iii<listMethod.length; iii++) {
// Method elem = listMethod[iii];
// if (elem.getName().equals(function)) {
// if (elem.getParameterCount() != 2) {
//
// } else {
// Parameter[] params = elem.getParameters();
// Parameter param = params[0];
// if (!param.getType().equals(object.getClass()) ) {
// // error
//
// } else {
//
// }
// param = params[1];
// if (! T.class.isAssignableFrom(param.getType()) ) {
// // error
//
// } else {
//
// }
//
// }
//
// }
// }
// Method out = object.getClass().getMethod(function, U.class, T.class );
// return null;
// }
// public void connectWeak(final T function) {
// public <U> void connectWeak(final U object, final T+1 function) {
// public Connection connect(final T function) {
// public <U> Connection connect(final U object, final T+1 function) {
// public <U> Connection connect(final U object, final String functionName) {
}

View File

@ -0,0 +1,102 @@
package org.atriasoft.esignal;
import java.util.function.BiConsumer;
public class GenericSignalInstrumented<T, U> extends GenericSignal<T, U> {
BiConsumer<Integer, Integer> callback = null;
/**
* Notify to the callback that the number of connection change
* @param sizeStart Number of connection before call
* @param sizeEnd Number of connection after call
*/
protected synchronized void notifyChange(final int sizeStart, final int sizeEnd) {
if (sizeEnd == sizeStart) {
return;
}
if (this.callback == null) {
return;
}
BiConsumer<Integer, Integer> cb = this.callback;
if (cb == null) {
this.callback = null;
return;
}
// notify client
cb.accept(sizeEnd, sizeEnd - sizeStart);
}
/**
* Specify the consumer that managed the dynamic connection handle change
* @param callback BiConsumer that receive the number of current connection and the delta of connection since the previous call.
*/
public synchronized void setCallBackNotification(final BiConsumer<Integer, Integer> callback) {
this.callback = callback;
}
@Override
public void clear() {
int sizeStart = this.data.size();
super.clear();
notifyChange(sizeStart, this.data.size());
}
@Override
public Connection connect(final T function) {
int sizeStart = this.data.size();
Connection tmp = super.connect(function);
notifyChange(sizeStart, this.data.size());
return tmp;
}
@Override
public void disconnect(final T obj) {
int sizeStart = this.data.size();
super.disconnect(obj);
notifyChange(sizeStart, this.data.size());
}
@Override
public void connectWeak(final T function) {
int sizeStart = this.data.size();
super.connectWeak(function);
notifyChange(sizeStart, this.data.size());
}
@Override
public Connection connect(final Object object, final U function) {
int sizeStart = this.data.size();
Connection out = super.connect(object, function);
notifyChange(sizeStart, this.data.size());
return out;
}
@Override
public void connectAuto(final Object object, final U function) {
int sizeStart = this.data.size();
super.connectAuto(object, function);
notifyChange(sizeStart, this.data.size());
}
@Override
public void connectAutoRemoveObject(final Object object, final T function) {
int sizeStart = this.data.size();
super.connectAutoRemoveObject(object, function);
notifyChange(sizeStart, this.data.size());
}
@Override
public void disconnect(final Connection connection) {
int sizeStart = this.data.size();
super.disconnect(connection);
notifyChange(sizeStart, this.data.size());
}
@Override
protected void cleanedList() {
int sizeStart = this.data.size();
super.cleanedList();
notifyChange(sizeStart, this.data.size());
}
}

View File

@ -0,0 +1,85 @@
package org.atriasoft.esignal;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.atriasoft.esignal.internal.ConnectedElementInterface;
import edu.umd.cs.findbugs.annotations.CheckReturnValue;
/**
* Simple interface to manage signal connection and disconnection with notification on connection change.
* @see Signal documentation
* <pre>{@code
* class EmiterSimple {
* public final ISignal<String> signalEvent = new ISignal<>();
* public EmiterSimple() {
* signalEvent.setCallBackNotification(this::onConnectionChange);
* }
* public void onConnectionChange(final int currentNumberConnection, final int deltaConnection) {
* Log.info("Number of connection Change : " + currentNumberConnection + " delta=" + deltaConnection);
* }
* }
* }</pre>
*
* @param <T> Type of the signal
*
*/
public class ISignal<T> extends GenericSignalInstrumented<Consumer<T>, BiConsumer<Object, T>> {
/**
* Emit a signal on all element connect (and clean the list of unlinked elements).
* @param value Value to set in parameter.
*/
public void emit(final T value) {
List<ConnectedElementInterface<Consumer<T>, BiConsumer<Object, T>>> tmp = getACleanedList();
if (tmp == null) {
return;
}
// real call elements
final Iterator<ConnectedElementInterface<Consumer<T>, BiConsumer<Object, T>>> iterator = tmp.iterator();
while (iterator.hasNext()) {
final ConnectedElementInterface<Consumer<T>, BiConsumer<Object, T>> elem = iterator.next();
Object remoteLockObject = elem.lockObjects();
if (elem.isObjectDependent() && remoteLockObject == null) {
continue;
}
Consumer<T> tmpConsumer = elem.getConsumer();
if (tmpConsumer != null) {
tmpConsumer.accept(value);
continue;
}
// Not a dead code, but very hard to simply test it.
BiConsumer<Object, T> tmpConsumer2 = elem.getConsumer2();
if (tmpConsumer2 != null) {
tmpConsumer2.accept(elem.getObject(), value);
}
}
}
/**
* Connect to the signal and automatically disconnect when the object is removed
* @param object Object to check if remove to continue keeping the signal active (Keep a WeakReference on it only)
* @param function Function to connect (Keep a WeakReference on it only)
*/
@SuppressWarnings("unchecked")
public <V> void connectAuto(final V object, final BiConsumer<V, T> function) {
connectAuto(object,
(final Object obj, final T value) -> {
function.accept((V)obj, value);
});
}
@CheckReturnValue
@SuppressWarnings("unchecked")
public <V> Connection connect(final V object, final BiConsumer<V, T> function) {
return connect(object,
(final Object obj, final T value) -> {
function.accept((V)obj, value);
});
}
}

View File

@ -0,0 +1,80 @@
package org.atriasoft.esignal;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import org.atriasoft.esignal.internal.ConnectedElementInterface;
import edu.umd.cs.findbugs.annotations.CheckReturnValue;
/**
* Simple interface to manage signal connection and disconnection with notification on connection change.
* @see SignalEmpty documentation
* <pre>{@code
* class EmiterSimple {
* public final ISignalEmpty signalEvent = new ISignalEmpty();
* public EmiterSimple() {
* signalEvent.setCallBackNotification(this::onConnectionChange);
* }
* public void onConnectionChange(final int currentNumberConnection, final int deltaConnection) {
* Log.info("Number of connection Change : " + currentNumberConnection + " delta=" + deltaConnection);
* }
* }
* }</pre>
*
*/
public class ISignalEmpty extends GenericSignalInstrumented<Runnable, Consumer<Object>> {
/**
* Emit a signal on all element connect (and clean the list of unlinked elements).
*/
public void emit() {
List<ConnectedElementInterface<Runnable, Consumer<Object>>> tmp = getACleanedList();
if (tmp == null) {
return;
}
// real call elements
final Iterator<ConnectedElementInterface<Runnable, Consumer<Object>>> iterator = tmp.iterator();
while (iterator.hasNext()) {
final ConnectedElementInterface<Runnable, Consumer<Object>> elem = iterator.next();
Object remoteLockObject = elem.lockObjects();
if (elem.isObjectDependent() && remoteLockObject == null) {
continue;
}
Runnable tmpConsumer = elem.getConsumer();
if (tmpConsumer != null) {
tmpConsumer.run();
continue;
}
// Not a dead code, but very hard to simply test it.
Consumer<Object> tmpConsumer2 = elem.getConsumer2();
if (tmpConsumer2 != null) {
tmpConsumer2.accept(elem.getObject());
}
}
}
/**
* Connect to the signal and automatically disconnect when the object is removed
* @param object Object to check if remove to continue keeping the signal active (Keep a WeakReference on it only)
* @param function Function to connect (Keep a WeakReference on it only)
*/
@SuppressWarnings("unchecked")
public <V> void connectAuto(final V object, final Consumer<V> function) {
connectAuto(object,
(final Object obj) -> {
function.accept((V)obj);
});
}
@CheckReturnValue
@SuppressWarnings("unchecked")
public <V> Connection connect(final V object, final Consumer<V> function) {
return connect(object,
(final Object obj) -> {
function.accept((V)obj);
});
}
}

View File

@ -2,9 +2,12 @@ package org.atriasoft.esignal;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.atriasoft.esignal.internal.ConnectedElement;
import org.atriasoft.esignal.internal.ConnectedElementInterface;
import edu.umd.cs.findbugs.annotations.CheckReturnValue;
/**
* Simple interface to manage signal connection and disconnection
@ -50,26 +53,56 @@ import org.atriasoft.esignal.internal.ConnectedElement;
* @param <T> Type of the signal
*
*/
public class Signal<T> extends GenericSignal<Consumer<T>> {
public class Signal<T> extends GenericSignal<Consumer<T>, BiConsumer<Object, T>> {
/**
* Emit a signal on all element connect (and clean the list of unlinked elements).
* @param value Value to set in parameter.
*/
public void emit(final T value) {
List<ConnectedElement<Consumer<T>>> tmp = getACleanedList();
List<ConnectedElementInterface<Consumer<T>, BiConsumer<Object, T>>> tmp = getACleanedList();
if (tmp == null) {
return;
}
// real call elements
final Iterator<ConnectedElement<Consumer<T>>> iterator = tmp.iterator();
final Iterator<ConnectedElementInterface<Consumer<T>, BiConsumer<Object, T>>> iterator = tmp.iterator();
while (iterator.hasNext()) {
final ConnectedElement<Consumer<T>> elem = iterator.next();
Consumer<T> tmpObject = elem.getConsumer();
if (tmpObject == null) {
// Not a dead code, but very hard to simply test it.
final ConnectedElementInterface<Consumer<T>, BiConsumer<Object, T>> elem = iterator.next();
Object remoteLockObject = elem.lockObjects();
if (elem.isObjectDependent() && remoteLockObject == null) {
continue;
}
tmpObject.accept(value);
Consumer<T> tmpConsumer = elem.getConsumer();
if (tmpConsumer != null) {
tmpConsumer.accept(value);
continue;
}
// Not a dead code, but very hard to simply test it.
BiConsumer<Object, T> tmpConsumer2 = elem.getConsumer2();
if (tmpConsumer2 != null) {
tmpConsumer2.accept(elem.getObject(), value);
}
}
}
/**
* Connect to the signal and automatically disconnect when the object is removed
* @param object Object to check if remove to continue keeping the signal active (Keep a WeakReference on it only)
* @param function Function to connect (Keep a WeakReference on it only)
*/
@SuppressWarnings("unchecked")
public <V> void connectAuto(final V object, final BiConsumer<V, T> function) {
connectAuto(object,
(final Object obj, final T value) -> {
function.accept((V)obj, value);
});
}
@CheckReturnValue
@SuppressWarnings("unchecked")
public <V> Connection connect(final V object, final BiConsumer<V, T> function) {
return connect(object,
(final Object obj, final T value) -> {
function.accept((V)obj, value);
});
}
}

View File

@ -1,78 +0,0 @@
package org.atriasoft.esignal;
import java.util.Iterator;
import java.util.List;
import java.util.function.BiConsumer;
import org.atriasoft.esignal.internal.ConnectedElement;
/**
* Simple interface to manage signal connection and disconnection
* <pre>{@code
* class EmiterSimple {
* public Signal2<String, Double> signalEvent = new Signal2<>();
* }
*
* class ReceiverSimple {
* public void onEvent(String data, Double data2) {
* Log.error("function receive: " + data + " " + data2);
* }
* public connectLambda(EmiterSimple other) {
* // Note : this lambda is reference a a global, then it will never removed in the connection list ==> refer the local class or @see connectAutoRemoveObject
* other.signalEvent.connect((data, data2) -> {
* Log.error("lambda receive: " + data + " " + data2);
* });
* }
* }
* // use :
* EmiterSimple aaa = new EmiterSimple();
* ReceiverSimple bbb = new ReceiverSimple();
* // Emit a signal:
* aaa.signalEvent.emit("My message ...", 16516.541654);
* // simple direct connection:
* aaa.signalEvent.connect(bbb::onEvent);
* //removable connection (2 possibilities:)
* // First solution (best way ==> does not need to lock a reference on the current object and the remote)
* {
* Connection connect = aaa.signalEvent.connectDynamic(bbb::onEvent());
* // disconnect
* connect.disconnect();
* }
* // Second solution
* {
* Consumer<?> connect = bbb::onEvent;
* aaa.signalEvent.connect(connect);
* // disconnect
* aaa.signalEvent.disconnect(connect);
* }
* }</pre>
*
* @param <T> First type of the signal
* @param <U> Second type of the signal
*
*/
public class Signal2<T, U> extends GenericSignal<BiConsumer<T, U>> {
/**
* Emit a signal on all element connect (and clean the list of unlinked elements).
* @param valueT First parameter value to emit.
* @param valueU Second parameter value to emit.
*/
public void emit(final T valueT, final U valueU) {
List<ConnectedElement<BiConsumer<T, U>>> tmp = getACleanedList();
if (tmp == null) {
return;
}
// real call elements
final Iterator<ConnectedElement<BiConsumer<T, U>>> iterator = tmp.iterator();
while (iterator.hasNext()) {
final ConnectedElement<BiConsumer<T, U>> elem = iterator.next();
BiConsumer<T, U> tmpObject = elem.getConsumer();
if (tmpObject == null) {
continue;
}
tmpObject.accept(valueT, valueU);
}
}
}

View File

@ -2,8 +2,11 @@ package org.atriasoft.esignal;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
import org.atriasoft.esignal.internal.ConnectedElement;
import org.atriasoft.esignal.internal.ConnectedElementInterface;
import edu.umd.cs.findbugs.annotations.CheckReturnValue;
/**
* Simple interface to manage signal connection and disconnection
@ -47,25 +50,57 @@ import org.atriasoft.esignal.internal.ConnectedElement;
* }</pre>
*
*/
public class SignalEmpty extends GenericSignal<Runnable> {
public class SignalEmpty extends GenericSignal<Runnable, Consumer<Object>> {
/**
* Emit a signal on all element connect (and clean the list of unlinked elements).
*/
public void emit() {
List<ConnectedElement<Runnable>> tmp = getACleanedList();
List<ConnectedElementInterface<Runnable, Consumer<Object>>> tmp = getACleanedList();
if (tmp == null) {
return;
}
// real call elements
final Iterator<ConnectedElement<Runnable>> iterator = tmp.iterator();
final Iterator<ConnectedElementInterface<Runnable, Consumer<Object>>> iterator = tmp.iterator();
while (iterator.hasNext()) {
final ConnectedElement<Runnable> elem = iterator.next();
Runnable tmpObject = elem.getConsumer();
if (tmpObject == null) {
final ConnectedElementInterface<Runnable, Consumer<Object>> elem = iterator.next();
Object remoteLockObject = elem.lockObjects();
if (elem.isObjectDependent() && remoteLockObject == null) {
continue;
}
tmpObject.run();
Runnable tmpConsumer = elem.getConsumer();
if (tmpConsumer != null) {
tmpConsumer.run();
continue;
}
// Not a dead code, but very hard to simply test it.
Consumer<Object> tmpConsumer2 = elem.getConsumer2();
if (tmpConsumer2 != null) {
tmpConsumer2.accept(elem.getObject());
}
}
}
/**
* Connect to the signal and automatically disconnect when the object is removed
* @param object Object to check if remove to continue keeping the signal active (Keep a WeakReference on it only)
* @param function Function to connect (Keep a WeakReference on it only)
*/
@SuppressWarnings("unchecked")
public <V> void connectAuto(final V object, final Consumer<V> function) {
connectAuto(object,
(final Object obj) -> {
function.accept((V)obj);
});
}
@CheckReturnValue
@SuppressWarnings("unchecked")
public <V> Connection connect(final V object, final Consumer<V> function) {
return connect(object,
(final Object obj) -> {
function.accept((V)obj);
});
}
}

View File

@ -0,0 +1,26 @@
package org.atriasoft.esignal.internal;
/**
* Connected element on a consumer to Manage event
*
* @param <T> Type Of the Signal
*/
public interface ConnectedElementInterface<T, U> {
default T getConsumer() { return null; }
default boolean isObjectDependent() { return false; }
default U getConsumer2() { return null; }
/**
* Lock an Object that keep a reference on all object that need to be alive while the call is done
* @return An unusable Object (just keep a reference on it.
*/
default Object lockObjects() { return null; }
default Object getObject() { return null; }
boolean isCompatibleWith(final Object elem);
/**
* Permit to remove connection on the associated signal.
*/
default void disconnect() {}
}

View File

@ -0,0 +1,32 @@
package org.atriasoft.esignal.internal;
/**
* Connected element on a consumer to Manage event
*
* @param <T> Type Of the Signal
*/
public class ConnectedElementTRefConsumer<T, U> implements ConnectedElementInterface<T, U> {
protected final T consumer;
public ConnectedElementTRefConsumer(final T consumer) {
this.consumer = consumer;
}
@Override
public T getConsumer() {
return this.consumer;
}
@Override
public boolean isCompatibleWith(final Object elem) {
if (this.consumer == elem) {
return true;
}
return false;
}
@Override
public void disconnect() {
}
}

View File

@ -0,0 +1,49 @@
package org.atriasoft.esignal.internal;
import java.lang.ref.WeakReference;
import org.atriasoft.esignal.Connection;
/**
* Connected element with a dependency of an other object to auto remove the signals
*
* @param <T> Type Of the Signal
*/
public class ConnectedElementTRefConsumerWeakConnection<T, U> extends ConnectedElementTRefConsumer<T, U> {
protected final WeakReference<Connection> linkedConnection;
public ConnectedElementTRefConsumerWeakConnection(final Connection linkedConnection, final T consumer) {
super(consumer);
this.linkedConnection = new WeakReference<Connection>(linkedConnection);
}
@Override
public boolean isObjectDependent() {
return true;
}
@Override
public Object lockObjects() {
return this.linkedConnection.get();
}
@Override
public boolean isCompatibleWith(final Object elem) {
if (super.isCompatibleWith(elem)) {
return true;
}
Object obj = this.linkedConnection.get();
if (obj == elem) {
return true;
}
return false;
}
@Override
public void disconnect() {
Connection con = this.linkedConnection.get();
if (con != null) {
con.connectionIsRemovedBySignal();
}
}
}

View File

@ -2,27 +2,31 @@ package org.atriasoft.esignal.internal;
import java.lang.ref.WeakReference;
import org.atriasoft.esignal.Connection;
/**
* Connected element with a dependency of an other object to auto remove the signals
*
* @param <T> Type Of the Signal
*/
public class ConnectedElementDynamic<T> extends ConnectedElement<T> {
public class ConnectedElementTRefConsumerWeakObject<T, U> extends ConnectedElementTRefConsumer<T, U> {
protected final WeakReference<Object> linkedObject;
public ConnectedElementDynamic(final Object linkedObject, final T consumer) {
public ConnectedElementTRefConsumerWeakObject(final Object linkedObject, final T consumer) {
super(consumer);
this.linkedObject = new WeakReference<Object>(linkedObject);
}
@Override
public boolean isObjectDependent() {
return true;
}
@Override
public T getConsumer() {
if (this.linkedObject.get() == null) {
return null;
}
return this.consumer.get();
public Object lockObjects() {
return this.linkedObject.get();
}
@Override
public Object getObject() {
return this.linkedObject.get();
}
@Override
@ -37,14 +41,4 @@ public class ConnectedElementDynamic<T> extends ConnectedElement<T> {
return false;
}
@Override
public void disconnect() {
Object obj = this.linkedObject.get();
if (obj == null) {
return;
}
if (obj instanceof Connection tmp) {
tmp.connectionIsRemovedBySignal();
}
}
}

View File

@ -7,17 +7,19 @@ import java.lang.ref.WeakReference;
*
* @param <T> Type Of the Signal
*/
public class ConnectedElement<T> {
public class ConnectedElementTWeakConsumer<T, U> implements ConnectedElementInterface<T, U> {
protected final WeakReference<T> consumer;
public ConnectedElement(final T consumer) {
public ConnectedElementTWeakConsumer(final T consumer) {
this.consumer = new WeakReference<T>(consumer);
}
@Override
public T getConsumer() {
return this.consumer.get();
}
@Override
public boolean isCompatibleWith(final Object elem) {
Object out = this.consumer.get();
if (out == elem) {
@ -26,7 +28,8 @@ public class ConnectedElement<T> {
return false;
}
@Override
public void disconnect() {
}
}
}

View File

@ -0,0 +1,51 @@
package org.atriasoft.esignal.internal;
import java.lang.ref.WeakReference;
/**
* Connected element on a consumer to Manage event
*
* @param <T> Type Of the Signal
* @param <U> Second type Of the Signal
*/
public class ConnectedElementURefConsumerWeakObject<T, U> implements ConnectedElementInterface<T, U> {
protected final U consumer;
protected final WeakReference<Object> linkedObject;
public ConnectedElementURefConsumerWeakObject(final Object linkedObject, final U consumer) {
this.consumer = consumer;
this.linkedObject = new WeakReference<Object>(linkedObject);
}
@Override
public boolean isObjectDependent() {
return true;
}
@Override
public U getConsumer2() {
return this.consumer;
}
@Override
public Object lockObjects() {
return this.linkedObject.get();
}
@Override
public Object getObject() {
return this.linkedObject.get();
}
@Override
public boolean isCompatibleWith(final Object elem) {
Object out = this.consumer;
if (out == elem) {
return true;
}
Object obj = this.linkedObject.get();
if (obj == elem) {
return true;
}
return false;
}
}

View File

@ -0,0 +1,51 @@
package org.atriasoft.esignal.internal;
import java.lang.ref.WeakReference;
import org.atriasoft.esignal.Connection;
record LockObject(Object aaa, Object bbb) {};
/**
* Connected element on a consumer to Manage event
*
* @param <T> Type Of the Signal
* @param <U> Second type Of the Signal
*/
public class ConnectedElementURefConsumerWeakObjectWeakConnection<T, U> extends ConnectedElementURefConsumerWeakObject<T, U> {
protected final WeakReference<Connection> linkedConnection;
public ConnectedElementURefConsumerWeakObjectWeakConnection(final Connection linkedConnection, final Object linkedObject, final U consumer) {
super(linkedObject, consumer);
this.linkedConnection = new WeakReference<Connection>(linkedConnection);
}
@Override
public Object lockObjects() {
Object tmp1 = this.linkedObject.get();
Object tmp2 = this.linkedConnection.get();
if (tmp1 != null && tmp2 != null) {
return new LockObject(tmp1, tmp2);
}
return null;
}
@Override
public boolean isCompatibleWith(final Object elem) {
if (super.isCompatibleWith(elem)) {
return true;
}
if (this.linkedConnection.get() == elem) {
return true;
}
return false;
}
@Override
public void disconnect() {
Connection con = this.linkedConnection.get();
if (con != null) {
con.connectionIsRemovedBySignal();
}
}
}

View File

@ -1,69 +0,0 @@
/*******************************************************************************
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Contributors:
* Edouard DUPIN - initial API and implementation
******************************************************************************/
package test.atriasoft.esignal;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
//import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import io.scenarium.logger.Logger;
@TestMethodOrder(OrderAnnotation.class)
public class TestBasicLog {
@Test
@Order(1)
public void aaFirstInitialisation() {
List<String> args = new ArrayList<>();
args.add("--log-level=999");
args.add("--log-level=1");
args.add("--log-no-color");
args.add("--log-color");
args.add("--log-lib=sc-log-test+6");
args.add("--log-lib=sc-log-test/6");
args.add("--log-lib=sc-log-test:6");
args.add("--log-lib=sc-log-test:verbose");
args.add("--log-lib=sc-log-test2+3");
args.add("--log-lib=sc-log-test");
args.add("--log-with-stupid-parameter=sdkfjsqdlkf");
args.add("--help");
Logger.init(args);
}
@Test
@Order(2)
public void bbSecondInitialisation() {
List<String> args = new ArrayList<>();
Logger.init(args);
}
@Test
@Order(3)
public void ccBasicLogCall() {
Log.print("Simple print");
Log.todo("Simple todo");
Log.error("Simple error");
Log.warning("Simple warning");
Log.info("Simple info");
Log.debug("Simple debug");
Log.verbose("Simple verbose");
}
@Test
@Order(4)
public void eeUsage() {
Logger.usage();
}
}

View File

@ -0,0 +1,649 @@
/*******************************************************************************
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Contributors:
* Edouard DUPIN - initial API and implementation
******************************************************************************/
package test.atriasoft.esignal;
import java.lang.ref.WeakReference;
import java.util.function.Consumer;
import org.atriasoft.esignal.Connection;
import org.atriasoft.esignal.ISignal;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
//import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(OrderAnnotation.class)
public class TestISignal {
class EmiterSimple {
public ISignal<String> signalEvent = new ISignal<String>();
public int currentNumberConnection = 0;
public int deltaConnection = 0;
public EmiterSimple() {
this.signalEvent.setCallBackNotification(this::onConnectionChange);
}
public void onConnectionChange(final int currentNumberConnection, final int deltaConnection) {
Log.info(">>>>> Number of connection Change : " + currentNumberConnection + " delta=" + deltaConnection);
this.currentNumberConnection = currentNumberConnection;
this.deltaConnection = deltaConnection;
}
public void sendEvent(final String value) {
this.signalEvent.emit(value);
}
}
static class ReceiverSimple implements AutoCloseable {
private String dataReceive = null;
ReceiverSimple() {
}
// record consumer
private Consumer<String> tmpConsumer1 = null;
private Connection tmpConnect = null;
@Override
public void close() {
this.tmpConsumer1 = null;
if (this.tmpConnect != null) {
this.tmpConnect.close();
this.tmpConnect = null;
}
this.dataReceive = null;
}
public void disconnectConnection() {
this.tmpConnect.close();
}
public boolean isConnected() {
return this.tmpConnect.isConnected();
}
public void connect1(final EmiterSimple other) {
WeakReference<ReceiverSimple> self = new WeakReference<ReceiverSimple>(this);
this.tmpConnect = other.signalEvent.connect(data -> {
self.get().onData(data);
});
System.gc();
}
public void connect2(final EmiterSimple other) {
// the solo lambda will not depend on the object => the remove must be done manually...
this.tmpConnect = other.signalEvent.connect(data -> {
Log.error("lambda receive: " + data);
});
System.gc();
}
public void connect3(final EmiterSimple other) {
// we reference the local object, then the lambda is alive while the object is alive...
this.tmpConnect =other.signalEvent.connect(data -> {
Log.error("lambda receive: " + data);
this.dataReceive = data;
});
System.gc();
}
public void connect4(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(data -> {
onData(data);
});
System.gc();
}
public void connect5(final EmiterSimple other) {
this.tmpConsumer1 = this::onData;
other.signalEvent.connectWeak(this.tmpConsumer1);
System.gc();
}
public void disconnectConsumer1(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConsumer1);
this.tmpConsumer1 = null;
}
public void connect6(final EmiterSimple other) {
// the solo lambda will not depend on the object => the remove must be done manually...
other.signalEvent.connectAutoRemoveObject(this, data -> {
Log.error("lambda receive: " + data);
});
System.gc();
}
public void connect7(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this::onData);
System.gc();
}
public void disconnect7(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConnect);
}
public void onData(final String data) {
Log.error("Retrive data : " + data);
this.dataReceive = data;
}
public void connect8(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, ReceiverSimple::onDataStatic);
System.gc();
}
public void connect9(final EmiterSimple other) {
other.signalEvent.connectAuto(this, ReceiverSimple::onDataStatic);
System.gc();
}
public static void onDataStatic(final Object local, final String data) {
ReceiverSimple self = (ReceiverSimple)local;
Log.error("Retrive data : " + data);
self.dataReceive = data;
}
public void connect10(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, ReceiverSimple::onDataStatic2);
System.gc();
}
public void connect11(final EmiterSimple other) {
other.signalEvent.connectAuto(this, ReceiverSimple::onDataStatic2);
System.gc();
}
public static void onDataStatic2(final ReceiverSimple self, final String data) {
Log.error("Retrive data : " + data);
self.dataReceive = data;
}
public void connect12(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, (final ReceiverSimple self, final String data) -> {
Log.error("Retrive data : " + data);
self.dataReceive = data;
});
System.gc();
}
public void connect13(final EmiterSimple other) {
other.signalEvent.connectAuto(this, (final ReceiverSimple self, final String data) -> {
Log.error("Retrive data : " + data);
self.dataReceive = data;
});
System.gc();
}
public String getDataAndClean() {
String tmp = this.dataReceive;
this.dataReceive = null;
return tmp;
}
}
@Test
@Order(1)
public void testConnectAndTransmit1() {
Log.warning("Test 1 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect1(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
receiver = null;
Assertions.assertEquals(1, sender.signalEvent.size());
System.gc();
String testData2 = "MUST NOT receive this data...";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(0, sender.currentNumberConnection);
Assertions.assertEquals(-1, sender.deltaConnection);
Log.warning("Test 1 [ END ]");
}
@Test
@Order(2)
public void testConnectAndTransmit2() {
Log.warning("Test 2 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect2(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1);
// No data stored ... assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// !!!! NO need to close lambda does not capture the THIS
receiver = null;
System.gc();
String testData2 = "Solo Lambda MUST receive this data...";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(0, sender.currentNumberConnection);
Assertions.assertEquals(-1, sender.deltaConnection);
Log.warning("Test 2 [ END ]");
}
@Test
@Order(3)
public void testConnectAndTransmit3() {
Log.warning("Test 3 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect3(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
// Need to close ==> capture Of this
receiver.close();
receiver = null;
System.gc();
String testData2 = "MUST NOT receive this data...";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(0, sender.currentNumberConnection);
Assertions.assertEquals(-1, sender.deltaConnection);
Log.warning("Test 3 [ END ]");
}
@Test
@Order(4)
public void testConnectAndTransmit4() {
Log.warning("Test 4 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect4(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close ==> capture Of this
receiver.close();
receiver = null;
System.gc();
String testData2 = "MUST NOT receive this data...";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 4 [ END ]");
}
@Test
@Order(5)
public void testConnectAndTransmit5() {
Log.warning("Test 5 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect5(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection
receiver.disconnectConsumer1(sender);
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect5(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// No need to close ==> the capture seams does not increase the cumber of Reference ....
// check auto remove...
receiver = null;
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 5 [ END ]");
}
@Test
@Order(6)
public void testConnectAndTransmit6() {
Log.warning("Test 6 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect6(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1);
//assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
receiver = null;
System.gc();
String testData2 = "MUST NOT receive this data...";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 6 [ END ]");
}
@Test
@Order(7)
public void testConnectAndTransmit7() {
Log.warning("Test 7 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnect7(sender);
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData5 = "MUST receive this data... 555";
sender.sendEvent(testData5);
Assertions.assertEquals(testData5, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close to prevent miss removing of connection.
receiver.close();
// check auto remove...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 7 [ END ]");
}
@Test
@Order(8)
public void testConnectAndTransmit8() {
Log.warning("Test 8 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData5 = "MUST receive this data... 555";
sender.sendEvent(testData5);
Assertions.assertEquals(testData5, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 8 [ END ]");
}
@Test
@Order(9)
public void testConnectAndTransmit9() {
Log.warning("Test 9 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect9(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 9 [ END ]");
}
@Test
@Order(10)
public void testConnectAndTransmit10() {
Log.warning("Test 10 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData5 = "MUST receive this data... 555";
sender.sendEvent(testData5);
Assertions.assertEquals(testData5, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 10 [ END ]");
}
@Test
@Order(11)
public void testConnectAndTransmit11() {
Log.warning("Test 11 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect11(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 11 [ END ]");
}
@Test
@Order(12)
public void testConnectAndTransmit12() {
Log.warning("Test 12 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData5 = "MUST receive this data... 555";
sender.sendEvent(testData5);
Assertions.assertEquals(testData5, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 12 [ END ]");
}
@Test
@Order(13)
public void testConnectAndTransmit13() {
Log.warning("Test 13 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect13(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 131";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 13 [ END ]");
}
@Test
public void testClearConnection() {
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.signalEvent.clear();
}
}

View File

@ -0,0 +1,683 @@
/*******************************************************************************
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Contributors:
* Edouard DUPIN - initial API and implementation
******************************************************************************/
package test.atriasoft.esignal;
import java.lang.ref.WeakReference;
import org.atriasoft.esignal.Connection;
import org.atriasoft.esignal.ISignalEmpty;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
//import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(OrderAnnotation.class)
public class TestISignalEmpty {
class EmiterSimple {
public ISignalEmpty signalEvent = new ISignalEmpty();
public int currentNumberConnection = 0;
public int deltaConnection = 0;
public EmiterSimple() {
this.signalEvent.setCallBackNotification(this::onConnectionChange);
}
public void onConnectionChange(final int currentNumberConnection, final int deltaConnection) {
Log.info(">>>>> Number of connection Change : " + currentNumberConnection + " delta=" + deltaConnection);
this.currentNumberConnection = currentNumberConnection;
this.deltaConnection = deltaConnection;
}
public void sendEvent() {
this.signalEvent.emit();
}
}
static class ReceiverSimple implements AutoCloseable {
private boolean dataReceive = false;
ReceiverSimple() {
}
// record consumer
private Runnable tmpConsumer1 = null;
private Connection tmpConnect = null;
@Override
public void close() {
this.tmpConsumer1 = null;
if (this.tmpConnect != null) {
this.tmpConnect.close();
this.tmpConnect = null;
}
this.dataReceive = false;
}
public void disconnectConnection() {
this.tmpConnect.close();
}
public boolean isConnected() {
return this.tmpConnect.isConnected();
}
public void connect1(final EmiterSimple other) {
WeakReference<ReceiverSimple> self = new WeakReference<ReceiverSimple>(this);
this.tmpConnect = other.signalEvent.connect(() -> {
self.get().onData();
});
System.gc();
}
public void connect2(final EmiterSimple other) {
// the solo lambda will not depend on the object => the remove must be done manually...
this.tmpConnect = other.signalEvent.connect(() -> {
Log.error("lambda receive: ");
});
System.gc();
}
public void connect3(final EmiterSimple other) {
// we reference the local object, then the lambda is alive while the object is alive...
this.tmpConnect =other.signalEvent.connect(() -> {
Log.error("lambda receive: ");
this.dataReceive = true;
});
System.gc();
}
public void connect4(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(() -> {
onData();
});
System.gc();
}
public void connect5(final EmiterSimple other) {
this.tmpConsumer1 = this::onData;
other.signalEvent.connectWeak(this.tmpConsumer1);
System.gc();
}
public void disconnectConsumer1(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConsumer1);
this.tmpConsumer1 = null;
}
public void connect6(final EmiterSimple other) {
// the solo lambda will not depend on the object => the remove must be done manually...
other.signalEvent.connectAutoRemoveObject(this, () -> {
Log.error("lambda receive: ");
});
System.gc();
}
public void connect7(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this::onData);
System.gc();
}
public void disconnect7(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConnect);
}
public void onData() {
Log.error("Retrive data : ");
this.dataReceive = true;
}
public void connect8(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, ReceiverSimple::onDataStatic);
System.gc();
}
public void connect9(final EmiterSimple other) {
other.signalEvent.connectAuto(this, ReceiverSimple::onDataStatic);
System.gc();
}
public static void onDataStatic(final Object local) {
ReceiverSimple self = (ReceiverSimple)local;
Log.error("Retrive data : ");
self.dataReceive = true;
}
public void connect10(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, ReceiverSimple::onDataStatic2);
System.gc();
}
public void connect11(final EmiterSimple other) {
other.signalEvent.connectAuto(this, ReceiverSimple::onDataStatic2);
System.gc();
}
public static void onDataStatic2(final ReceiverSimple self) {
Log.error("Retrive data : ");
self.dataReceive = true;
}
public void connect12(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, (final ReceiverSimple self) -> {
Log.error("Retrive data : ");
self.dataReceive = true;
});
System.gc();
}
public void connect13(final EmiterSimple other) {
other.signalEvent.connectAuto(this, (final ReceiverSimple self) -> {
Log.error("Retrive data : ");
self.dataReceive = true;
});
System.gc();
}
public boolean getDataAndClean() {
boolean tmp = this.dataReceive;
this.dataReceive = false;
return tmp;
}
}
@Test
@Order(1)
public void testConnectAndTransmit1() {
Log.warning("Test 1 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect1(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
receiver = null;
Assertions.assertEquals(1, sender.signalEvent.size());
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 1 [ END ]");
}
@Test
@Order(2)
public void testConnectAndTransmit2() {
Log.warning("Test 2 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect2(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
// No data stored ... assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// !!!! NO need to close lambda does not capture the THIS
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 2 [ END ]");
}
@Test
@Order(3)
public void testConnectAndTransmit3() {
Log.warning("Test 3 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect3(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close ==> capture Of this
receiver.close();
receiver = null;
System.gc();
Assertions.assertEquals(0, sender.currentNumberConnection);
Assertions.assertEquals(-1, sender.deltaConnection);
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 3 [ END ]");
}
@Test
@Order(4)
public void testConnectAndTransmit4() {
Log.warning("Test 4 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect4(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close ==> capture Of this
receiver.close();
receiver = null;
System.gc();
Assertions.assertEquals(0, sender.currentNumberConnection);
Assertions.assertEquals(-1, sender.deltaConnection);
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 4 [ END ]");
}
@Test
@Order(5)
public void testConnectAndTransmit5() {
Log.warning("Test 5 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect5(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection
receiver.disconnectConsumer1(sender);
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
sender.sendEvent();
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect5(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// No need to close ==> the capture seams does not increase the cumber of Reference ....
// check auto remove...
receiver = null;
System.gc();
Assertions.assertEquals(1, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
sender.sendEvent();
Assertions.assertEquals(0, sender.currentNumberConnection);
Assertions.assertEquals(-1, sender.deltaConnection);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 5 [ END ]");
}
@Test
@Order(6)
public void testConnectAndTransmit6() {
Log.warning("Test 6 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect6(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
//assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 6 [ END ]");
}
@Test
@Order(7)
public void testConnectAndTransmit7() {
Log.warning("Test 7 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnect7(sender);
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
sender.sendEvent();
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close to prevent miss removing of connection.
receiver.close();
// check auto remove...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 7 [ END ]");
}
@Test
@Order(8)
public void testConnectAndTransmit8() {
Log.warning("Test 8 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
sender.sendEvent();
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 8 [ END ]");
}
@Test
@Order(9)
public void testConnectAndTransmit9() {
Log.warning("Test 9 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect9(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 9 [ END ]");
}
@Test
@Order(10)
public void testConnectAndTransmit10() {
Log.warning("Test 10 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
sender.sendEvent();
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 10 [ END ]");
}
@Test
@Order(11)
public void testConnectAndTransmit11() {
Log.warning("Test 11 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect11(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 11 [ END ]");
}
@Test
@Order(12)
public void testConnectAndTransmit12() {
Log.warning("Test 12 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
sender.sendEvent();
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 12 [ END ]");
}
@Test
@Order(13)
public void testConnectAndTransmit13() {
Log.warning("Test 13 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect13(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 13 [ END ]");
}
@Test
public void testEmptyConnection() {
Log.warning("Test 8 [BEGIN]");
Connection con = new Connection();
Assertions.assertEquals(false, con.isConnected());
con.close();
Log.warning("Test 8 [ END ]");
}
@Test
public void testClearConnection() {
Log.warning("Test 9 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect7(sender);
Assertions.assertEquals(1, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
receiver.connect5(sender);
Assertions.assertEquals(2, sender.currentNumberConnection);
Assertions.assertEquals(1, sender.deltaConnection);
Assertions.assertEquals(2, sender.signalEvent.size());
sender.signalEvent.clear();
Assertions.assertEquals(0, sender.currentNumberConnection);
Assertions.assertEquals(-2, sender.deltaConnection);
Log.warning("Test 9 [ END ]");
}
@Test
public void testDisconnectionRemovedSignal() {
Log.warning("Test 10 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender = null;
System.gc();
Assertions.assertEquals(false, receiver.isConnected());
receiver.close();
Log.warning("Test 10 [ END ]");
}
}

View File

@ -30,44 +30,68 @@ public class TestSignal {
this.signalEvent.emit(value);
}
}
class ReceiverSimple {
static class ReceiverSimple implements AutoCloseable {
private String dataReceive = null;
ReceiverSimple() {
}
// record consumer
private Consumer<String> tmpConsumer1 = null;
private Connection tmpConnect = null;
@Override
public void close() {
this.tmpConsumer1 = null;
if (this.tmpConnect != null) {
this.tmpConnect.close();
this.tmpConnect = null;
}
this.dataReceive = null;
}
public void disconnectConnection() {
this.tmpConnect.close();
}
public boolean isConnected() {
return this.tmpConnect.isConnected();
}
public void connect1(final EmiterSimple other) {
WeakReference<ReceiverSimple> tmpp = new WeakReference<ReceiverSimple>(this);
other.signalEvent.connect(data -> {
tmpp.get().onData(data);
WeakReference<ReceiverSimple> self = new WeakReference<ReceiverSimple>(this);
this.tmpConnect = other.signalEvent.connect(data -> {
self.get().onData(data);
});
System.gc();
}
public void connect2(final EmiterSimple other) {
// the solo lambda will not depend on the object => the remove must be done manually...
other.signalEvent.connect(data -> {
this.tmpConnect = other.signalEvent.connect(data -> {
Log.error("lambda receive: " + data);
});
System.gc();
}
public void connect3(final EmiterSimple other) {
// we reference the local object, then the lambda is alive while the object is alive...
other.signalEvent.connect(data -> {
this.tmpConnect =other.signalEvent.connect(data -> {
Log.error("lambda receive: " + data);
this.dataReceive = data;
});
System.gc();
}
public void connect4(final EmiterSimple other) {
other.signalEvent.connect(data -> {
this.tmpConnect = other.signalEvent.connect(data -> {
onData(data);
});
System.gc();
}
// record consumer
private Consumer<String> tmpConsumer = null;
public void connect5(final EmiterSimple other) {
this.tmpConsumer = this::onData;
other.signalEvent.connect(this.tmpConsumer);
this.tmpConsumer1 = this::onData;
other.signalEvent.connectWeak(this.tmpConsumer1);
System.gc();
}
public void disconnect5(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConsumer);
this.tmpConsumer = null;
public void disconnectConsumer1(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConsumer1);
this.tmpConsumer1 = null;
}
public void connect6(final EmiterSimple other) {
@ -75,28 +99,76 @@ public class TestSignal {
other.signalEvent.connectAutoRemoveObject(this, data -> {
Log.error("lambda receive: " + data);
});
System.gc();
}
private Connection tmpConnect = null;
public void connect7(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connectDynamic(this::onData);
this.tmpConnect = other.signalEvent.connect(this::onData);
System.gc();
}
public void disconnect7(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConnect);
}
public void disconnect72() {
this.tmpConnect.disconnect();
}
public boolean isConnected() {
return this.tmpConnect.isConnected();
}
public void onData(final String data) {
Log.error("Retrive data : " + data);
this.dataReceive = data;
}
public void connect8(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, ReceiverSimple::onDataStatic);
System.gc();
}
public void connect9(final EmiterSimple other) {
other.signalEvent.connectAuto(this, ReceiverSimple::onDataStatic);
System.gc();
}
public static void onDataStatic(final Object local, final String data) {
ReceiverSimple self = (ReceiverSimple)local;
Log.error("Retrive data : " + data);
self.dataReceive = data;
}
public void connect10(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, ReceiverSimple::onDataStatic2);
System.gc();
}
public void connect11(final EmiterSimple other) {
other.signalEvent.connectAuto(this, ReceiverSimple::onDataStatic2);
System.gc();
}
public static void onDataStatic2(final ReceiverSimple self, final String data) {
Log.error("Retrive data : " + data);
self.dataReceive = data;
}
public void connect12(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, (final ReceiverSimple self, final String data) -> {
Log.error("Retrive data : " + data);
self.dataReceive = data;
});
System.gc();
}
public void connect13(final EmiterSimple other) {
other.signalEvent.connectAuto(this, (final ReceiverSimple self, final String data) -> {
Log.error("Retrive data : " + data);
self.dataReceive = data;
});
System.gc();
}
public String getDataAndClean() {
String tmp = this.dataReceive;
this.dataReceive = null;
@ -136,12 +208,13 @@ public class TestSignal {
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1);
// No data stored ... assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.signalEvent.size());
// !!!! NO need to close lambda does not capture the THIS
receiver = null;
System.gc();
String testData2 = "Solo Lambda MUST receive this data...";
sender.sendEvent(testData2);
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 2 [ END ]");
}
@ -156,7 +229,9 @@ public class TestSignal {
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close ==> capture Of this
receiver.close();
receiver = null;
System.gc();
String testData2 = "MUST NOT receive this data...";
@ -178,6 +253,8 @@ public class TestSignal {
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close ==> capture Of this
receiver.close();
receiver = null;
System.gc();
String testData2 = "MUST NOT receive this data...";
@ -201,7 +278,7 @@ public class TestSignal {
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection
receiver.disconnect5(sender);
receiver.disconnectConsumer1(sender);
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
@ -214,6 +291,7 @@ public class TestSignal {
sender.sendEvent(testData3);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// No need to close ==> the capture seams does not increase the cumber of Reference ....
// check auto remove...
receiver = null;
System.gc();
@ -275,7 +353,7 @@ public class TestSignal {
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnect72();
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
@ -289,6 +367,8 @@ public class TestSignal {
sender.sendEvent(testData5);
Assertions.assertEquals(testData5, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close to prevent miss removing of connection.
receiver.close();
// check auto remove...
receiver = null;
System.gc();
@ -299,6 +379,240 @@ public class TestSignal {
}
@Test
@Order(8)
public void testConnectAndTransmit8() {
Log.warning("Test 8 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData5 = "MUST receive this data... 555";
sender.sendEvent(testData5);
Assertions.assertEquals(testData5, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 8 [ END ]");
}
@Test
@Order(9)
public void testConnectAndTransmit9() {
Log.warning("Test 9 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect9(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 9 [ END ]");
}
@Test
@Order(10)
public void testConnectAndTransmit10() {
Log.warning("Test 10 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData5 = "MUST receive this data... 555";
sender.sendEvent(testData5);
Assertions.assertEquals(testData5, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 10 [ END ]");
}
@Test
@Order(11)
public void testConnectAndTransmit11() {
Log.warning("Test 11 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect11(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 11 [ END ]");
}
@Test
@Order(12)
public void testConnectAndTransmit12() {
Log.warning("Test 12 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData5 = "MUST receive this data... 555";
sender.sendEvent(testData5);
Assertions.assertEquals(testData5, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 12 [ END ]");
}
@Test
@Order(13)
public void testConnectAndTransmit13() {
Log.warning("Test 13 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect13(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 131";
sender.sendEvent(testData1);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 13 [ END ]");
}
@Test
public void testClearConnection() {
EmiterSimple sender = new EmiterSimple();

View File

@ -1,311 +0,0 @@
/*******************************************************************************
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Contributors:
* Edouard DUPIN - initial API and implementation
******************************************************************************/
package test.atriasoft.esignal;
import java.lang.ref.WeakReference;
import java.util.function.BiConsumer;
import org.atriasoft.esignal.Connection;
import org.atriasoft.esignal.Signal2;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
//import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
@TestMethodOrder(OrderAnnotation.class)
public class TestSignal2 {
class EmiterSimple {
public Signal2<String, Double> signalEvent = new Signal2<>();
public void sendEvent(final String value, final double valueD) {
this.signalEvent.emit(value, valueD);
}
}
class ReceiverSimple {
private String dataReceive = null;
ReceiverSimple() {
}
public void connect1(final EmiterSimple other) {
WeakReference<ReceiverSimple> tmpp = new WeakReference<ReceiverSimple>(this);
other.signalEvent.connect((data, data2) -> {
tmpp.get().onData(data, data2);
});
}
public void connect2(final EmiterSimple other) {
// the solo lambda will not depend on the object => the remove must be done manually...
other.signalEvent.connect((data, data2) -> {
Log.error("lambda receive: " + data + " " + data2);
});
}
public void connect3(final EmiterSimple other) {
// we reference the local object, then the lambda is alive while the object is alive...
other.signalEvent.connect((data, data2) -> {
Log.error("lambda receive: " + data + " " + data2);
this.dataReceive = data;
});
}
public void connect4(final EmiterSimple other) {
other.signalEvent.connect((data, data2) -> {
onData(data, data2);
});
}
// record consumer
private BiConsumer<String, Double> tmpConsumer = null;
public void connect5(final EmiterSimple other) {
this.tmpConsumer = this::onData;
other.signalEvent.connect(this.tmpConsumer);
}
public void disconnect5(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConsumer);
this.tmpConsumer = null;
}
public void connect6(final EmiterSimple other) {
// the solo lambda will not depend on the object => the remove must be done manually...
other.signalEvent.connectAutoRemoveObject(this, (data, data2) -> {
Log.error("lambda receive: " + data + " " + data2);
});
}
private Connection tmpConnect = null;
public void connect7(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connectDynamic(this::onData);
}
public void disconnect7(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConnect);
}
public void disconnect72() {
this.tmpConnect.disconnect();
}
public boolean isConnected() {
return this.tmpConnect.isConnected();
}
public void onData(final String data, final double data2) {
Log.error("Retrive data : " + data);
this.dataReceive = data;
}
public String getDataAndClean() {
String tmp = this.dataReceive;
this.dataReceive = null;
return tmp;
}
}
@Test
@Order(1)
public void testConnectAndTransmit1() {
Log.warning("Test 1 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect1(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1, 15);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
receiver = null;
Assertions.assertEquals(1, sender.signalEvent.size());
System.gc();
String testData2 = "MUST NOT receive this data...";
sender.sendEvent(testData2, 16);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 1 [ END ]");
}
@Test
@Order(2)
public void testConnectAndTransmit2() {
Log.warning("Test 2 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect2(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1, 17);
// No data stored ... assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
receiver = null;
System.gc();
String testData2 = "Solo Lambda MUST receive this data...";
sender.sendEvent(testData2, 18);
Assertions.assertEquals(1, sender.signalEvent.size());
Log.warning("Test 2 [ END ]");
}
@Test
@Order(3)
public void testConnectAndTransmit3() {
Log.warning("Test 3 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect3(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1, 19);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
receiver = null;
System.gc();
String testData2 = "MUST NOT receive this data...";
sender.sendEvent(testData2, 20);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 3 [ END ]");
}
@Test
@Order(4)
public void testConnectAndTransmit4() {
Log.warning("Test 4 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect4(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1, 21);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
receiver = null;
System.gc();
String testData2 = "MUST NOT receive this data...";
sender.sendEvent(testData2, 22);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 4 [ END ]");
}
@Test
@Order(5)
public void testConnectAndTransmit5() {
Log.warning("Test 5 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect5(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1, 23);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection
receiver.disconnect5(sender);
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2, 24);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect5(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3, 25);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4, 26);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 5 [ END ]");
}
@Test
@Order(6)
public void testConnectAndTransmit6() {
Log.warning("Test 6 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
receiver.connect6(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data...";
sender.sendEvent(testData1, 27);
//assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
receiver = null;
System.gc();
String testData2 = "MUST NOT receive this data...";
sender.sendEvent(testData2, 28);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 6 [ END ]");
}
@Test
@Order(7)
public void testConnectAndTransmit7() {
Log.warning("Test 7 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData1 = "MUST receive this data... 111";
sender.sendEvent(testData1, 29);
Assertions.assertEquals(testData1, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnect7(sender);
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
String testData2 = "MUST NOT receive this data... 222";
sender.sendEvent(testData2, 30);
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData3 = "MUST receive this data... 333";
sender.sendEvent(testData3, 31);
Assertions.assertEquals(testData3, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnect72();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
String testData4 = "MUST NOT receive this data... 444";
sender.sendEvent(testData4, 32);
Assertions.assertEquals(null, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
String testData5 = "MUST receive this data... 555";
sender.sendEvent(testData5, 33);
Assertions.assertEquals(testData5, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
String testData6 = "MUST NOT receive this data... 666";
sender.sendEvent(testData6, 34);
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 7 [ END ]");
}
@Test
public void testClearConnection() {
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.signalEvent.clear();
}
}

View File

@ -29,43 +29,68 @@ public class TestSignalEmpty {
this.signalEvent.emit();
}
}
class ReceiverSimple {
static class ReceiverSimple implements AutoCloseable {
private boolean dataReceive = false;
ReceiverSimple() {
}
// record consumer
private Runnable tmpConsumer1 = null;
private Connection tmpConnect = null;
@Override
public void close() {
this.tmpConsumer1 = null;
if (this.tmpConnect != null) {
this.tmpConnect.close();
this.tmpConnect = null;
}
this.dataReceive = false;
}
public void disconnectConnection() {
this.tmpConnect.close();
}
public boolean isConnected() {
return this.tmpConnect.isConnected();
}
public void connect1(final EmiterSimple other) {
WeakReference<ReceiverSimple> tmpp = new WeakReference<ReceiverSimple>(this);
other.signalEvent.connect(() -> {
tmpp.get().onData();
WeakReference<ReceiverSimple> self = new WeakReference<ReceiverSimple>(this);
this.tmpConnect = other.signalEvent.connect(() -> {
self.get().onData();
});
System.gc();
}
public void connect2(final EmiterSimple other) {
// the solo lambda will not depend on the object => the remove must be done manually...
other.signalEvent.connect(() -> {
this.tmpConnect = other.signalEvent.connect(() -> {
Log.error("lambda receive: ");
});
System.gc();
}
public void connect3(final EmiterSimple other) {
// we reference the local object, then the lambda is alive while the object is alive...
other.signalEvent.connect(() -> {
this.tmpConnect =other.signalEvent.connect(() -> {
Log.error("lambda receive: ");
this.dataReceive = true;
});
System.gc();
}
public void connect4(final EmiterSimple other) {
other.signalEvent.connect(() -> {
this.tmpConnect = other.signalEvent.connect(() -> {
onData();
});
System.gc();
}
Runnable tmpRunner = null;
public void connect5(final EmiterSimple other) {
this.tmpRunner = this::onData;
other.signalEvent.connect(this.tmpRunner);
this.tmpConsumer1 = this::onData;
other.signalEvent.connectWeak(this.tmpConsumer1);
System.gc();
}
public void disconnect5(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpRunner);
this.tmpRunner = null;
public void disconnectConsumer1(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConsumer1);
this.tmpConsumer1 = null;
}
public void connect6(final EmiterSimple other) {
@ -73,28 +98,76 @@ public class TestSignalEmpty {
other.signalEvent.connectAutoRemoveObject(this, () -> {
Log.error("lambda receive: ");
});
System.gc();
}
private Connection tmpConnect = null;
public void connect7(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connectDynamic(this::onData);
this.tmpConnect = other.signalEvent.connect(this::onData);
System.gc();
}
public void disconnect7(final EmiterSimple other) {
other.signalEvent.disconnect(this.tmpConnect);
}
public void disconnect72() {
this.tmpConnect.disconnect();
}
public boolean isConnected() {
return this.tmpConnect.isConnected();
}
public void onData() {
Log.error("Retrive data : ");
this.dataReceive = true;
}
public void connect8(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, ReceiverSimple::onDataStatic);
System.gc();
}
public void connect9(final EmiterSimple other) {
other.signalEvent.connectAuto(this, ReceiverSimple::onDataStatic);
System.gc();
}
public static void onDataStatic(final Object local) {
ReceiverSimple self = (ReceiverSimple)local;
Log.error("Retrive data : ");
self.dataReceive = true;
}
public void connect10(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, ReceiverSimple::onDataStatic2);
System.gc();
}
public void connect11(final EmiterSimple other) {
other.signalEvent.connectAuto(this, ReceiverSimple::onDataStatic2);
System.gc();
}
public static void onDataStatic2(final ReceiverSimple self) {
Log.error("Retrive data : ");
self.dataReceive = true;
}
public void connect12(final EmiterSimple other) {
this.tmpConnect = other.signalEvent.connect(this, (final ReceiverSimple self) -> {
Log.error("Retrive data : ");
self.dataReceive = true;
});
System.gc();
}
public void connect13(final EmiterSimple other) {
other.signalEvent.connectAuto(this, (final ReceiverSimple self) -> {
Log.error("Retrive data : ");
self.dataReceive = true;
});
System.gc();
}
public boolean getDataAndClean() {
boolean tmp = this.dataReceive;
this.dataReceive = false;
@ -117,7 +190,9 @@ public class TestSignalEmpty {
receiver = null;
Assertions.assertEquals(1, sender.signalEvent.size());
System.gc();
Assertions.assertEquals(0, sender.signalEvent.sizeCleaned());
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 1 [ END ]");
}
@ -132,12 +207,13 @@ public class TestSignalEmpty {
sender.sendEvent();
// No data stored ... assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.signalEvent.size());
// !!!! NO need to close lambda does not capture the THIS
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 2 [ END ]");
}
@ -152,7 +228,9 @@ public class TestSignalEmpty {
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close ==> capture Of this
receiver.close();
receiver = null;
System.gc();
@ -174,6 +252,8 @@ public class TestSignalEmpty {
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close ==> capture Of this
receiver.close();
receiver = null;
System.gc();
@ -197,7 +277,7 @@ public class TestSignalEmpty {
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection
receiver.disconnect5(sender);
receiver.disconnectConsumer1(sender);
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
@ -210,6 +290,7 @@ public class TestSignalEmpty {
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// No need to close ==> the capture seams does not increase the cumber of Reference ....
// check auto remove...
receiver = null;
System.gc();
@ -271,7 +352,7 @@ public class TestSignalEmpty {
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnect72();
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
@ -285,6 +366,8 @@ public class TestSignalEmpty {
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// Need to close to prevent miss removing of connection.
receiver.close();
// check auto remove...
receiver = null;
System.gc();
@ -296,10 +379,237 @@ public class TestSignalEmpty {
}
@Test
public void testEmptyConnection() {
Connection con = new Connection();
Assertions.assertEquals(false, con.isConnected());
con.disconnect();
@Order(8)
public void testConnectAndTransmit8() {
Log.warning("Test 8 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
sender.sendEvent();
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect8(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 8 [ END ]");
}
@Test
@Order(9)
public void testConnectAndTransmit9() {
Log.warning("Test 9 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect9(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 9 [ END ]");
}
@Test
@Order(10)
public void testConnectAndTransmit10() {
Log.warning("Test 10 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
sender.sendEvent();
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect10(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 10 [ END ]");
}
@Test
@Order(11)
public void testConnectAndTransmit11() {
Log.warning("Test 11 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect11(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 11 [ END ]");
}
@Test
@Order(12)
public void testConnectAndTransmit12() {
Log.warning("Test 12 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
Assertions.assertEquals(true, receiver.isConnected());
// remove connection
receiver.disconnectConnection();
Assertions.assertEquals(false, receiver.isConnected());
Assertions.assertEquals(0, sender.signalEvent.size());
System.gc();
sender.sendEvent();
Assertions.assertEquals(false, receiver.getDataAndClean());
// reconnect (step 2
receiver.connect12(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// check auto remove...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 12 [ END ]");
}
@Test
@Order(13)
public void testConnectAndTransmit13() {
Log.warning("Test 13 [BEGIN]");
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect13(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender.sendEvent();
Assertions.assertEquals(true, receiver.getDataAndClean());
Assertions.assertEquals(1, sender.signalEvent.size());
// remove connection (check auto remove)...
receiver = null;
System.gc();
sender.sendEvent();
Assertions.assertEquals(0, sender.signalEvent.size());
Log.warning("Test 13 [ END ]");
}
@Test
@ -311,16 +621,4 @@ public class TestSignalEmpty {
Assertions.assertEquals(1, sender.signalEvent.size());
sender.signalEvent.clear();
}
@Test
public void testDisconnectionRemovedSignal() {
EmiterSimple sender = new EmiterSimple();
ReceiverSimple receiver = new ReceiverSimple();
//connect step 1
receiver.connect7(sender);
Assertions.assertEquals(1, sender.signalEvent.size());
sender = null;
System.gc();
Assertions.assertEquals(false, receiver.isConnected());
receiver.disconnect72();
}
}