Compare commits
No commits in common. "e6905e78a76f02a559b319ff39b3317f963c356f" and "722e6fe5cf3e13e860282cfc4ff52cb20939e82b" have entirely different histories.
e6905e78a7
...
722e6fe5cf
@ -1,12 +1,5 @@
|
|||||||
package org.atriasoft.esignal;
|
package org.atriasoft.esignal;
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface to permit to the connection to unlink itself.
|
|
||||||
*/
|
|
||||||
public interface ConnectionRemoveInterface {
|
public interface ConnectionRemoveInterface {
|
||||||
/**
|
|
||||||
* Request the removing on the specify connection
|
|
||||||
* @param connection Connection to removed.
|
|
||||||
*/
|
|
||||||
void disconnect(final Connection connection);
|
void disconnect(final Connection connection);
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,8 @@ import org.atriasoft.esignal.internal.ConnectedElementDynamic;
|
|||||||
* @param <T> generic Runnable, Consumer, or BiConsumer template...
|
* @param <T> generic Runnable, Consumer, or BiConsumer template...
|
||||||
*/
|
*/
|
||||||
public class GenericSignal<T> implements ConnectionRemoveInterface {
|
public class GenericSignal<T> implements ConnectionRemoveInterface {
|
||||||
// List of all connected Links
|
List<ConnectedElement<T>> data = new ArrayList<>();
|
||||||
protected List<ConnectedElement<T>> data = new ArrayList<>();
|
|
||||||
/**
|
|
||||||
* Clear all connection on this signal.
|
|
||||||
*/
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
List<ConnectedElement<T>> data2 = this.data;
|
List<ConnectedElement<T>> data2 = this.data;
|
||||||
synchronized(this.data) {
|
synchronized(this.data) {
|
||||||
@ -29,21 +26,12 @@ public class GenericSignal<T> implements ConnectionRemoveInterface {
|
|||||||
elem.disconnect();
|
elem.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Connect a Function to this signal
|
|
||||||
* @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()
|
|
||||||
*/
|
|
||||||
public void connect(final T function) {
|
public void connect(final T function) {
|
||||||
synchronized(this.data) {
|
synchronized(this.data) {
|
||||||
this.data.add(new ConnectedElement<T>(function));
|
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) {
|
public void disconnect(final T obj) {
|
||||||
synchronized(this.data) {
|
synchronized(this.data) {
|
||||||
final Iterator<ConnectedElement<T>> iterator = this.data.iterator();
|
final Iterator<ConnectedElement<T>> iterator = this.data.iterator();
|
||||||
@ -55,11 +43,6 @@ public class GenericSignal<T> implements ConnectionRemoveInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
public Connection connectDynamic(final T function) {
|
public Connection connectDynamic(final T function) {
|
||||||
Connection out = new Connection(this);
|
Connection out = new Connection(this);
|
||||||
synchronized(this.data) {
|
synchronized(this.data) {
|
||||||
@ -67,14 +50,9 @@ public class GenericSignal<T> implements ConnectionRemoveInterface {
|
|||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
/**
|
public void connectAutoRemoveObject(final Object reference, final T 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 connectAutoRemoveObject(final Object object, final T function) {
|
|
||||||
synchronized(this.data) {
|
synchronized(this.data) {
|
||||||
this.data.add(new ConnectedElementDynamic<T>(object, function));
|
this.data.add(new ConnectedElementDynamic<T>(reference, function));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,57 +70,8 @@ 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() {
|
|
||||||
// first clean the list
|
|
||||||
cleanedList();
|
|
||||||
// get a copy of elements
|
|
||||||
List<ConnectedElement<T>> out = null;
|
|
||||||
// clean the list:
|
|
||||||
synchronized(this.data) {
|
|
||||||
// simple optimization:
|
|
||||||
if (this.data.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// clone the list to permit to have asynchronous remove call
|
|
||||||
out = new ArrayList<>(this.data);
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Clean all the deprecated list of removed elements
|
|
||||||
*/
|
|
||||||
protected void cleanedList() {
|
|
||||||
// clean the list:
|
|
||||||
synchronized(this.data) {
|
|
||||||
final Iterator<ConnectedElement<T>> iterator = this.data.iterator();
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
final ConnectedElement<T> elem = iterator.next();
|
|
||||||
Object tmpObject = elem.getConsumer();
|
|
||||||
if (tmpObject == null) {
|
|
||||||
elem.disconnect();
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Get the Number of current connection (clean is not done).
|
|
||||||
* @return Number of connection
|
|
||||||
*/
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return this.data.size();
|
return this.data.size();
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Get the Number of current connection (clean is done).
|
|
||||||
* @return Number of connection
|
|
||||||
*/
|
|
||||||
public int sizeCleaned() {
|
|
||||||
cleanedList();
|
|
||||||
return this.data.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.atriasoft.esignal;
|
package org.atriasoft.esignal;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@ -51,25 +52,43 @@ import org.atriasoft.esignal.internal.ConnectedElement;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Signal<T> extends GenericSignal<Consumer<T>> {
|
public class Signal<T> extends GenericSignal<Consumer<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) {
|
public void emit(final T value) {
|
||||||
List<ConnectedElement<Consumer<T>>> tmp = getACleanedList();
|
List<ConnectedElement<Consumer<T>>> tmp;
|
||||||
if (tmp == null) {
|
// clean the list:
|
||||||
return;
|
synchronized(this.data) {
|
||||||
|
final Iterator<ConnectedElement<Consumer<T>>> iterator = this.data.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final ConnectedElement<Consumer<T>> elem = iterator.next();
|
||||||
|
Object tmpObject = elem.getConsumer();
|
||||||
|
if (tmpObject == null) {
|
||||||
|
elem.disconnect();
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// simple optimization:
|
||||||
|
if (this.data.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// clone the list to permit to have asynchronous remove call
|
||||||
|
tmp = new ArrayList<>(this.data);
|
||||||
}
|
}
|
||||||
// real call elements
|
// real call elements
|
||||||
final Iterator<ConnectedElement<Consumer<T>>> iterator = tmp.iterator();
|
{
|
||||||
while (iterator.hasNext()) {
|
final Iterator<ConnectedElement<Consumer<T>>> iterator = tmp.iterator();
|
||||||
final ConnectedElement<Consumer<T>> elem = iterator.next();
|
while (iterator.hasNext()) {
|
||||||
Consumer<T> tmpObject = elem.getConsumer();
|
final ConnectedElement<Consumer<T>> elem = iterator.next();
|
||||||
if (tmpObject == null) {
|
Consumer<T> tmpObject = elem.getConsumer();
|
||||||
// Not a dead code, but very hard to simply test it.
|
if (tmpObject == null) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
tmpObject.accept(value);
|
||||||
}
|
}
|
||||||
tmpObject.accept(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int size() {
|
||||||
|
return this.data.size();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.atriasoft.esignal;
|
package org.atriasoft.esignal;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
@ -53,25 +54,37 @@ import org.atriasoft.esignal.internal.ConnectedElement;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Signal2<T, U> extends GenericSignal<BiConsumer<T, U>> {
|
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) {
|
public void emit(final T valueT, final U valueU) {
|
||||||
List<ConnectedElement<BiConsumer<T, U>>> tmp = getACleanedList();
|
List<ConnectedElement<BiConsumer<T, U>>> tmp;
|
||||||
if (tmp == null) {
|
// clean the list:
|
||||||
return;
|
synchronized(this.data) {
|
||||||
|
final Iterator<ConnectedElement<BiConsumer<T, U>>> iterator = this.data.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final ConnectedElement<BiConsumer<T, U>> elem = iterator.next();
|
||||||
|
Object tmpObject = elem.getConsumer();
|
||||||
|
if (tmpObject == null) {
|
||||||
|
elem.disconnect();
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// simple optimization:
|
||||||
|
if (this.data.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// clone the list to permit to have asynchronous remove call
|
||||||
|
tmp = new ArrayList<>(this.data);
|
||||||
}
|
}
|
||||||
// real call elements
|
// real call elements
|
||||||
final Iterator<ConnectedElement<BiConsumer<T, U>>> iterator = tmp.iterator();
|
{
|
||||||
while (iterator.hasNext()) {
|
final Iterator<ConnectedElement<BiConsumer<T, U>>> iterator = tmp.iterator();
|
||||||
final ConnectedElement<BiConsumer<T, U>> elem = iterator.next();
|
while (iterator.hasNext()) {
|
||||||
BiConsumer<T, U> tmpObject = elem.getConsumer();
|
final ConnectedElement<BiConsumer<T, U>> elem = iterator.next();
|
||||||
if (tmpObject == null) {
|
BiConsumer<T, U> tmpObject = elem.getConsumer();
|
||||||
continue;
|
if (tmpObject == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmpObject.accept(valueT, valueU);
|
||||||
}
|
}
|
||||||
tmpObject.accept(valueT, valueU);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.atriasoft.esignal;
|
package org.atriasoft.esignal;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -48,23 +49,38 @@ import org.atriasoft.esignal.internal.ConnectedElement;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SignalEmpty extends GenericSignal<Runnable> {
|
public class SignalEmpty extends GenericSignal<Runnable> {
|
||||||
/**
|
|
||||||
* Emit a signal on all element connect (and clean the list of unlinked elements).
|
|
||||||
*/
|
|
||||||
public void emit() {
|
public void emit() {
|
||||||
List<ConnectedElement<Runnable>> tmp = getACleanedList();
|
List<ConnectedElement<Runnable>> tmp;
|
||||||
if (tmp == null) {
|
// clean the list:
|
||||||
return;
|
synchronized(this.data) {
|
||||||
|
final Iterator<ConnectedElement<Runnable>> iterator = this.data.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final ConnectedElement<Runnable> elem = iterator.next();
|
||||||
|
Object tmpObject = elem.getConsumer();
|
||||||
|
if (tmpObject == null) {
|
||||||
|
elem.disconnect();
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// simple optimization:
|
||||||
|
if (this.data.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// clone the list to permit to have asynchronous remove call
|
||||||
|
tmp = new ArrayList<>(this.data);
|
||||||
}
|
}
|
||||||
// real call elements
|
// real call elements
|
||||||
final Iterator<ConnectedElement<Runnable>> iterator = tmp.iterator();
|
{
|
||||||
while (iterator.hasNext()) {
|
final Iterator<ConnectedElement<Runnable>> iterator = tmp.iterator();
|
||||||
final ConnectedElement<Runnable> elem = iterator.next();
|
while (iterator.hasNext()) {
|
||||||
Runnable tmpObject = elem.getConsumer();
|
final ConnectedElement<Runnable> elem = iterator.next();
|
||||||
if (tmpObject == null) {
|
Runnable tmpObject = elem.getConsumer();
|
||||||
continue;
|
if (tmpObject == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmpObject.run();
|
||||||
}
|
}
|
||||||
tmpObject.run();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,9 @@ public class TestSignalEmpty {
|
|||||||
receiver = null;
|
receiver = null;
|
||||||
Assertions.assertEquals(1, sender.signalEvent.size());
|
Assertions.assertEquals(1, sender.signalEvent.size());
|
||||||
System.gc();
|
System.gc();
|
||||||
Assertions.assertEquals(0, sender.signalEvent.sizeCleaned());
|
|
||||||
|
sender.sendEvent();
|
||||||
|
Assertions.assertEquals(0, sender.signalEvent.size());
|
||||||
Log.warning("Test 1 [ END ]");
|
Log.warning("Test 1 [ END ]");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user