001
014
015 package com.liferay.portal.kernel.concurrent;
016
017 import java.util.Set;
018 import java.util.concurrent.Callable;
019 import java.util.concurrent.CopyOnWriteArraySet;
020 import java.util.concurrent.Future;
021 import java.util.concurrent.FutureTask;
022 import java.util.concurrent.atomic.AtomicBoolean;
023
024
027 public class DefaultNoticeableFuture<T>
028 extends FutureTask<T> implements NoticeableFuture<T> {
029
030 @SuppressWarnings("unchecked")
031 public DefaultNoticeableFuture() {
032 super((Callable<T>)_emptyCallable);
033 }
034
035 public DefaultNoticeableFuture(Callable<T> callable) {
036 super(callable);
037 }
038
039 public DefaultNoticeableFuture(Runnable runnable, T result) {
040 super(runnable, result);
041 }
042
043 @Override
044 public boolean addFutureListener(FutureListener<T> futureListener) {
045 if (futureListener == null) {
046 throw new NullPointerException("Future listener is null");
047 }
048
049 futureListener = new OnceFutureListener<>(futureListener);
050
051 if (_futureListeners.add(futureListener)) {
052 if (isDone()) {
053 futureListener.complete(this);
054 }
055
056 return true;
057 }
058
059 return false;
060 }
061
062 @Override
063 public boolean removeFutureListener(FutureListener<T> futureListener) {
064 if (futureListener == null) {
065 throw new NullPointerException("Future listener is null");
066 }
067
068 return _futureListeners.remove(
069 new OnceFutureListener<T>(futureListener));
070 }
071
072 @Override
073 public void set(T t) {
074 super.set(t);
075 }
076
077 @Override
078 public void setException(Throwable t) {
079 super.setException(t);
080 }
081
082 @Override
083 protected void done() {
084 for (FutureListener<T> futureListener : _futureListeners) {
085 futureListener.complete(this);
086 }
087 }
088
089 private static final Callable<Object> _emptyCallable =
090 new Callable<Object>() {
091
092 @Override
093 public Object call() {
094 return null;
095 }
096
097 };
098
099 private final Set<FutureListener<T>> _futureListeners =
100 new CopyOnWriteArraySet<>();
101
102 private static class OnceFutureListener<V> implements FutureListener<V> {
103
104 public OnceFutureListener(FutureListener<V> futureListener) {
105 _futureListener = futureListener;
106 }
107
108 @Override
109 public void complete(Future<V> future) {
110 if (_ran.compareAndSet(false, true)) {
111 _futureListener.complete(future);
112 }
113 }
114
115 @Override
116 public boolean equals(Object obj) {
117 OnceFutureListener<V> onceFutureListener =
118 (OnceFutureListener<V>)obj;
119
120 return _futureListener.equals(onceFutureListener._futureListener);
121 }
122
123 @Override
124 public int hashCode() {
125 return _futureListener.hashCode();
126 }
127
128 private final FutureListener<V> _futureListener;
129 private final AtomicBoolean _ran = new AtomicBoolean();
130
131 }
132
133 }