diff --git a/rxjava-core/src/main/java/rx/Observable.java b/rxjava-core/src/main/java/rx/Observable.java
index 542bedbff2..3d672326e5 100644
--- a/rxjava-core/src/main/java/rx/Observable.java
+++ b/rxjava-core/src/main/java/rx/Observable.java
@@ -118,6 +118,7 @@
import rx.subjects.ReplaySubject;
import rx.subjects.Subject;
import rx.subscriptions.Subscriptions;
+import rx.util.Exceptions;
import rx.util.OnErrorNotImplementedException;
import rx.util.Range;
import rx.util.TimeInterval;
@@ -6964,10 +6965,9 @@ public void call() {
}
});
- } catch (OnErrorNotImplementedException e) {
- // special handling when onError is not implemented ... we just rethrow
- throw e;
} catch (Throwable e) {
+ // special handling for certain Throwable/Error/Exception types
+ Exceptions.throwIfFatal(e);
// if an unhandled error occurs executing the onSubscribe we will propagate it
try {
observer.onError(hook.onSubscribeError(this, e));
diff --git a/rxjava-core/src/main/java/rx/observers/SafeSubscriber.java b/rxjava-core/src/main/java/rx/observers/SafeSubscriber.java
index a7ce075ef5..d757d85251 100644
--- a/rxjava-core/src/main/java/rx/observers/SafeSubscriber.java
+++ b/rxjava-core/src/main/java/rx/observers/SafeSubscriber.java
@@ -19,11 +19,9 @@
import java.util.concurrent.atomic.AtomicBoolean;
import rx.Subscriber;
-import rx.Subscription;
-import rx.operators.SafeObservableSubscription;
import rx.plugins.RxJavaPlugins;
-import rx.subscriptions.Subscriptions;
import rx.util.CompositeException;
+import rx.util.Exceptions;
import rx.util.OnErrorNotImplementedException;
/**
@@ -74,6 +72,9 @@ public void onCompleted() {
try {
actual.onCompleted();
} catch (Throwable e) {
+ // we handle here instead of another method so we don't add stacks to the frame
+ // which can prevent it from being able to handle StackOverflow
+ Exceptions.throwIfFatal(e);
// handle errors if the onCompleted implementation fails, not just if the Observable fails
_onError(e);
} finally {
@@ -85,6 +86,9 @@ public void onCompleted() {
@Override
public void onError(Throwable e) {
+ // we handle here instead of another method so we don't add stacks to the frame
+ // which can prevent it from being able to handle StackOverflow
+ Exceptions.throwIfFatal(e);
if (isFinished.compareAndSet(false, true)) {
_onError(e);
}
@@ -97,6 +101,9 @@ public void onNext(T args) {
actual.onNext(args);
}
} catch (Throwable e) {
+ // we handle here instead of another method so we don't add stacks to the frame
+ // which can prevent it from being able to handle StackOverflow
+ Exceptions.throwIfFatal(e);
// handle errors if the onNext implementation fails, not just if the Observable fails
onError(e);
}
diff --git a/rxjava-core/src/main/java/rx/observers/SynchronizedObserver.java b/rxjava-core/src/main/java/rx/observers/SynchronizedObserver.java
index ad18e6a2eb..eedecd1368 100644
--- a/rxjava-core/src/main/java/rx/observers/SynchronizedObserver.java
+++ b/rxjava-core/src/main/java/rx/observers/SynchronizedObserver.java
@@ -16,18 +16,11 @@
package rx.observers;
import rx.Observer;
-import rx.Subscriber;
-import rx.operators.SafeObservableSubscription;
/**
- * A thread-safe Observer for transitioning states in operators.
+ * Synchronize execution to be single-threaded.
*
- * Execution rules are:
- *
- *
Allow only single-threaded, synchronous, ordered execution of onNext, onCompleted, onError
- *
Once an onComplete or onError are performed, no further calls can be executed
- *
If unsubscribe is called, this means we call completed() and don't allow any further onNext calls.
- *
+ * This ONLY does synchronization. It does not involve itself in safety or subscriptions. See SafeSubscriber for that.
*
* @param
*/
@@ -48,76 +41,33 @@ public final class SynchronizedObserver implements Observer {
*/
private final Observer super T> observer;
- private final SafeObservableSubscription subscription;
- private volatile boolean finishRequested = false;
- private volatile boolean finished = false;
private volatile Object lock;
- public SynchronizedObserver(Observer super T> subscriber, SafeObservableSubscription subscription) {
+ public SynchronizedObserver(Observer super T> subscriber) {
this.observer = subscriber;
- this.subscription = subscription;
this.lock = this;
}
- public SynchronizedObserver(Observer super T> subscriber, SafeObservableSubscription subscription, Object lock) {
+ public SynchronizedObserver(Observer super T> subscriber, Object lock) {
this.observer = subscriber;
- this.subscription = subscription;
this.lock = lock;
}
- /**
- * Used when synchronizing an Observer without access to the subscription.
- *
- * @param Observer
- */
- public SynchronizedObserver(Observer super T> subscriber) {
- this(subscriber, new SafeObservableSubscription());
- }
-
public void onNext(T arg) {
- if (finished || finishRequested || subscription.isUnsubscribed()) {
- // if we're already stopped, or a finish request has been received, we won't allow further onNext requests
- return;
- }
synchronized (lock) {
- // check again since this could have changed while waiting
- if (finished || finishRequested || subscription.isUnsubscribed()) {
- // if we're already stopped, or a finish request has been received, we won't allow further onNext requests
- return;
- }
observer.onNext(arg);
}
}
public void onError(Throwable e) {
- if (finished || subscription.isUnsubscribed()) {
- // another thread has already finished us, so we won't proceed
- return;
- }
- finishRequested = true;
synchronized (lock) {
- // check again since this could have changed while waiting
- if (finished || subscription.isUnsubscribed()) {
- return;
- }
observer.onError(e);
- finished = true;
}
}
public void onCompleted() {
- if (finished || subscription.isUnsubscribed()) {
- // another thread has already finished us, so we won't proceed
- return;
- }
- finishRequested = true;
synchronized (lock) {
- // check again since this could have changed while waiting
- if (finished || subscription.isUnsubscribed()) {
- return;
- }
observer.onCompleted();
- finished = true;
}
}
}
\ No newline at end of file
diff --git a/rxjava-core/src/main/java/rx/observers/SynchronizedSubscriber.java b/rxjava-core/src/main/java/rx/observers/SynchronizedSubscriber.java
index 54eef0f8cc..8c01f506e1 100644
--- a/rxjava-core/src/main/java/rx/observers/SynchronizedSubscriber.java
+++ b/rxjava-core/src/main/java/rx/observers/SynchronizedSubscriber.java
@@ -17,7 +17,6 @@
import rx.Observer;
import rx.Subscriber;
-import rx.operators.SafeObservableSubscription;
/**
* A thread-safe Observer for transitioning states in operators.
@@ -37,9 +36,7 @@ public final class SynchronizedSubscriber extends Subscriber {
public SynchronizedSubscriber(Subscriber super T> subscriber, Object lock) {
super(subscriber);
- SafeObservableSubscription s = new SafeObservableSubscription();
- subscriber.add(s);
- this.observer = new SynchronizedObserver(subscriber, s, lock);
+ this.observer = new SynchronizedObserver(subscriber, lock);
}
/**
diff --git a/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java b/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java
index d36225a5ed..7a31593d99 100644
--- a/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java
+++ b/rxjava-core/src/main/java/rx/operators/OperationMergeDelayError.java
@@ -151,9 +151,7 @@ public Subscription onSubscribe(Observer super T> actualObserver) {
*
* Bug report: https://github.com/Netflix/RxJava/issues/614
*/
- SafeObservableSubscription subscription = new SafeObservableSubscription(ourSubscription);
- completeSubscription.add(subscription);
- SynchronizedObserver synchronizedObserver = new SynchronizedObserver(actualObserver, subscription);
+ SynchronizedObserver synchronizedObserver = new SynchronizedObserver(actualObserver);
/**
* Subscribe to the parent Observable to get to the children Observables
diff --git a/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java b/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java
index a13fbab9cb..e94411b313 100644
--- a/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java
+++ b/rxjava-core/src/main/java/rx/operators/OperationSynchronize.java
@@ -86,14 +86,13 @@ public Synchronize(Observable extends T> innerObservable, Object lock) {
private Object lock;
public Subscription onSubscribe(Observer super T> observer) {
- SafeObservableSubscription subscription = new SafeObservableSubscription();
if (lock == null) {
- atomicObserver = new SynchronizedObserver(observer, subscription);
+ atomicObserver = new SynchronizedObserver(observer);
}
else {
- atomicObserver = new SynchronizedObserver(observer, subscription, lock);
+ atomicObserver = new SynchronizedObserver(observer, lock);
}
- return subscription.wrap(innerObservable.subscribe(atomicObserver));
+ return innerObservable.subscribe(atomicObserver);
}
}
diff --git a/rxjava-core/src/main/java/rx/operators/OperationZip.java b/rxjava-core/src/main/java/rx/operators/OperationZip.java
deleted file mode 100644
index 7f6affae4f..0000000000
--- a/rxjava-core/src/main/java/rx/operators/OperationZip.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/**
- * Copyright 2014 Netflix, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package rx.operators;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import rx.Observable;
-import rx.Observable.OnSubscribeFunc;
-import rx.Observer;
-import rx.Subscription;
-import rx.subscriptions.CompositeSubscription;
-import rx.subscriptions.SerialSubscription;
-import rx.subscriptions.Subscriptions;
-import rx.util.functions.Func2;
-import rx.util.functions.Func3;
-import rx.util.functions.Func4;
-import rx.util.functions.Func5;
-import rx.util.functions.Func6;
-import rx.util.functions.Func7;
-import rx.util.functions.Func8;
-import rx.util.functions.Func9;
-import rx.util.functions.FuncN;
-import rx.util.functions.Functions;
-
-/**
- * Returns an Observable that emits the results of a function applied to sets of items emitted, in
- * sequence, by two or more other Observables.
- *
- *
- *
- * The zip operation applies this function in strict sequence, so the first item emitted by the new
- * Observable will be the result of the function applied to the first item emitted by each zipped
- * Observable; the second item emitted by the new Observable will be the result of the function
- * applied to the second item emitted by each zipped Observable; and so forth.
- *
- * The resulting Observable returned from zip will invoke onNext as many times as the
- * number of onNext invocations of the source Observable that emits the fewest items.
- */
-public final class OperationZip {
-
- @SuppressWarnings("unchecked")
- public static OnSubscribeFunc zip(Observable extends T1> o1, Observable extends T2> o2, final Func2 super T1, ? super T2, ? extends R> zipFunction) {
- return zip(Arrays.asList(o1, o2), Functions.fromFunc(zipFunction));
- }
-
- @SuppressWarnings("unchecked")
- public static OnSubscribeFunc zip(Observable extends T1> o1, Observable extends T2> o2, Observable extends T3> o3, final Func3 super T1, ? super T2, ? super T3, ? extends R> zipFunction) {
- return zip(Arrays.asList(o1, o2, o3), Functions.fromFunc(zipFunction));
- }
-
- @SuppressWarnings("unchecked")
- public static OnSubscribeFunc zip(Observable extends T1> o1, Observable extends T2> o2, Observable extends T3> o3, Observable extends T4> o4, final Func4 super T1, ? super T2, ? super T3, ? super T4, ? extends R> zipFunction) {
- return zip(Arrays.asList(o1, o2, o3, o4), Functions.fromFunc(zipFunction));
- }
-
- @SuppressWarnings("unchecked")
- public static OnSubscribeFunc zip(Observable extends T1> o1, Observable extends T2> o2, Observable extends T3> o3, Observable extends T4> o4, Observable extends T5> o5, final Func5 super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? extends R> zipFunction) {
- return zip(Arrays.asList(o1, o2, o3, o4, o5), Functions.fromFunc(zipFunction));
- }
-
- @SuppressWarnings("unchecked")
- public static OnSubscribeFunc zip(Observable extends T1> o1, Observable extends T2> o2, Observable extends T3> o3, Observable extends T4> o4, Observable extends T5> o5, Observable extends T6> o6,
- final Func6 super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? extends R> zipFunction) {
- return zip(Arrays.asList(o1, o2, o3, o4, o5, o6), Functions.fromFunc(zipFunction));
- }
-
- @SuppressWarnings("unchecked")
- public static OnSubscribeFunc zip(Observable extends T1> o1, Observable extends T2> o2, Observable extends T3> o3, Observable extends T4> o4, Observable extends T5> o5, Observable extends T6> o6, Observable extends T7> o7,
- final Func7 super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? extends R> zipFunction) {
- return zip(Arrays.asList(o1, o2, o3, o4, o5, o6, o7), Functions.fromFunc(zipFunction));
- }
-
- @SuppressWarnings("unchecked")
- public static OnSubscribeFunc zip(Observable extends T1> o1, Observable extends T2> o2, Observable extends T3> o3, Observable extends T4> o4, Observable extends T5> o5, Observable extends T6> o6, Observable extends T7> o7, Observable extends T8> o8,
- final Func8 super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? super T8, ? extends R> zipFunction) {
- return zip(Arrays.asList(o1, o2, o3, o4, o5, o6, o7, o8), Functions.fromFunc(zipFunction));
- }
-
- @SuppressWarnings("unchecked")
- public static OnSubscribeFunc zip(Observable extends T1> o1, Observable extends T2> o2, Observable extends T3> o3, Observable extends T4> o4, Observable extends T5> o5, Observable extends T6> o6, Observable extends T7> o7, Observable extends T8> o8,
- Observable extends T9> o9, final Func9 super T1, ? super T2, ? super T3, ? super T4, ? super T5, ? super T6, ? super T7, ? super T8, ? super T9, ? extends R> zipFunction) {
- return zip(Arrays.asList(o1, o2, o3, o4, o5, o6, o7, o8, o9), Functions.fromFunc(zipFunction));
- }
-
- public static OnSubscribeFunc zip(Iterable extends Observable>> ws, final FuncN extends R> zipFunction) {
- return new ManyObservables