Skip to content

Commit c09efd8

Browse files
Merge pull request ReactiveX#1010 from benjchristensen/unsafe-subscribe
UnsafeSubscribe
2 parents 7af5c32 + 7ce6860 commit c09efd8

File tree

85 files changed

+604
-687
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+604
-687
lines changed

rxjava-core/src/main/java/rx/Observable.java

Lines changed: 211 additions & 342 deletions
Large diffs are not rendered by default.

rxjava-core/src/main/java/rx/joins/JoinObserver1.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public void addActivePlan(ActivePlan0 activePlan) {
6161
public void subscribe(Object gate) {
6262
if (subscribed.compareAndSet(false, true)) {
6363
this.gate = gate;
64-
source.materialize().subscribe(this);
64+
source.materialize().unsafeSubscribe(this);
6565
} else {
6666
throw new IllegalStateException("Can only be subscribed to once.");
6767
}

rxjava-core/src/main/java/rx/observables/BlockingObservable.java

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@
2222

2323
import rx.Observable;
2424
import rx.Subscriber;
25-
import rx.Subscription;
2625
import rx.functions.Action1;
2726
import rx.functions.Func1;
28-
import rx.observers.SafeSubscriber;
29-
import rx.operators.OperationLatest;
30-
import rx.operators.OperationMostRecent;
31-
import rx.operators.OperationNext;
32-
import rx.operators.OperationToFuture;
33-
import rx.operators.OperationToIterator;
27+
import rx.operators.BlockingOperatorLatest;
28+
import rx.operators.BlockingOperatorMostRecent;
29+
import rx.operators.BlockingOperatorNext;
30+
import rx.operators.BlockingOperatorToFuture;
31+
import rx.operators.BlockingOperatorToIterator;
3432

3533
/**
3634
* An extension of {@link Observable} that provides blocking operators.
@@ -64,17 +62,6 @@ public static <T> BlockingObservable<T> from(final Observable<? extends T> o) {
6462
return new BlockingObservable<T>(o);
6563
}
6664

67-
/**
68-
* Used for protecting against errors being thrown from {@link Subscriber} implementations and ensuring onNext/onError/onCompleted contract
69-
* compliance.
70-
* <p>
71-
* See https://github.com/Netflix/RxJava/issues/216 for discussion on
72-
* "Guideline 6.4: Protect calls to user code from within an operator"
73-
*/
74-
private Subscription protectivelyWrapAndSubscribe(Subscriber<? super T> observer) {
75-
return o.subscribe(new SafeSubscriber<T>(observer));
76-
}
77-
7865
/**
7966
* Invoke a method on each item emitted by the {@link Observable}; block
8067
* until the Observable completes.
@@ -97,12 +84,10 @@ public void forEach(final Action1<? super T> onNext) {
9784
final AtomicReference<Throwable> exceptionFromOnError = new AtomicReference<Throwable>();
9885

9986
/**
100-
* Wrapping since raw functions provided by the user are being invoked.
101-
*
102-
* See https://github.com/Netflix/RxJava/issues/216 for discussion on
103-
* "Guideline 6.4: Protect calls to user code from within an operator"
87+
* Use 'subscribe' instead of 'unsafeSubscribe' for Rx contract behavior
88+
* as this is the final subscribe in the chain.
10489
*/
105-
protectivelyWrapAndSubscribe(new Subscriber<T>() {
90+
o.subscribe(new Subscriber<T>() {
10691
@Override
10792
public void onCompleted() {
10893
latch.countDown();
@@ -158,7 +143,7 @@ public void onNext(T args) {
158143
* @see <a href="https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators#transformations-tofuture-toiterable-and-toiteratorgetiterator">RxJava Wiki: getIterator()</a>
159144
*/
160145
public Iterator<T> getIterator() {
161-
return OperationToIterator.toIterator(o);
146+
return BlockingOperatorToIterator.toIterator(o);
162147
}
163148

164149
/**
@@ -311,7 +296,7 @@ public T lastOrDefault(T defaultValue, Func1<? super T, Boolean> predicate) {
311296
* @see <a href="http://msdn.microsoft.com/en-us/library/hh229751.aspx">MSDN: Observable.MostRecent</a>
312297
*/
313298
public Iterable<T> mostRecent(T initialValue) {
314-
return OperationMostRecent.mostRecent(o, initialValue);
299+
return BlockingOperatorMostRecent.mostRecent(o, initialValue);
315300
}
316301

317302
/**
@@ -324,7 +309,7 @@ public Iterable<T> mostRecent(T initialValue) {
324309
* @see <a href="http://msdn.microsoft.com/en-us/library/hh211897.aspx">MSDN: Observable.Next</a>
325310
*/
326311
public Iterable<T> next() {
327-
return OperationNext.next(o);
312+
return BlockingOperatorNext.next(o);
328313
}
329314

330315
/**
@@ -344,7 +329,7 @@ public Iterable<T> next() {
344329
* @see <a href="http://msdn.microsoft.com/en-us/library/hh212115.aspx">MSDN: Observable.Latest</a>
345330
*/
346331
public Iterable<T> latest() {
347-
return OperationLatest.latest(o);
332+
return BlockingOperatorLatest.latest(o);
348333
}
349334

350335
/**
@@ -441,7 +426,7 @@ public T singleOrDefault(T defaultValue, Func1<? super T, Boolean> predicate) {
441426
* @see <a href="https://github.com/Netflix/RxJava/wiki/Blocking-Observable-Operators#transformations-tofuture-toiterable-and-toiteratorgetiterator">RxJava Wiki: toFuture()</a>
442427
*/
443428
public Future<T> toFuture() {
444-
return OperationToFuture.toFuture(o);
429+
return BlockingOperatorToFuture.toFuture(o);
445430
}
446431

447432
/**

rxjava-core/src/main/java/rx/observables/GroupedObservable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public static <K, T> GroupedObservable<K, T> from(K key, final Observable<T> o)
3737

3838
@Override
3939
public void call(Subscriber<? super T> s) {
40-
o.subscribe(s);
40+
o.unsafeSubscribe(s);
4141
}
4242
});
4343
}

rxjava-core/src/main/java/rx/operators/OperationLatest.java renamed to rxjava-core/src/main/java/rx/operators/BlockingOperatorLatest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@
2222

2323
import rx.Notification;
2424
import rx.Observable;
25-
import rx.Observer;
25+
import rx.Subscriber;
2626
import rx.exceptions.Exceptions;
2727

2828
/**
2929
* Wait for and iterate over the latest values of the source observable.
3030
* If the source works faster than the iterator, values may be skipped, but
3131
* not the onError or onCompleted events.
3232
*/
33-
public final class OperationLatest {
33+
public final class BlockingOperatorLatest {
3434
/** Utility class. */
35-
private OperationLatest() {
35+
private BlockingOperatorLatest() {
3636
throw new IllegalStateException("No instances!");
3737
}
3838

@@ -48,7 +48,7 @@ public Iterator<T> iterator() {
4848
}
4949

5050
/** Observer of source, iterator for output. */
51-
static final class LatestObserverIterator<T> implements Observer<Notification<? extends T>>, Iterator<T> {
51+
static final class LatestObserverIterator<T> extends Subscriber<Notification<? extends T>> implements Iterator<T> {
5252
final Semaphore notify = new Semaphore(0);
5353
// observer's notification
5454
final AtomicReference<Notification<? extends T>> reference = new AtomicReference<Notification<? extends T>>();

rxjava-core/src/main/java/rx/operators/OperationMostRecent.java renamed to rxjava-core/src/main/java/rx/operators/BlockingOperatorMostRecent.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import java.util.concurrent.atomic.AtomicReference;
2121

2222
import rx.Observable;
23-
import rx.Observer;
23+
import rx.Subscriber;
2424
import rx.exceptions.Exceptions;
2525

2626
/**
@@ -29,7 +29,7 @@
2929
* <p>
3030
* <img width="640" src="https://github.com/Netflix/RxJava/wiki/images/rx-operators/B.mostRecent.png">
3131
*/
32-
public final class OperationMostRecent {
32+
public final class BlockingOperatorMostRecent {
3333

3434
public static <T> Iterable<T> mostRecent(final Observable<? extends T> source, final T initialValue) {
3535

@@ -39,6 +39,10 @@ public Iterator<T> iterator() {
3939
MostRecentObserver<T> mostRecentObserver = new MostRecentObserver<T>(initialValue);
4040
final MostRecentIterator<T> nextIterator = new MostRecentIterator<T>(mostRecentObserver);
4141

42+
/**
43+
* Subscribe instead of unsafeSubscribe since this is the final subscribe in the chain
44+
* since it is for BlockingObservable.
45+
*/
4246
source.subscribe(mostRecentObserver);
4347

4448
return nextIterator;
@@ -74,7 +78,7 @@ public void remove() {
7478
}
7579
}
7680

77-
private static class MostRecentObserver<T> implements Observer<T> {
81+
private static class MostRecentObserver<T> extends Subscriber<T> {
7882
private final AtomicBoolean completed = new AtomicBoolean(false);
7983
private final AtomicReference<T> value;
8084
private final AtomicReference<Throwable> exception = new AtomicReference<Throwable>();

rxjava-core/src/main/java/rx/operators/OperationNext.java renamed to rxjava-core/src/main/java/rx/operators/BlockingOperatorNext.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@
2323

2424
import rx.Notification;
2525
import rx.Observable;
26-
import rx.Observer;
26+
import rx.Subscriber;
2727
import rx.exceptions.Exceptions;
2828

2929
/**
3030
* Returns an Iterable that blocks until the Observable emits another item, then returns that item.
3131
* <p>
3232
* <img width="640" src="https://github.com/Netflix/RxJava/wiki/images/rx-operators/B.next.png">
3333
*/
34-
public final class OperationNext {
34+
public final class BlockingOperatorNext {
3535

3636
public static <T> Iterable<T> next(final Observable<? extends T> items) {
3737
return new Iterable<T>() {
@@ -133,7 +133,7 @@ public void remove() {
133133
}
134134
}
135135

136-
private static class NextObserver<T> implements Observer<Notification<? extends T>> {
136+
private static class NextObserver<T> extends Subscriber<Notification<? extends T>> {
137137
private final BlockingQueue<Notification<? extends T>> buf = new ArrayBlockingQueue<Notification<? extends T>>(1);
138138
private final AtomicBoolean waiting = new AtomicBoolean(false);
139139

rxjava-core/src/main/java/rx/operators/OperationToFuture.java renamed to rxjava-core/src/main/java/rx/operators/BlockingOperatorToFuture.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import java.util.concurrent.atomic.AtomicReference;
2525

2626
import rx.Observable;
27-
import rx.Observer;
27+
import rx.Subscriber;
2828
import rx.Subscription;
2929

3030
/**
@@ -35,7 +35,7 @@
3535
* The toFuture operation throws an exception if the Observable emits more than one item. If the
3636
* Observable may emit more than item, use <code>toList().toFuture()</code>.
3737
*/
38-
public class OperationToFuture {
38+
public class BlockingOperatorToFuture {
3939

4040
/**
4141
* Returns a Future that expects a single item from the observable.
@@ -52,7 +52,7 @@ public static <T> Future<T> toFuture(Observable<? extends T> that) {
5252
final AtomicReference<T> value = new AtomicReference<T>();
5353
final AtomicReference<Throwable> error = new AtomicReference<Throwable>();
5454

55-
final Subscription s = that.subscribe(new Observer<T>() {
55+
final Subscription s = that.subscribe(new Subscriber<T>() {
5656

5757
@Override
5858
public void onCompleted() {

rxjava-core/src/main/java/rx/operators/OperationToIterator.java renamed to rxjava-core/src/main/java/rx/operators/BlockingOperatorToIterator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
import rx.Notification;
2424
import rx.Observable;
25-
import rx.Observer;
25+
import rx.Subscriber;
2626
import rx.exceptions.Exceptions;
2727

2828
/**
@@ -33,7 +33,7 @@
3333
*
3434
* @see <a href="https://github.com/Netflix/RxJava/issues/50">Issue #50</a>
3535
*/
36-
public class OperationToIterator {
36+
public class BlockingOperatorToIterator {
3737

3838
/**
3939
* Returns an iterator that iterates all values of the observable.
@@ -45,7 +45,8 @@ public class OperationToIterator {
4545
public static <T> Iterator<T> toIterator(Observable<? extends T> source) {
4646
final BlockingQueue<Notification<? extends T>> notifications = new LinkedBlockingQueue<Notification<? extends T>>();
4747

48-
source.materialize().subscribe(new Observer<Notification<? extends T>>() {
48+
// using subscribe instead of unsafeSubscribe since this is a BlockingObservable "final subscribe"
49+
source.materialize().subscribe(new Subscriber<Notification<? extends T>>() {
4950
@Override
5051
public void onCompleted() {
5152
// ignore

rxjava-core/src/main/java/rx/operators/BufferUntilSubscriber.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public void onNext(T t) {
9191
* It will then immediately swap itself out for the actual (after a single notification), but since this is now
9292
* being done on the same producer thread no further buffering will occur.
9393
*/
94-
private static class PassThruObserver<T> implements Observer<T> {
94+
private static class PassThruObserver<T> extends Subscriber<T> {
9595

9696
private final Observer<? super T> actual;
9797
// this assumes single threaded synchronous notifications (the Rx contract for a single Observer)
@@ -133,7 +133,7 @@ private void drainIfNeededAndSwitchToActual() {
133133

134134
}
135135

136-
private static class BufferedObserver<T> implements Observer<T> {
136+
private static class BufferedObserver<T> extends Subscriber<T> {
137137
private final ConcurrentLinkedQueue<Object> buffer = new ConcurrentLinkedQueue<Object>();
138138

139139
@Override

rxjava-core/src/main/java/rx/operators/ChunkedOperation.java

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@
2828
import rx.Observer;
2929
import rx.Scheduler;
3030
import rx.Scheduler.Inner;
31+
import rx.Subscriber;
3132
import rx.Subscription;
3233
import rx.functions.Action1;
3334
import rx.functions.Func0;
3435
import rx.functions.Func1;
36+
import rx.subscriptions.CompositeSubscription;
3537

3638
/**
3739
* The base class for operations that break observables into "chunks". Currently buffers and windows.
@@ -408,7 +410,7 @@ public void pushValue(T value) {
408410
* The type of object all internal {@link rx.operators.ChunkedOperation.Chunk} objects record.
409411
* <C> The type of object being tracked by the {@link Chunk}
410412
*/
411-
protected static class ChunkObserver<T, C> implements Observer<T> {
413+
protected static class ChunkObserver<T, C> extends Subscriber<T> {
412414

413415
private final Chunks<T, C> chunks;
414416
private final Observer<? super C> observer;
@@ -492,12 +494,24 @@ public ObservableBasedSingleChunkCreator(NonOverlappingChunks<T, C> chunks, Func
492494

493495
private void listenForChunkEnd() {
494496
Observable<? extends TClosing> closingObservable = chunkClosingSelector.call();
495-
closingObservable.subscribe(new Action1<TClosing>() {
497+
closingObservable.unsafeSubscribe(new Subscriber<TClosing>() {
498+
499+
@Override
500+
public void onCompleted() {
501+
502+
}
503+
504+
@Override
505+
public void onError(Throwable e) {
506+
507+
}
508+
496509
@Override
497-
public void call(TClosing closing) {
510+
public void onNext(TClosing t) {
498511
chunks.emitAndReplaceChunk();
499-
listenForChunkEnd();
512+
listenForChunkEnd();
500513
}
514+
501515
});
502516
}
503517

@@ -524,23 +538,47 @@ public void stop() {
524538
*/
525539
protected static class ObservableBasedMultiChunkCreator<T, C, TOpening, TClosing> implements ChunkCreator {
526540

527-
private final SafeObservableSubscription subscription = new SafeObservableSubscription();
541+
private final CompositeSubscription subscription = new CompositeSubscription();
528542

529543
public ObservableBasedMultiChunkCreator(final OverlappingChunks<T, C> chunks, Observable<? extends TOpening> openings, final Func1<? super TOpening, ? extends Observable<? extends TClosing>> chunkClosingSelector) {
530-
subscription.wrap(openings.subscribe(new Action1<TOpening>() {
544+
openings.unsafeSubscribe(new Subscriber<TOpening>(subscription) {
545+
546+
@Override
547+
public void onCompleted() {
548+
549+
}
550+
531551
@Override
532-
public void call(TOpening opening) {
552+
public void onError(Throwable e) {
553+
554+
}
555+
556+
@Override
557+
public void onNext(TOpening opening) {
533558
final Chunk<T, C> chunk = chunks.createChunk();
534559
Observable<? extends TClosing> closingObservable = chunkClosingSelector.call(opening);
535560

536-
closingObservable.subscribe(new Action1<TClosing>() {
561+
closingObservable.unsafeSubscribe(new Subscriber<TClosing>() {
562+
537563
@Override
538-
public void call(TClosing closing) {
539-
chunks.emitChunk(chunk);
564+
public void onCompleted() {
565+
540566
}
541-
});
567+
568+
@Override
569+
public void onError(Throwable e) {
570+
571+
}
572+
573+
@Override
574+
public void onNext(TClosing t) {
575+
chunks.emitChunk(chunk);
576+
}
577+
578+
});
542579
}
543-
}));
580+
581+
});
544582
}
545583

546584
@Override

rxjava-core/src/main/java/rx/operators/NotificationLite.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package rx.operators;
22

3-
import java.io.ObjectStreamException;
43
import java.io.Serializable;
54

65
import rx.Notification;

0 commit comments

Comments
 (0)