final BoundedState<T> state = new BoundedState<T>( new PairEvictionPolicy( new SizeEvictionPolicy(size),
final BoundedState<T> state = new BoundedState<T>( new TimeEvictionPolicy(unit.toMillis(time), scheduler), new AddTimestamped(scheduler),
/** * Creates a size-bounded replay subject. * <p> * In this setting, the {@code ReplaySubject} holds at most {@code size} items in its internal buffer and * discards the oldest item. * <p> * When observers subscribe to a terminated {@code ReplaySubject}, they are guaranteed to see at most * {@code size} {@code onNext} events followed by a termination event. * <p> * If an observer subscribes while the {@code ReplaySubject} is active, it will observe all items in the * buffer at that point in time and each item observed afterwards, even if the buffer evicts items due to * the size constraint in the mean time. In other words, once an Observer subscribes, it will receive items * without gaps in the sequence. * * @param <T> * the type of items observed and emitted by the Subject * @param size * the maximum number of buffered items * @return the created subject */ public static <T> ReplaySubject<T> createWithSize(int size) { final BoundedState<T> state = new BoundedState<T>( new SizeEvictionPolicy(size), Functions.identity(), Functions.identity() ); return createWithState(state, new DefaultOnAdd<T>(state)); } /**
/** * Creates an unbounded replay subject with the bounded-implementation for testing purposes. * <p> * This variant behaves like the regular unbounded {@code ReplaySubject} created via {@link #create()} but * uses the structures of the bounded-implementation. This is by no means intended for the replacement of * the original, array-backed and unbounded {@code ReplaySubject} due to the additional overhead of the * linked-list based internal buffer. The sole purpose is to allow testing and reasoning about the behavior * of the bounded implementations without the interference of the eviction policies. * * @param <T> * the type of items observed and emitted by the Subject * @return the created subject */ /* public */ static <T> ReplaySubject<T> createUnbounded() { final BoundedState<T> state = new BoundedState<T>( new EmptyEvictionPolicy(), Functions.identity(), Functions.identity() ); return createWithState(state, new DefaultOnAdd<T>(state)); } /**
@Override public void call(SubjectObserver<T> t1) { NodeList.Node<Object> l; if (!state.terminated) { // ignore stale entries if still active l = state.replayObserverFromIndexTest(state.head(), t1, scheduler.now()); } else { // accept all if terminated l = state.replayObserverFromIndex(state.head(), t1); } t1.index(l); }
@Override public void call(SubjectObserver<T> t1) { NodeList.Node<Object> l = state.replayObserverFromIndex(state.head(), t1); t1.index(l); }
@Override public void replayObserver(SubjectObserver<? super T> observer) { NodeList.Node<Object> lastEmittedLink = observer.index(); NodeList.Node<Object> l = replayObserverFromIndex(lastEmittedLink, observer); observer.index(l); }
@Override public void call(SubjectObserver<T> t1) { NodeList.Node<Object> l = t1.index(); if (l == null) { l = state.head(); } state.replayObserverFromIndex(l, t1); }
@Override public NodeList.Node<Object> replayObserverFromIndexTest( NodeList.Node<Object> l, SubjectObserver<? super T> observer, long now) { while (l != tail()) { acceptTest(observer, l.next, now); l = l.next; } return l; }