[DEV] add a real Signal interface
This commit is contained in:
parent
ff07d48196
commit
3d262b8b82
@ -1,10 +1,31 @@
|
|||||||
package org.atriasoft.esignal;
|
package org.atriasoft.esignal;
|
||||||
|
|
||||||
public class Connection {
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
public class Connection implements AutoCloseable {
|
||||||
|
protected final WeakReference<ConnectionRemoveInterface> connection;
|
||||||
|
|
||||||
public void disconnect() {
|
public void disconnect() {
|
||||||
// TODO Auto-generated method stub
|
close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Connection( final ConnectionRemoveInterface object ) {
|
||||||
|
this.connection = new WeakReference<>(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Connection() {
|
||||||
|
this.connection = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (this.connection == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ConnectionRemoveInterface tmp = this.connection.get();
|
||||||
|
if (tmp == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tmp.disconnect(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
5
src/org/atriasoft/esignal/ConnectionRemoveInterface.java
Normal file
5
src/org/atriasoft/esignal/ConnectionRemoveInterface.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package org.atriasoft.esignal;
|
||||||
|
|
||||||
|
public interface ConnectionRemoveInterface {
|
||||||
|
void disconnect(final Connection connection);
|
||||||
|
}
|
@ -7,8 +7,8 @@ import java.util.List;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
class ConnectedElement<T> {
|
class ConnectedElement<T> {
|
||||||
private final Consumer<T> consumer;
|
protected final Consumer<T> consumer;
|
||||||
private final WeakReference<Object> reference;
|
protected final WeakReference<Object> reference;
|
||||||
|
|
||||||
public ConnectedElement(final WeakReference<Object> reference, final Consumer<T> consumer) {
|
public ConnectedElement(final WeakReference<Object> reference, final Consumer<T> consumer) {
|
||||||
this.reference = reference;
|
this.reference = reference;
|
||||||
@ -22,38 +22,135 @@ class ConnectedElement<T> {
|
|||||||
public WeakReference<Object> getReference() {
|
public WeakReference<Object> getReference() {
|
||||||
return this.reference;
|
return this.reference;
|
||||||
}
|
}
|
||||||
|
public Object getIfAlive() {
|
||||||
|
return this.reference.get();
|
||||||
|
}
|
||||||
|
public boolean isCompatibleWith(final Object elem) {
|
||||||
|
Object out = this.reference.get();
|
||||||
|
if (out == elem) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class ConnectedElementDynamic<T> extends ConnectedElement<T> {
|
||||||
|
protected final WeakReference<Connection> connection;
|
||||||
|
|
||||||
|
public ConnectedElementDynamic(final WeakReference<Connection> connection, final WeakReference<Object> reference, final Consumer<T> consumer) {
|
||||||
|
super(reference, consumer);
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeakReference<Connection> getConnection() {
|
||||||
|
return this.connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getIfAlive() {
|
||||||
|
Object out = this.reference.get();
|
||||||
|
if (out == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Object outConnection = this.connection.get();
|
||||||
|
if (outConnection == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean isCompatibleWith(final Object elem) {
|
||||||
|
if (super.isCompatibleWith(elem)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Object outConnection = this.connection.get();
|
||||||
|
if (outConnection == elem) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Signal<T> {
|
public class Signal<T> implements ConnectionRemoveInterface {
|
||||||
|
|
||||||
List<ConnectedElement<T>> data = new ArrayList<>();
|
List<ConnectedElement<T>> data = new ArrayList<>();
|
||||||
|
|
||||||
public void clear(final Object obj) {
|
public void clear() {
|
||||||
|
synchronized(this.data) {
|
||||||
|
this.data = new ArrayList<>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Connection connect(final Object reference, final T fucntion) {
|
public void connect(final Object reference, final Consumer<T> function) {
|
||||||
|
synchronized(this.data) {
|
||||||
return null;
|
WeakReference<Object> weakRef = new WeakReference<Object>(reference);
|
||||||
|
this.data.add(new ConnectedElement<T>(weakRef, function));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect(final Connection connection) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disconnect(final Object obj) {
|
public void disconnect(final Object 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
public Connection connectDynamic(final Object reference, final Consumer<T> function) {
|
||||||
|
WeakReference<Object> weakRef = new WeakReference<Object>(reference);
|
||||||
|
Connection out = new Connection(this);
|
||||||
|
WeakReference<Connection> weakConnection = new WeakReference<Connection>(out);
|
||||||
|
synchronized(this.data) {
|
||||||
|
this.data.add(new ConnectedElementDynamic<T>(weakConnection, weakRef, function));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect(final Connection connection) {
|
||||||
|
synchronized(this.data) {
|
||||||
|
final Iterator<ConnectedElement<T>> iterator = this.data.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final ConnectedElement<T> elem = iterator.next();
|
||||||
|
if (elem.isCompatibleWith(connection)) {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void emit(final T value) {
|
public void emit(final T value) {
|
||||||
final Iterator<ConnectedElement<T>> iterator = this.data.iterator();
|
List<ConnectedElement<T>> tmp;
|
||||||
while (iterator.hasNext()) {
|
// clean the list:
|
||||||
final ConnectedElement<T> elem = iterator.next();
|
synchronized(this.data) {
|
||||||
if (elem.getReference().get() == null) {
|
final Iterator<ConnectedElement<T>> iterator = this.data.iterator();
|
||||||
iterator.remove();
|
while (iterator.hasNext()) {
|
||||||
|
final ConnectedElement<T> elem = iterator.next();
|
||||||
|
Object tmpObject = elem.getIfAlive();
|
||||||
|
if (tmpObject == null) {
|
||||||
|
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
|
||||||
|
{
|
||||||
|
final Iterator<ConnectedElement<T>> iterator = tmp.iterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
final ConnectedElement<T> elem = iterator.next();
|
||||||
|
Object tmpObject = elem.getIfAlive();
|
||||||
|
if (tmpObject == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
elem.getConsumer().accept(value);
|
||||||
}
|
}
|
||||||
elem.getConsumer().accept(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user