update code style

This commit is contained in:
huangyuhui
2016-01-01 11:03:09 +08:00
parent 1f7eb04215
commit b82243a9c0
298 changed files with 3902 additions and 3998 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -18,28 +18,36 @@ package rx;
/**
* Provides a mechanism for receiving push-based notifications.
* <p>
* After an Observer calls an {@link Observable}'s <code>Observable.subscribe</code> method, the {@link Observable} calls the Observer's <code>onNext</code> method to provide notifications. A
* well-behaved {@link Observable} will
* call an Observer's <code>onCompleted</code> closure exactly once or the Observer's <code>onError</code> closure exactly once.
* After an Observer calls an {@link Observable}'s
* <code>Observable.subscribe</code> method, the {@link Observable} calls the
* Observer's <code>onNext</code> method to provide notifications. A
* well-behaved {@link Observable} will call an Observer's
* <code>onCompleted</code> closure exactly once or the Observer's
* <code>onError</code> closure exactly once.
* <p>
* For more information see the <a href="https://github.com/Netflix/RxJava/wiki/Observable">RxJava Wiki</a>
*
* For more information see the
* <a href="https://github.com/Netflix/RxJava/wiki/Observable">RxJava Wiki</a>
*
* @param <T>
*/
public interface Observer<T> {
/**
* Notifies the Observer that the {@link Observable} has finished sending push-based notifications.
* Notifies the Observer that the {@link Observable} has finished sending
* push-based notifications.
* <p>
* The {@link Observable} will not call this closure if it calls <code>onError</code>.
* The {@link Observable} will not call this closure if it calls
* <code>onError</code>.
*/
public void onCompleted();
/**
* Notifies the Observer that the {@link Observable} has experienced an error condition.
* Notifies the Observer that the {@link Observable} has experienced an
* error condition.
* <p>
* If the {@link Observable} calls this closure, it will not thereafter call <code>onNext</code> or <code>onCompleted</code>.
*
* If the {@link Observable} calls this closure, it will not thereafter call
* <code>onNext</code> or <code>onCompleted</code>.
*
* @param e
*/
public void onError(Exception e);
@@ -47,10 +55,13 @@ public interface Observer<T> {
/**
* Provides the Observer with new data.
* <p>
* The {@link Observable} calls this closure 1 or more times, unless it calls <code>onError</code> in which case this closure may never be called.
* The {@link Observable} calls this closure 1 or more times, unless it
* calls <code>onError</code> in which case this closure may never be
* called.
* <p>
* The {@link Observable} will not call this closure again after it calls either <code>onCompleted</code> or <code>onError</code>.
*
* The {@link Observable} will not call this closure again after it calls
* either <code>onCompleted</code> or <code>onError</code>.
*
* @param args
*/
public void onNext(T args);

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -27,36 +27,36 @@ public interface Scheduler {
/**
* Schedules a cancelable action to be executed.
*
* @param action
* action
*
* @param action action
*
* @return a subscription to be able to unsubscribe from action.
*/
Subscription schedule(Func0<Subscription> action);
/**
* Schedules an action to be executed.
*
* @param action
* action
*
* @param action action
*
* @return a subscription to be able to unsubscribe from action.
*/
Subscription schedule(Action0 action);
/**
* Schedules an action to be executed in dueTime.
*
* @param action
* action
*
* @param action action
*
* @return a subscription to be able to unsubscribe from action.
*/
Subscription schedule(Action0 action, long dueTime, TimeUnit unit);
/**
* Schedules a cancelable action to be executed in dueTime.
*
* @param action
* action
*
* @param action action
*
* @return a subscription to be able to unsubscribe from action.
*/
Subscription schedule(Func0<Subscription> action, long dueTime, TimeUnit unit);

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -18,16 +18,20 @@ package rx;
import rx.subscriptions.Subscriptions;
/**
* Subscription returns from {@link Observable#subscribe(Observer)} to allow unsubscribing.
* Subscription returns from {@link Observable#subscribe(Observer)} to allow
* unsubscribing.
* <p>
* See utilities in {@link Subscriptions} and implementations in the {@link rx.subscriptions} package.
* See utilities in {@link Subscriptions} and implementations in the
* {@link rx.subscriptions} package.
*/
public interface Subscription {
/**
* Stop receiving notifications on the {@link Observer} that was registered when this Subscription was received.
* Stop receiving notifications on the {@link Observer} that was registered
* when this Subscription was received.
* <p>
* This allows unregistering an {@link Observer} before it has finished receiving all events (ie. before onCompleted is called).
* This allows unregistering an {@link Observer} before it has finished
* receiving all events (ie. before onCompleted is called).
*/
public void unsubscribe();

View File

@@ -23,7 +23,9 @@ import rx.subscriptions.Subscriptions;
import rx.util.functions.Action0;
import rx.util.functions.Func0;
/* package */
/*
* package
*/
abstract class AbstractScheduler implements Scheduler {
@Override

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -23,9 +23,11 @@ import rx.Subscription;
import rx.util.functions.Func0;
/**
* Schedules work on the current thread but does not execute immediately. Work is put in a queue and executed after the current unit of work is completed.
* Schedules work on the current thread but does not execute immediately. Work
* is put in a queue and executed after the current unit of work is completed.
*/
public class CurrentThreadScheduler extends AbstractScheduler {
private static final CurrentThreadScheduler INSTANCE = new CurrentThreadScheduler();
public static CurrentThreadScheduler getInstance() {
@@ -61,9 +63,8 @@ public class CurrentThreadScheduler extends AbstractScheduler {
queue.add(action);
if (exec) {
while (!queue.isEmpty()) {
while (!queue.isEmpty())
queue.poll().call();
}
QUEUE.set(null);
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -22,9 +22,15 @@ import rx.util.AtomicObservableSubscription;
import rx.util.functions.Func0;
/**
* Combines standard {@link Subscription#unsubscribe()} functionality with ability to skip execution if an unsubscribe occurs before the {@link #call()} method is invoked.
* Combines standard {@link Subscription#unsubscribe()} functionality with
* ability to skip execution if an unsubscribe occurs before the {@link #call()}
* method is invoked.
*/
/* package */class DiscardableAction implements Func0<Subscription>, Subscription {
/*
* package
*/
class DiscardableAction implements Func0<Subscription>, Subscription {
private final Func0<Subscription> underlying;
private final AtomicObservableSubscription wrapper = new AtomicObservableSubscription();

View File

@@ -1,7 +1,7 @@
/*
* Hello Minecraft! Launcher.
* Copyright (C) 2013 huangyuhui <huanghongxun2008@126.com>
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -27,6 +27,7 @@ import rx.util.functions.Func0;
* @author huangyuhui
*/
public class EventQueueScheduler extends AbstractScheduler {
private static final EventQueueScheduler INSTANCE = new EventQueueScheduler();
public static EventQueueScheduler getInstance() {

View File

@@ -53,16 +53,16 @@ public class ExecutorScheduler extends AbstractScheduler {
count = 8;
SYSTEM_SCHEDULED_EXECUTOR = Executors.newScheduledThreadPool(count, new ThreadFactory() {
final AtomicInteger counter = new AtomicInteger();
final AtomicInteger counter = new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "RxScheduledExecutorPool-" + counter.incrementAndGet());
t.setDaemon(true);
return t;
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "RxScheduledExecutorPool-" + counter.incrementAndGet());
t.setDaemon(true);
return t;
}
});
});
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -24,6 +24,7 @@ import rx.util.functions.Func0;
* Executes work immediately on the current thread.
*/
public final class ImmediateScheduler extends AbstractScheduler {
private static final ImmediateScheduler INSTANCE = new ImmediateScheduler();
public static ImmediateScheduler getInstance() {

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -24,6 +24,7 @@ import rx.util.functions.Func0;
* Schedules work on a new thread.
*/
public class NewThreadScheduler extends AbstractScheduler {
private static final NewThreadScheduler INSTANCE = new NewThreadScheduler();
public static NewThreadScheduler getInstance() {

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -28,6 +28,7 @@ import rx.Scheduler;
* Static factory methods for creating Schedulers.
*/
public class Schedulers {
private static final ScheduledExecutorService COMPUTATION_EXECUTOR = createComputationExecutor();
private static final Executor IO_EXECUTOR = createIOExecutor();
@@ -37,7 +38,7 @@ public class Schedulers {
/**
* {@link Scheduler} that executes work immediately on the current thread.
*
*
* @return {@link ImmediateScheduler} instance
*/
public static Scheduler immediate() {
@@ -45,8 +46,9 @@ public class Schedulers {
}
/**
* {@link Scheduler} that queues work on the current thread to be executed after the current work completes.
*
* {@link Scheduler} that queues work on the current thread to be executed
* after the current work completes.
*
* @return {@link CurrentThreadScheduler} instance
*/
public static Scheduler currentThread() {
@@ -54,8 +56,9 @@ public class Schedulers {
}
/**
* {@link Scheduler} that creates a new {@link Thread} for each unit of work.
*
* {@link Scheduler} that creates a new {@link Thread} for each unit of
* work.
*
* @return {@link NewThreadScheduler} instance
*/
public static Scheduler newThread() {
@@ -63,8 +66,9 @@ public class Schedulers {
}
/**
* {@link Scheduler} that queues work on the EventQueue thread to be executed on the Swing UI Thread.
*
* {@link Scheduler} that queues work on the EventQueue thread to be
* executed on the Swing UI Thread.
*
* @return {@link NewThreadScheduler} instance
*/
public static Scheduler eventQueue() {
@@ -75,7 +79,7 @@ public class Schedulers {
* {@link Scheduler} that queues work on an {@link Executor}.
* <p>
* Note that this does not support scheduled actions with a delay.
*
*
* @return {@link ExecutorScheduler} instance
*/
public static Scheduler executor(Executor executor) {
@@ -83,8 +87,9 @@ public class Schedulers {
}
/**
* {@link Scheduler} that queues work on an {@link ScheduledExecutorService}.
*
* {@link Scheduler} that queues work on an
* {@link ScheduledExecutorService}.
*
* @return {@link ExecutorScheduler} instance
*/
public static Scheduler executor(ScheduledExecutorService executor) {
@@ -94,12 +99,15 @@ public class Schedulers {
/**
* {@link Scheduler} intended for computational work.
* <p>
* The implementation is backed by a {@link ScheduledExecutorService} thread-pool sized to the number of CPU cores.
* The implementation is backed by a {@link ScheduledExecutorService}
* thread-pool sized to the number of CPU cores.
* <p>
* This can be used for event-loops, processing callbacks and other computational work.
* This can be used for event-loops, processing callbacks and other
* computational work.
* <p>
* Do not perform IO-bound work on this scheduler. Use {@link #threadPoolForComputation()} instead.
*
* Do not perform IO-bound work on this scheduler. Use
* {@link #threadPoolForComputation()} instead.
*
* @return {@link ExecutorScheduler} for computation-bound work.
*/
public static Scheduler threadPoolForComputation() {
@@ -109,12 +117,14 @@ public class Schedulers {
/**
* {@link Scheduler} intended for IO-bound work.
* <p>
* The implementation is backed by an {@link Executor} thread-pool that will grow as needed.
* The implementation is backed by an {@link Executor} thread-pool that will
* grow as needed.
* <p>
* This can be used for asynchronously performing blocking IO.
* <p>
* Do not perform computational work on this scheduler. Use {@link #threadPoolForComputation()} instead.
*
* Do not perform computational work on this scheduler. Use
* {@link #threadPoolForComputation()} instead.
*
* @return {@link ExecutorScheduler} for IO-bound work.
*/
public static Scheduler threadPoolForIO() {
@@ -124,15 +134,15 @@ public class Schedulers {
private static ScheduledExecutorService createComputationExecutor() {
int cores = Runtime.getRuntime().availableProcessors();
return Executors.newScheduledThreadPool(cores, new ThreadFactory() {
final AtomicInteger counter = new AtomicInteger();
final AtomicInteger counter = new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "RxComputationThreadPool-" + counter.incrementAndGet());
t.setDaemon(true);
return t;
}
});
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "RxComputationThreadPool-" + counter.incrementAndGet());
t.setDaemon(true);
return t;
}
});
}
private static Executor createIOExecutor() {

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -21,7 +21,11 @@ import rx.Scheduler;
import rx.Subscription;
import rx.util.functions.Func0;
/* package */class SleepingAction implements Func0<Subscription> {
/*
* package
*/
class SleepingAction implements Func0<Subscription> {
private final Func0<Subscription> underlying;
private final Scheduler scheduler;
private final long execTime;
@@ -34,14 +38,13 @@ import rx.util.functions.Func0;
@Override
public Subscription call() {
if (execTime < scheduler.now()) {
if (execTime < scheduler.now())
try {
Thread.sleep(scheduler.now() - execTime);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
}
return underlying.call();

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -21,14 +21,17 @@ import rx.Subscription;
import rx.util.functions.Func1;
/**
* An {@link Observable} that has been grouped by a key whose value can be obtained using {@link #getKey()} <p>
*
* An {@link Observable} that has been grouped by a key whose value can be
* obtained using {@link #getKey()}
* <p>
*
* @see {@link Observable#groupBy(Observable, Func1)}
*
*
* @param <K>
* @param <T>
*/
public class GroupedObservable<K, T> extends Observable<T> {
private final K key;
public GroupedObservable(K key, Func1<Observer<T>, Subscription> onSubscribe) {

View File

@@ -15,19 +15,18 @@ public class OperationAll {
}
private static class AllObservable<T> implements Func1<Observer<Boolean>, Subscription> {
private final Observable<T> sequence;
private final Func1<T, Boolean> predicate;
private final AtomicBoolean status = new AtomicBoolean(true);
private final AtomicObservableSubscription subscription = new AtomicObservableSubscription();
private AllObservable(Observable<T> sequence, Func1<T, Boolean> predicate) {
this.sequence = sequence;
this.predicate = predicate;
}
@Override
public Subscription call(final Observer<Boolean> observer) {
return subscription.wrap(sequence.subscribe(new Observer<T>() {

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -36,12 +36,18 @@ import rx.util.functions.Functions;
public class OperationCombineLatest {
/**
* Combines the two given observables, emitting an event containing an aggregation of the latest values of each of the source observables
* each time an event is received from one of the source observables, where the aggregation is defined by the given function.
* @param w0 The first source observable.
* @param w1 The second source observable.
* @param combineLatestFunction The aggregation function used to combine the source observable values.
* @return A function from an observer to a subscription. This can be used to create an observable from.
* Combines the two given observables, emitting an event containing an
* aggregation of the latest values of each of the source observables each
* time an event is received from one of the source observables, where the
* aggregation is defined by the given function.
*
* @param w0 The first source observable.
* @param w1 The second source observable.
* @param combineLatestFunction The aggregation function used to combine the
* source observable values.
*
* @return A function from an observer to a subscription. This can be used
* to create an observable from.
*/
public static <T0, T1, R> Func1<Observer<R>, Subscription> combineLatest(Observable<T0> w0, Observable<T1> w1, Func2<T0, T1, R> combineLatestFunction) {
Aggregator<R> a = new Aggregator<>(Functions.fromFunc(combineLatestFunction));
@@ -51,7 +57,8 @@ public class OperationCombineLatest {
}
/**
* @see #combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction)
* @see #combineLatest(Observable w0, Observable w1, Func2
* combineLatestFunction)
*/
public static <T0, T1, T2, R> Func1<Observer<R>, Subscription> combineLatest(Observable<T0> w0, Observable<T1> w1, Observable<T2> w2, Func3<T0, T1, T2, R> combineLatestFunction) {
Aggregator<R> a = new Aggregator<>(Functions.fromFunc(combineLatestFunction));
@@ -62,7 +69,8 @@ public class OperationCombineLatest {
}
/**
* @see #combineLatest(Observable w0, Observable w1, Func2 combineLatestFunction)
* @see #combineLatest(Observable w0, Observable w1, Func2
* combineLatestFunction)
*/
public static <T0, T1, T2, T3, R> Func1<Observer<R>, Subscription> combineLatest(Observable<T0> w0, Observable<T1> w1, Observable<T2> w2, Observable<T3> w3, Func4<T0, T1, T2, T3, R> combineLatestFunction) {
Aggregator<R> a = new Aggregator<>(Functions.fromFunc(combineLatestFunction));
@@ -74,6 +82,7 @@ public class OperationCombineLatest {
}
private static class CombineObserver<R, T> implements Observer<T> {
final Observable<T> w;
final Aggregator<R> a;
private Subscription subscription;
@@ -84,9 +93,8 @@ public class OperationCombineLatest {
}
public synchronized void startWatching() {
if (subscription != null) {
if (subscription != null)
throw new RuntimeException("This should only be called once.");
}
subscription = w.subscribe(this);
}
@@ -107,9 +115,10 @@ public class OperationCombineLatest {
}
/**
* Receive notifications from each of the observables we are reducing and execute the combineLatestFunction
* whenever we have received an event from one of the observables, as soon as each Observable has received
* at least one event.
* Receive notifications from each of the observables we are reducing and
* execute the combineLatestFunction whenever we have received an event from
* one of the observables, as soon as each Observable has received at least
* one event.
*/
private static class Aggregator<R> implements Func1<Observer<R>, Subscription> {
@@ -120,31 +129,37 @@ public class OperationCombineLatest {
// used as an internal lock for handling the latest values and the completed state of each observer
private final Object lockObject = new Object();
/**
* Store when an observer completes.
* <p>
* Note that access to this set MUST BE SYNCHRONIZED via 'lockObject' above.
* */
* Note that access to this set MUST BE SYNCHRONIZED via 'lockObject'
* above.
*
*/
private final Set<CombineObserver<R, ?>> completed = new HashSet<>();
/**
* The latest value from each observer
* <p>
* Note that access to this set MUST BE SYNCHRONIZED via 'lockObject' above.
* */
* Note that access to this set MUST BE SYNCHRONIZED via 'lockObject'
* above.
*
*/
private final Map<CombineObserver<R, ?>, Object> latestValue = new HashMap<>();
/**
* Whether each observer has a latest value at all.
* <p>
* Note that access to this set MUST BE SYNCHRONIZED via 'lockObject' above.
* */
* Note that access to this set MUST BE SYNCHRONIZED via 'lockObject'
* above.
*
*/
private final Set<CombineObserver<R, ?>> hasLatestValue = new HashSet<>();
/**
* Ordered list of observers to combine.
* No synchronization is necessary as these can not be added or changed asynchronously.
* Ordered list of observers to combine. No synchronization is necessary
* as these can not be added or changed asynchronously.
*/
private final List<CombineObserver<R, ?>> observers = new LinkedList<>();
@@ -153,8 +168,9 @@ public class OperationCombineLatest {
}
/**
* Receive notification of a Observer starting (meaning we should require it for aggregation)
*
* Receive notification of a Observer starting (meaning we should
* require it for aggregation)
*
* @param w The observer to add.
*/
<T> void addObserver(CombineObserver<R, T> w) {
@@ -163,51 +179,56 @@ public class OperationCombineLatest {
/**
* Receive notification of a Observer completing its iterations.
*
*
* @param w The observer that has completed.
*/
<T> void complete(CombineObserver<R, T> w) {
synchronized(lockObject) {
synchronized (lockObject) {
// store that this CombineLatestObserver is completed
completed.add(w);
// if all CombineObservers are completed, we mark the whole thing as completed
if (completed.size() == observers.size()) {
if (completed.size() == observers.size())
if (running.get()) {
// mark ourselves as done
observer.onCompleted();
// just to ensure we stop processing in case we receive more onNext/complete/error calls after this
running.set(false);
}
}
}
}
/**
* Receive error for a Observer. Throw the error up the chain and stop processing.
* Receive error for a Observer. Throw the error up the chain and stop
* processing.
*/
void error(Exception e) {
observer.onError(e);
/* tell all observers to unsubscribe since we had an error */
/*
* tell all observers to unsubscribe since we had an error
*/
stop();
}
/**
* Receive the next value from an observer.
* <p>
* If we have received values from all observers, trigger the combineLatest function, otherwise store the value and keep waiting.
*
* If we have received values from all observers, trigger the
* combineLatest function, otherwise store the value and keep waiting.
*
* @param w
* @param arg
*/
<T> void next(CombineObserver<R, T> w, T arg) {
if (observer == null) {
if (observer == null)
throw new RuntimeException("This shouldn't be running if an Observer isn't registered");
}
/* if we've been 'unsubscribed' don't process anything further even if the things we're watching keep sending (likely because they are not responding to the unsubscribe call) */
if (!running.get()) {
/*
* if we've been 'unsubscribed' don't process anything further even
* if the things we're watching keep sending (likely because they
* are not responding to the unsubscribe call)
*/
if (!running.get())
return;
}
// define here so the variable is out of the synchronized scope
Object[] argsToCombineLatest = new Object[observers.size()];
@@ -216,22 +237,19 @@ public class OperationCombineLatest {
synchronized (lockObject) {
// remember this as the latest value for this observer
latestValue.put(w, arg);
// remember that this observer now has a latest value set
hasLatestValue.add(w);
// if all observers in the 'observers' list have a value, invoke the combineLatestFunction
for (CombineObserver<R, ?> rw : observers) {
if (!hasLatestValue.contains(rw)) {
for (CombineObserver<R, ?> rw : observers)
if (!hasLatestValue.contains(rw))
// we don't have a value yet for each observer to combine, so we don't have a combined value yet either
return;
}
}
// if we get to here this means all the queues have data
int i = 0;
for (CombineObserver<R, ?> _w : observers) {
for (CombineObserver<R, ?> _w : observers)
argsToCombineLatest[i++] = latestValue.get(_w);
}
}
// if we did not return above from the synchronized block we can now invoke the combineLatestFunction with all of the args
// we do this outside the synchronized block as it is now safe to call this concurrently and don't need to block other threads from calling
@@ -241,15 +259,15 @@ public class OperationCombineLatest {
@Override
public Subscription call(Observer<R> observer) {
if (this.observer != null) {
if (this.observer != null)
throw new IllegalStateException("Only one Observer can subscribe to this Observable.");
}
this.observer = observer;
/* start the observers */
for (CombineObserver<R, ?> rw : observers) {
/*
* start the observers
*/
for (CombineObserver<R, ?> rw : observers)
rw.startWatching();
}
return new Subscription() {
@Override
@@ -260,14 +278,16 @@ public class OperationCombineLatest {
}
private void stop() {
/* tell ourselves to stop processing onNext events */
/*
* tell ourselves to stop processing onNext events
*/
running.set(false);
/* propogate to all observers to unsubscribe */
for (CombineObserver<R, ?> rw : observers) {
if (rw.subscription != null) {
/*
* propogate to all observers to unsubscribe
*/
for (CombineObserver<R, ?> rw : observers)
if (rw.subscription != null)
rw.subscription.unsubscribe();
}
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -30,11 +30,13 @@ import rx.util.functions.Func1;
public final class OperationConcat {
/**
* Combine the observable sequences from the list of Observables into one observable sequence without any transformation.
*
* @param sequences
* An observable sequence of elements to project.
* @return An observable sequence whose elements are the result of combining the output from the list of Observables.
* Combine the observable sequences from the list of Observables into one
* observable sequence without any transformation.
*
* @param sequences An observable sequence of elements to project.
*
* @return An observable sequence whose elements are the result of combining
* the output from the list of Observables.
*/
public static <T> Func1<Observer<T>, Subscription> concat(final Observable<T>... sequences) {
return new Func1<Observer<T>, Subscription>() {
@@ -66,6 +68,7 @@ public final class OperationConcat {
}
private static class Concat<T> implements Func1<Observer<T>, Subscription> {
private final Observable<T>[] sequences;
private int num = 0;
private int count = 0;
@@ -94,6 +97,7 @@ public final class OperationConcat {
}
private class ConcatObserver implements Observer<T> {
private final Observer<T> observer;
ConcatObserver(Observer<T> observer) {
@@ -123,4 +127,4 @@ public final class OperationConcat {
}
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -22,17 +22,23 @@ import rx.Subscription;
import rx.util.functions.Func1;
/**
* Dematerializes the explicit notification values of an observable sequence as implicit notifications.
* See http://msdn.microsoft.com/en-us/library/hh229047(v=vs.103).aspx for the Microsoft Rx equivalent.
* Dematerializes the explicit notification values of an observable sequence as
* implicit notifications. See
* http://msdn.microsoft.com/en-us/library/hh229047(v=vs.103).aspx for the
* Microsoft Rx equivalent.
*/
public final class OperationDematerialize {
/**
* Dematerializes the explicit notification values of an observable sequence as implicit notifications.
*
* @param sequence
* An observable sequence containing explicit notification values which have to be turned into implicit notifications.
* @return An observable sequence exhibiting the behavior corresponding to the source sequence's notification values.
* Dematerializes the explicit notification values of an observable sequence
* as implicit notifications.
*
* @param sequence An observable sequence containing explicit notification
* values which have to be turned into implicit notifications.
*
* @return An observable sequence exhibiting the behavior corresponding to
* the source sequence's notification values.
*
* @see http://msdn.microsoft.com/en-us/library/hh229047(v=vs.103).aspx
*/
public static <T> Func1<Observer<T>, Subscription> dematerialize(final Observable<Notification<T>> sequence) {

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -44,16 +44,15 @@ public final class OperationFilter<T> {
@Override
public void onNext(T value) {
try {
if (predicate.call(value)) {
if (predicate.call(value))
observer.onNext(value);
}
} catch (Exception ex) {
observer.onError(ex);
// this will work if the sequence is asynchronous, it will have no effect on a synchronous observable
subscription.unsubscribe();
}
}
@Override
public void onError(Exception ex) {
observer.onError(ex);
@@ -67,4 +66,4 @@ public final class OperationFilter<T> {
}
}
}
}

View File

@@ -25,25 +25,31 @@ public final class OperationFinally {
/**
* Call a given action when a sequence completes (with or without an
* exception). The returned observable is exactly as threadsafe as the
* exception). The returned observable is exactly as threadsafe as the
* source observable.
* <p/>
* Note that "finally" is a Java reserved word and cannot be an identifier,
* so we use "finallyDo".
*
* @param sequence An observable sequence of elements
* @param action An action to be taken when the sequence is complete or throws an exception
* @return An observable sequence with the same elements as the input.
* After the last element is consumed (and {@link Observer#onCompleted} has been called),
* or after an exception is thrown (and {@link Observer#onError} has been called),
* the given action will be called.
* @see <a href="http://msdn.microsoft.com/en-us/library/hh212133(v=vs.103).aspx">MSDN Observable.Finally method</a>
* @param action An action to be taken when the sequence is complete or
* throws an exception
*
* @return An observable sequence with the same elements as the input. After
* the last element is consumed (and {@link Observer#onCompleted} has been
* called), or after an exception is thrown (and {@link Observer#onError}
* has been called), the given action will be called.
*
* @see
* <a href="http://msdn.microsoft.com/en-us/library/hh212133(v=vs.103).aspx">MSDN
* Observable.Finally method</a>
*/
public static <T> Func1<Observer<T>, Subscription> finallyDo(final Observable<T> sequence, final Action0 action) {
return new Finally<>(sequence, action)::call;
}
private static class Finally<T> implements Func1<Observer<T>, Subscription> {
private final Observable<T> sequence;
private final Action0 finalAction;
@@ -58,6 +64,7 @@ public final class OperationFinally {
}
private class FinallyObserver implements Observer<T> {
private final Observer<T> observer;
FinallyObserver(Observer<T> observer) {

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -23,52 +23,51 @@ import rx.util.functions.Func1;
public final class OperationMap {
/**
* Accepts a sequence and a transformation function. Returns a sequence that is the result of
* applying the transformation function to each item in the sequence.
*
* @param sequence
* the input sequence.
* @param func
* a function to apply to each item in the sequence.
* @param <T>
* the type of the input sequence.
* @param <R>
* the type of the output sequence.
* @return a sequence that is the result of applying the transformation function to each item in the input sequence.
* Accepts a sequence and a transformation function. Returns a sequence that
* is the result of applying the transformation function to each item in the
* sequence.
*
* @param sequence the input sequence.
* @param func a function to apply to each item in the sequence.
* @param <T> the type of the input sequence.
* @param <R> the type of the output sequence.
*
* @return a sequence that is the result of applying the transformation
* function to each item in the input sequence.
*/
public static <T, R> Func1<Observer<R>, Subscription> map(Observable<T> sequence, Func1<T, R> func) {
return new MapObservable<>(sequence, func);
}
/**
* Accepts a sequence of observable sequences and a transformation function. Returns a flattened sequence that is the result of
* applying the transformation function to each item in the sequence of each observable sequence.
* Accepts a sequence of observable sequences and a transformation function.
* Returns a flattened sequence that is the result of applying the
* transformation function to each item in the sequence of each observable
* sequence.
* <p>
* The closure should return an Observable which will then be merged.
*
* @param sequence
* the input sequence.
* @param func
* a function to apply to each item in the sequence.
* @param <T>
* the type of the input sequence.
* @param <R>
* the type of the output sequence.
* @return a sequence that is the result of applying the transformation function to each item in the input sequence.
*
* @param sequence the input sequence.
* @param func a function to apply to each item in the sequence.
* @param <T> the type of the input sequence.
* @param <R> the type of the output sequence.
*
* @return a sequence that is the result of applying the transformation
* function to each item in the input sequence.
*/
public static <T, R> Func1<Observer<R>, Subscription> mapMany(Observable<T> sequence, Func1<T, Observable<R>> func) {
return OperationMerge.merge(Observable.create(map(sequence, func)));
}
/**
* An observable sequence that is the result of applying a transformation to each item in an input sequence.
*
* @param <T>
* the type of the input sequence.
* @param <R>
* the type of the output sequence.
* An observable sequence that is the result of applying a transformation to
* each item in an input sequence.
*
* @param <T> the type of the input sequence.
* @param <R> the type of the output sequence.
*/
private static class MapObservable<T, R> implements Func1<Observer<R>, Subscription> {
public MapObservable(Observable<T> sequence, Func1<T, R> func) {
this.sequence = sequence;
this.func = func;
@@ -85,14 +84,14 @@ public final class OperationMap {
}
/**
* An observer that applies a transformation function to each item and forwards the result to an inner observer.
*
* @param <T>
* the type of the observer items.
* @param <R>
* the type of the inner observer items.
* An observer that applies a transformation function to each item and
* forwards the result to an inner observer.
*
* @param <T> the type of the observer items.
* @param <R> the type of the inner observer items.
*/
private static class MapObserver<T, R> implements Observer<T> {
public MapObserver(Observer<R> observer, Func1<T, R> func) {
this.observer = observer;
this.func = func;

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -22,20 +22,27 @@ import rx.Subscription;
import rx.util.functions.Func1;
/**
* Materializes the implicit notifications of an observable sequence as explicit notification values.
* Materializes the implicit notifications of an observable sequence as explicit
* notification values.
* <p>
* In other words, converts a sequence of OnNext, OnError and OnCompleted events into a sequence of ObservableNotifications containing the OnNext, OnError and OnCompleted values.
* In other words, converts a sequence of OnNext, OnError and OnCompleted events
* into a sequence of ObservableNotifications containing the OnNext, OnError and
* OnCompleted values.
* <p>
* See http://msdn.microsoft.com/en-us/library/hh229453(v=VS.103).aspx for the Microsoft Rx equivalent.
* See http://msdn.microsoft.com/en-us/library/hh229453(v=VS.103).aspx for the
* Microsoft Rx equivalent.
*/
public final class OperationMaterialize {
/**
* Materializes the implicit notifications of an observable sequence as explicit notification values.
*
* @param sequence
* An observable sequence of elements to project.
* @return An observable sequence whose elements are the result of materializing the notifications of the given sequence.
* Materializes the implicit notifications of an observable sequence as
* explicit notification values.
*
* @param sequence An observable sequence of elements to project.
*
* @return An observable sequence whose elements are the result of
* materializing the notifications of the given sequence.
*
* @see http://msdn.microsoft.com/en-us/library/hh229453(v=VS.103).aspx
*/
public static <T> Func1<Observer<Notification<T>>, Subscription> materialize(final Observable<T> sequence) {

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -30,11 +30,14 @@ import rx.util.functions.Func1;
public final class OperationMerge {
/**
* Flattens the observable sequences from the list of Observables into one observable sequence without any transformation.
*
* @param source
* An observable sequence of elements to project.
* @return An observable sequence whose elements are the result of flattening the output from the list of Observables.
* Flattens the observable sequences from the list of Observables into one
* observable sequence without any transformation.
*
* @param source An observable sequence of elements to project.
*
* @return An observable sequence whose elements are the result of
* flattening the output from the list of Observables.
*
* @see http://msdn.microsoft.com/en-us/library/hh229099(v=vs.103).aspx
*/
public static <T> Func1<Observer<T>, Subscription> merge(final Observable<Observable<T>> source) {
@@ -53,17 +56,14 @@ public final class OperationMerge {
@Override
public Subscription call(Observer<Observable<T>> observer) {
for (Observable<T> o : sequences) {
if (!unsubscribed) {
for (Observable<T> o : sequences)
if (!unsubscribed)
observer.onNext(o);
} else {
else
// break out of the loop if we are unsubscribed
break;
}
}
if (!unsubscribed) {
if (!unsubscribed)
observer.onCompleted();
}
return () -> {
unsubscribed = true;
@@ -73,17 +73,24 @@ public final class OperationMerge {
}
/**
* This class is NOT thread-safe if invoked and referenced multiple times. In other words, don't subscribe to it multiple times from different threads.
* This class is NOT thread-safe if invoked and referenced multiple times.
* In other words, don't subscribe to it multiple times from different
* threads.
* <p>
* It IS thread-safe from within it while receiving onNext events from multiple threads.
* It IS thread-safe from within it while receiving onNext events from
* multiple threads.
* <p>
* This should all be fine as long as it's kept as a private class and a new instance created from static factory method above.
* This should all be fine as long as it's kept as a private class and a new
* instance created from static factory method above.
* <p>
* Note how the take() factory method above protects us from a single instance being exposed with the Observable wrapper handling the subscribe flow.
*
* Note how the take() factory method above protects us from a single
* instance being exposed with the Observable wrapper handling the subscribe
* flow.
*
* @param <T>
*/
private static final class MergeObservable<T> implements Func1<Observer<T>, Subscription> {
private final Observable<Observable<T>> sequences;
private final MergeSubscription ourSubscription = new MergeSubscription();
private final AtomicBoolean stopped = new AtomicBoolean(false);
@@ -99,7 +106,8 @@ public final class OperationMerge {
public Subscription call(Observer<T> actualObserver) {
/**
* We must synchronize a merge because we subscribe to multiple sequences in parallel that will each be emitting.
* We must synchronize a merge because we subscribe to multiple
* sequences in parallel that will each be emitting.
* <p>
* The calls from each sequence must be serialized.
* <p>
@@ -109,18 +117,23 @@ public final class OperationMerge {
SynchronizedObserver<T> synchronizedObserver = new SynchronizedObserver<>(actualObserver, subscription);
/**
* Subscribe to the parent Observable to get to the children Observables
* Subscribe to the parent Observable to get to the children
* Observables
*/
sequences.subscribe(new ParentObserver(synchronizedObserver));
/* return our subscription to allow unsubscribing */
/*
* return our subscription to allow unsubscribing
*/
return subscription;
}
/**
* Manage the internal subscription with a thread-safe means of stopping/unsubscribing so we don't unsubscribe twice.
* Manage the internal subscription with a thread-safe means of
* stopping/unsubscribing so we don't unsubscribe twice.
* <p>
* Also has the stop() method returning a boolean so callers know if their thread "won" and should perform further actions.
* Also has the stop() method returning a boolean so callers know if
* their thread "won" and should perform further actions.
*/
private class MergeSubscription implements Subscription {
@@ -134,23 +147,23 @@ public final class OperationMerge {
boolean didSet = stopped.compareAndSet(false, true);
if (didSet) {
// this thread won the race to stop, so unsubscribe from the actualSubscription
for (Subscription _s : childSubscriptions.values()) {
for (Subscription _s : childSubscriptions.values())
_s.unsubscribe();
}
return true;
} else {
} else
// another thread beat us
return false;
}
}
}
/**
* Subscribe to the top level Observable to receive the sequence of Observable<T> children.
*
* Subscribe to the top level Observable to receive the sequence of
* Observable<T> children.
*
* @param <T>
*/
private class ParentObserver implements Observer<Observable<T>> {
private final Observer<T> actualObserver;
public ParentObserver(Observer<T> actualObserver) {
@@ -164,13 +177,10 @@ public final class OperationMerge {
// but will let the child worry about it
// if however this completes and there are no children processing, then we will send onCompleted
if (childObservers.isEmpty()) {
if (!stopped.get()) {
if (ourSubscription.stop()) {
if (childObservers.isEmpty())
if (!stopped.get())
if (ourSubscription.stop())
actualObserver.onCompleted();
}
}
}
}
@Override
@@ -180,20 +190,21 @@ public final class OperationMerge {
@Override
public void onNext(Observable<T> childObservable) {
if (stopped.get()) {
if (stopped.get())
// we won't act on any further items
return;
}
if (childObservable == null) {
if (childObservable == null)
throw new IllegalArgumentException("Observable<T> can not be null.");
}
/**
* For each child Observable we receive we'll subscribe with a separate Observer
* that will each then forward their sequences to the actualObserver.
* For each child Observable we receive we'll subscribe with a
* separate Observer that will each then forward their sequences
* to the actualObserver.
* <p>
* We use separate child Observers for each sequence to simplify the onComplete/onError handling so each sequence has its own lifecycle.
* We use separate child Observers for each sequence to simplify
* the onComplete/onError handling so each sequence has its own
* lifecycle.
*/
ChildObserver _w = new ChildObserver(actualObserver);
childObservers.put(_w, _w);
@@ -204,8 +215,9 @@ public final class OperationMerge {
}
/**
* Subscribe to each child Observable<T> and forward their sequence of data to the actualObserver
*
* Subscribe to each child Observable<T> and forward their sequence of
* data to the actualObserver
*
*/
private class ChildObserver implements Observer<T> {
@@ -221,33 +233,27 @@ public final class OperationMerge {
childObservers.remove(this);
// if there are now 0 Observers left, so if the parent is also completed we send the onComplete to the actualObserver
// if the parent is not complete that means there is another sequence (and child Observer) to come
if (!stopped.get()) {
if (childObservers.isEmpty() && parentCompleted) {
if (ourSubscription.stop()) {
if (!stopped.get())
if (childObservers.isEmpty() && parentCompleted)
if (ourSubscription.stop())
// this thread 'won' the race to unsubscribe/stop so let's send onCompleted
actualObserver.onCompleted();
}
}
}
}
@Override
public void onError(Exception e) {
if (!stopped.get()) {
if (ourSubscription.stop()) {
if (!stopped.get())
if (ourSubscription.stop())
// this thread 'won' the race to unsubscribe/stop so let's send the error
actualObserver.onError(e);
}
}
}
@Override
public void onNext(T args) {
// in case the Observable is poorly behaved and doesn't listen to the unsubscribe request
// we'll ignore anything that comes in after we've unsubscribed
if (!stopped.get()) {
if (!stopped.get())
actualObserver.onNext(args);
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -27,23 +27,30 @@ import rx.util.CompositeException;
import rx.util.functions.Func1;
/**
* Same functionality as OperationMerge except that onError events will be skipped so that all onNext calls are passed on until all sequences finish with onComplete or onError, and then the first
* onError received (if any) will be passed on.
* Same functionality as OperationMerge except that onError events will be
* skipped so that all onNext calls are passed on until all sequences finish
* with onComplete or onError, and then the first onError received (if any) will
* be passed on.
* <p>
* This allows retrieving all successful onNext calls without being blocked by an onError early in a sequence.
* This allows retrieving all successful onNext calls without being blocked by
* an onError early in a sequence.
* <p>
* NOTE: If this is used on an infinite stream it will never call onError and effectively will swallow errors.
* NOTE: If this is used on an infinite stream it will never call onError and
* effectively will swallow errors.
*/
public final class OperationMergeDelayError {
/**
* Flattens the observable sequences from the list of Observables into one observable sequence without any transformation and delays any onError calls until after all sequences have called
* onError or onComplete so as to allow all successful
* onNext calls to be received.
*
* @param source
* An observable sequence of elements to project.
* @return An observable sequence whose elements are the result of flattening the output from the list of Observables.
* Flattens the observable sequences from the list of Observables into one
* observable sequence without any transformation and delays any onError
* calls until after all sequences have called onError or onComplete so as
* to allow all successful onNext calls to be received.
*
* @param source An observable sequence of elements to project.
*
* @return An observable sequence whose elements are the result of
* flattening the output from the list of Observables.
*
* @see http://msdn.microsoft.com/en-us/library/hh229099(v=vs.103).aspx
*/
public static <T> Func1<Observer<T>, Subscription> mergeDelayError(final Observable<Observable<T>> sequences) {
@@ -63,17 +70,14 @@ public final class OperationMergeDelayError {
@Override
public Subscription call(Observer<Observable<T>> observer) {
for (Observable<T> o : sequences) {
if (!unsubscribed) {
for (Observable<T> o : sequences)
if (!unsubscribed)
observer.onNext(o);
} else {
else
// break out of the loop if we are unsubscribed
break;
}
}
if (!unsubscribed) {
if (!unsubscribed)
observer.onCompleted();
}
return new Subscription() {
@Override
@@ -93,17 +97,14 @@ public final class OperationMergeDelayError {
@Override
public Subscription call(Observer<Observable<T>> observer) {
for (Observable<T> o : sequences) {
if (!unsubscribed) {
for (Observable<T> o : sequences)
if (!unsubscribed)
observer.onNext(o);
} else {
else
// break out of the loop if we are unsubscribed
break;
}
}
if (!unsubscribed) {
if (!unsubscribed)
observer.onCompleted();
}
return new Subscription() {
@@ -118,17 +119,24 @@ public final class OperationMergeDelayError {
}
/**
* This class is NOT thread-safe if invoked and referenced multiple times. In other words, don't subscribe to it multiple times from different threads.
* This class is NOT thread-safe if invoked and referenced multiple times.
* In other words, don't subscribe to it multiple times from different
* threads.
* <p>
* It IS thread-safe from within it while receiving onNext events from multiple threads.
* It IS thread-safe from within it while receiving onNext events from
* multiple threads.
* <p>
* This should all be fine as long as it's kept as a private class and a new instance created from static factory method above.
* This should all be fine as long as it's kept as a private class and a new
* instance created from static factory method above.
* <p>
* Note how the take() factory method above protects us from a single instance being exposed with the Observable wrapper handling the subscribe flow.
*
* Note how the take() factory method above protects us from a single
* instance being exposed with the Observable wrapper handling the subscribe
* flow.
*
* @param <T>
*/
private static final class MergeDelayErrorObservable<T> implements Func1<Observer<T>, Subscription> {
private final Observable<Observable<T>> sequences;
private final MergeSubscription ourSubscription = new MergeSubscription();
private AtomicBoolean stopped = new AtomicBoolean(false);
@@ -144,18 +152,23 @@ public final class OperationMergeDelayError {
public Subscription call(Observer<T> actualObserver) {
/**
* Subscribe to the parent Observable to get to the children Observables
* Subscribe to the parent Observable to get to the children
* Observables
*/
sequences.subscribe(new ParentObserver(actualObserver));
/* return our subscription to allow unsubscribing */
/*
* return our subscription to allow unsubscribing
*/
return ourSubscription;
}
/**
* Manage the internal subscription with a thread-safe means of stopping/unsubscribing so we don't unsubscribe twice.
* Manage the internal subscription with a thread-safe means of
* stopping/unsubscribing so we don't unsubscribe twice.
* <p>
* Also has the stop() method returning a boolean so callers know if their thread "won" and should perform further actions.
* Also has the stop() method returning a boolean so callers know if
* their thread "won" and should perform further actions.
*/
private class MergeSubscription implements Subscription {
@@ -169,23 +182,23 @@ public final class OperationMergeDelayError {
boolean didSet = stopped.compareAndSet(false, true);
if (didSet) {
// this thread won the race to stop, so unsubscribe from the actualSubscription
for (Subscription _s : childSubscriptions.values()) {
for (Subscription _s : childSubscriptions.values())
_s.unsubscribe();
}
return true;
} else {
} else
// another thread beat us
return false;
}
}
}
/**
* Subscribe to the top level Observable to receive the sequence of Observable<T> children.
*
* Subscribe to the top level Observable to receive the sequence of
* Observable<T> children.
*
* @param <T>
*/
private class ParentObserver implements Observer<Observable<T>> {
private final Observer<T> actualObserver;
public ParentObserver(Observer<T> actualObserver) {
@@ -199,22 +212,18 @@ public final class OperationMergeDelayError {
// but will let the child worry about it
// if however this completes and there are no children processing, then we will send onCompleted
if (childObservers.size() == 0) {
if (!stopped.get()) {
if (ourSubscription.stop()) {
if (onErrorReceived.size() == 1) {
if (childObservers.size() == 0)
if (!stopped.get())
if (ourSubscription.stop())
if (onErrorReceived.size() == 1)
// an onError was received from 1 ChildObserver so we now send it as a delayed error
actualObserver.onError(onErrorReceived.peek());
} else if (onErrorReceived.size() > 1) {
else if (onErrorReceived.size() > 1)
// an onError was received from more than 1 ChildObserver so we now send it as a delayed error
actualObserver.onError(new CompositeException(onErrorReceived));
} else {
else
// no delayed error so send onCompleted
actualObserver.onCompleted();
}
}
}
}
}
@Override
@@ -224,20 +233,21 @@ public final class OperationMergeDelayError {
@Override
public void onNext(Observable<T> childObservable) {
if (stopped.get()) {
if (stopped.get())
// we won't act on any further items
return;
}
if (childObservable == null) {
if (childObservable == null)
throw new IllegalArgumentException("Observable<T> can not be null.");
}
/**
* For each child Observable we receive we'll subscribe with a separate Observer
* that will each then forward their sequences to the actualObserver.
* For each child Observable we receive we'll subscribe with a
* separate Observer that will each then forward their sequences
* to the actualObserver.
* <p>
* We use separate child Observers for each sequence to simplify the onComplete/onError handling so each sequence has its own lifecycle.
* We use separate child Observers for each sequence to simplify
* the onComplete/onError handling so each sequence has its own
* lifecycle.
*/
ChildObserver _w = new ChildObserver(actualObserver);
childObservers.put(_w, _w);
@@ -248,8 +258,9 @@ public final class OperationMergeDelayError {
}
/**
* Subscribe to each child Observable<T> and forward their sequence of data to the actualObserver
*
* Subscribe to each child Observable<T> and forward their sequence of
* data to the actualObserver
*
*/
private class ChildObserver implements Observer<T> {
@@ -266,9 +277,8 @@ public final class OperationMergeDelayError {
childObservers.remove(this);
// if there are now 0 Observers left, so if the parent is also completed we send the onComplete to the actualObserver
// if the parent is not complete that means there is another sequence (and child Observer) to come
if (!stopped.get()) {
if (!stopped.get())
finishObserver();
}
}
@Override
@@ -289,37 +299,37 @@ public final class OperationMergeDelayError {
}
/**
* onComplete and onError when called need to check for the parent being complete and if so send the onCompleted or onError to the actualObserver.
* onComplete and onError when called need to check for the parent
* being complete and if so send the onCompleted or onError to the
* actualObserver.
* <p>
* This does NOT get invoked if synchronous execution occurs, but will when asynchronously executing.
* This does NOT get invoked if synchronous execution occurs, but
* will when asynchronously executing.
* <p>
* TestCase testErrorDelayed4WithThreading specifically tests this use case.
* TestCase testErrorDelayed4WithThreading specifically tests this
* use case.
*/
private void finishObserver() {
if (childObservers.size() == 0 && parentCompleted) {
if (ourSubscription.stop()) {
if (childObservers.size() == 0 && parentCompleted)
if (ourSubscription.stop())
// this thread 'won' the race to unsubscribe/stop so let's send onError or onCompleted
if (onErrorReceived.size() == 1) {
if (onErrorReceived.size() == 1)
// an onError was received from 1 ChildObserver so we now send it as a delayed error
actualObserver.onError(onErrorReceived.peek());
} else if (onErrorReceived.size() > 1) {
else if (onErrorReceived.size() > 1)
// an onError was received from more than 1 ChildObserver so we now send it as a delayed error
actualObserver.onError(new CompositeException(onErrorReceived));
} else {
else
// no delayed error so send onCompleted
actualObserver.onCompleted();
}
}
}
}
@Override
public void onNext(T args) {
// in case the Observable is poorly behaved and doesn't listen to the unsubscribe request
// we'll ignore anything that comes in after we've unsubscribed or an onError has been received and delayed
if (!stopped.get() && !finished) {
if (!stopped.get() && !finished)
actualObserver.onNext(args);
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -54,9 +54,8 @@ public final class OperationMostRecent {
@Override
public T next() {
if (observer.getException() != null) {
if (observer.getException() != null)
throw Exceptions.propagate(observer.getException());
}
return observer.getRecentValue();
}
@@ -67,6 +66,7 @@ public final class OperationMostRecent {
}
private static class MostRecentObserver<T> implements Observer<T> {
private final AtomicBoolean completed = new AtomicBoolean(false);
private final AtomicReference<T> value;
private final AtomicReference<Exception> exception = new AtomicReference<>();

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -26,7 +26,8 @@ import rx.Observer;
import rx.util.Exceptions;
/**
* Samples the next value (blocking without buffering) from in an observable sequence.
* Samples the next value (blocking without buffering) from in an observable
* sequence.
*/
public final class OperationNext {
@@ -56,9 +57,8 @@ public final class OperationNext {
@Override
public T next() {
if (observer.isCompleted(true)) {
if (observer.isCompleted(true))
throw new IllegalStateException("Observable is completed");
}
observer.await();
@@ -78,6 +78,7 @@ public final class OperationNext {
}
private static class NextObserver<T> implements Observer<Notification<T>> {
private final BlockingQueue<Notification<T>> buf = new ArrayBlockingQueue<>(1);
private final AtomicBoolean waiting = new AtomicBoolean(false);
@@ -100,9 +101,8 @@ public final class OperationNext {
Notification<T> concurrentItem = buf.poll();
// in case if we won race condition with onComplete/onError method
if (!concurrentItem.isOnNext()) {
if (!concurrentItem.isOnNext())
toOffer = concurrentItem;
}
}
}
@@ -114,17 +114,14 @@ public final class OperationNext {
public boolean isCompleted(boolean rethrowExceptionIfExists) {
Notification<T> lastItem = buf.peek();
if (lastItem == null) {
if (lastItem == null)
return false;
}
if (lastItem.isOnError()) {
if (rethrowExceptionIfExists) {
if (lastItem.isOnError())
if (rethrowExceptionIfExists)
throw Exceptions.propagate(lastItem.getException());
} else {
else
return true;
}
}
return lastItem.isOnCompleted();
}
@@ -132,13 +129,11 @@ public final class OperationNext {
public T takeNext() throws InterruptedException {
Notification<T> next = buf.take();
if (next.isOnError()) {
if (next.isOnError())
throw Exceptions.propagate(next.getException());
}
if (next.isOnCompleted()) {
if (next.isOnCompleted())
throw new IllegalStateException("Observable is completed");
}
return next.getValue();

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -28,6 +28,7 @@ public class OperationObserveOn {
}
private static class ObserveOn<T> implements Func1<Observer<T>, Subscription> {
private final Observable<T> source;
private final Scheduler scheduler;

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -55,30 +55,39 @@ public final class OperationOnErrorResumeNextViaFunction<T> {
}
/**
* Instead of passing the onError forward, we intercept and "resume" with the resumeSequence.
* Instead of passing the onError forward, we intercept and
* "resume" with the resumeSequence.
*/
@Override
public void onError(Exception ex) {
/* remember what the current subscription is so we can determine if someone unsubscribes concurrently */
/*
* remember what the current subscription is so we can
* determine if someone unsubscribes concurrently
*/
AtomicObservableSubscription currentSubscription = subscriptionRef.get();
// check that we have not been unsubscribed before we can process the error
if (currentSubscription != null) {
if (currentSubscription != null)
try {
Observable<T> resumeSequence = resumeFunction.call(ex);
/* error occurred, so switch subscription to the 'resumeSequence' */
/*
* error occurred, so switch subscription to the
* 'resumeSequence'
*/
AtomicObservableSubscription innerSubscription = new AtomicObservableSubscription(resumeSequence.subscribe(observer));
/* we changed the sequence, so also change the subscription to the one of the 'resumeSequence' instead */
if (!subscriptionRef.compareAndSet(currentSubscription, innerSubscription)) {
/*
* we changed the sequence, so also change the
* subscription to the one of the 'resumeSequence'
* instead
*/
if (!subscriptionRef.compareAndSet(currentSubscription, innerSubscription))
// we failed to set which means 'subscriptionRef' was set to NULL via the unsubscribe below
// so we want to immediately unsubscribe from the resumeSequence we just subscribed to
innerSubscription.unsubscribe();
}
} catch (Exception e) {
// the resume function failed so we need to call onError
// I am using CompositeException so that both exceptions can be seen
observer.onError(new CompositeException("OnErrorResume function failed", Arrays.asList(ex, e)));
}
}
}
@Override
@@ -96,4 +105,4 @@ public final class OperationOnErrorResumeNextViaFunction<T> {
};
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -54,22 +54,32 @@ public final class OperationOnErrorResumeNextViaObservable<T> {
}
/**
* Instead of passing the onError forward, we intercept and "resume" with the resumeSequence.
* Instead of passing the onError forward, we intercept and
* "resume" with the resumeSequence.
*/
@Override
public void onError(Exception ex) {
/* remember what the current subscription is so we can determine if someone unsubscribes concurrently */
/*
* remember what the current subscription is so we can
* determine if someone unsubscribes concurrently
*/
AtomicObservableSubscription currentSubscription = subscriptionRef.get();
// check that we have not been unsubscribed before we can process the error
if (currentSubscription != null) {
/* error occurred, so switch subscription to the 'resumeSequence' */
/*
* error occurred, so switch subscription to the
* 'resumeSequence'
*/
AtomicObservableSubscription innerSubscription = new AtomicObservableSubscription(resumeSequence.subscribe(observer));
/* we changed the sequence, so also change the subscription to the one of the 'resumeSequence' instead */
if (!subscriptionRef.compareAndSet(currentSubscription, innerSubscription)) {
/*
* we changed the sequence, so also change the
* subscription to the one of the 'resumeSequence'
* instead
*/
if (!subscriptionRef.compareAndSet(currentSubscription, innerSubscription))
// we failed to set which means 'subscriptionRef' was set to NULL via the unsubscribe below
// so we want to immediately unsubscribe from the resumeSequence we just subscribed to
innerSubscription.unsubscribe();
}
}
}
@@ -88,4 +98,4 @@ public final class OperationOnErrorResumeNextViaObservable<T> {
};
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -26,7 +26,8 @@ import rx.util.CompositeException;
import rx.util.functions.Func1;
/**
* When an onError occurs the resumeFunction will be executed and it's response passed to onNext instead of calling onError.
* When an onError occurs the resumeFunction will be executed and it's response
* passed to onNext instead of calling onError.
*/
public final class OperationOnErrorReturn<T> {
@@ -35,6 +36,7 @@ public final class OperationOnErrorReturn<T> {
}
private static class OnErrorReturn<T> implements Func1<Observer<T>, Subscription> {
private final Func1<Exception, T> resumeFunction;
private final Observable<T> originalSequence;
@@ -59,35 +61,50 @@ public final class OperationOnErrorReturn<T> {
}
/**
* Instead of passing the onError forward, we intercept and "resume" with the resumeSequence.
* Instead of passing the onError forward, we intercept and
* "resume" with the resumeSequence.
*/
@Override
public void onError(Exception ex) {
/* remember what the current subscription is so we can determine if someone unsubscribes concurrently */
/*
* remember what the current subscription is so we can
* determine if someone unsubscribes concurrently
*/
AtomicObservableSubscription currentSubscription = subscriptionRef.get();
// check that we have not been unsubscribed before we can process the error
if (currentSubscription != null) {
if (currentSubscription != null)
try {
/* error occurred, so execute the function, give it the exception and call onNext with the response */
/*
* error occurred, so execute the function, give it
* the exception and call onNext with the response
*/
onNext(resumeFunction.call(ex));
/*
* we are not handling an exception thrown from this function ... should we do something?
* error handling within an error handler is a weird one to determine what we should do
* right now I'm going to just let it throw whatever exceptions occur (such as NPE)
* but I'm considering calling the original Observer.onError to act as if this OnErrorReturn operator didn't happen
* we are not handling an exception thrown from this
* function ... should we do something?
* error handling within an error handler is a weird
* one to determine what we should do
* right now I'm going to just let it throw whatever
* exceptions occur (such as NPE)
* but I'm considering calling the original
* Observer.onError to act as if this OnErrorReturn
* operator didn't happen
*/
/* we are now completed */
/*
* we are now completed
*/
onCompleted();
/* unsubscribe since it blew up */
/*
* unsubscribe since it blew up
*/
currentSubscription.unsubscribe();
} catch (Exception e) {
// the return function failed so we need to call onError
// I am using CompositeException so that both exceptions can be seen
observer.onError(new CompositeException("OnErrorReturn function failed", Arrays.asList(ex, e)));
}
}
}
@Override
@@ -105,4 +122,4 @@ public final class OperationOnErrorReturn<T> {
};
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -23,17 +23,19 @@ import rx.util.functions.Func1;
import rx.util.functions.Func2;
public final class OperationScan {
/**
* Applies an accumulator function over an observable sequence and returns each intermediate result with the specified source and accumulator.
*
* @param sequence
* An observable sequence of elements to project.
* @param initialValue
* The initial (seed) accumulator value.
* @param accumulator
* An accumulator function to be invoked on each element from the sequence.
*
* @return An observable sequence whose elements are the result of accumulating the output from the list of Observables.
* Applies an accumulator function over an observable sequence and returns
* each intermediate result with the specified source and accumulator.
*
* @param sequence An observable sequence of elements to project.
* @param initialValue The initial (seed) accumulator value.
* @param accumulator An accumulator function to be invoked on each element
* from the sequence.
*
* @return An observable sequence whose elements are the result of
* accumulating the output from the list of Observables.
*
* @see http://msdn.microsoft.com/en-us/library/hh211665(v=vs.103).aspx
*/
public static <T> Func1<Observer<T>, Subscription> scan(Observable<T> sequence, T initialValue, Func2<T, T, T> accumulator) {
@@ -41,14 +43,16 @@ public final class OperationScan {
}
/**
* Applies an accumulator function over an observable sequence and returns each intermediate result with the specified source and accumulator.
*
* @param sequence
* An observable sequence of elements to project.
* @param accumulator
* An accumulator function to be invoked on each element from the sequence.
*
* @return An observable sequence whose elements are the result of accumulating the output from the list of Observables.
* Applies an accumulator function over an observable sequence and returns
* each intermediate result with the specified source and accumulator.
*
* @param sequence An observable sequence of elements to project.
* @param accumulator An accumulator function to be invoked on each element
* from the sequence.
*
* @return An observable sequence whose elements are the result of
* accumulating the output from the list of Observables.
*
* @see http://msdn.microsoft.com/en-us/library/hh211665(v=vs.103).aspx
*/
public static <T> Func1<Observer<T>, Subscription> scan(Observable<T> sequence, Func2<T, T, T> accumulator) {
@@ -56,6 +60,7 @@ public final class OperationScan {
}
private static class Accumulator<T> implements Func1<Observer<T>, Subscription> {
private final Observable<T> sequence;
private final T initialValue;
private final Func2<T, T, T> accumlatorFunction;
@@ -75,11 +80,13 @@ public final class OperationScan {
private boolean hasSentInitialValue = false;
/**
* We must synchronize this because we can't allow
* multiple threads to execute the 'accumulatorFunction' at the same time because
* the accumulator code very often will be doing mutation of the 'acc' object such as a non-threadsafe HashMap
*
* Because it's synchronized it's using non-atomic variables since everything in this method is single-threaded
* We must synchronize this because we can't allow multiple
* threads to execute the 'accumulatorFunction' at the same time
* because the accumulator code very often will be doing
* mutation of the 'acc' object such as a non-threadsafe HashMap
*
* Because it's synchronized it's using non-atomic variables
* since everything in this method is single-threaded
*/
@Override
public synchronized void onNext(T value) {
@@ -119,9 +126,8 @@ public final class OperationScan {
@Override
public synchronized void onCompleted() {
// if only one sequence value existed, we send it without any accumulation
if (!hasSentInitialValue) {
if (!hasSentInitialValue)
observer.onNext(acc);
}
observer.onCompleted();
}
}));

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -23,17 +23,20 @@ import rx.Subscription;
import rx.util.functions.Func1;
/**
* Skips a specified number of contiguous values from the start of a Observable sequence and then returns the remaining values.
* Skips a specified number of contiguous values from the start of a Observable
* sequence and then returns the remaining values.
*/
public final class OperationSkip {
/**
* Skips a specified number of contiguous values from the start of a Observable sequence and then returns the remaining values.
*
* Skips a specified number of contiguous values from the start of a
* Observable sequence and then returns the remaining values.
*
* @param items
* @param num
*
* @return
*
*
* @see http://msdn.microsoft.com/en-us/library/hh229847(v=vs.103).aspx
*/
public static <T> Func1<Observer<T>, Subscription> skip(final Observable<T> items, final int num) {
@@ -42,13 +45,17 @@ public final class OperationSkip {
}
/**
* This class is NOT thread-safe if invoked and referenced multiple times. In other words, don't subscribe to it multiple times from different threads.
* This class is NOT thread-safe if invoked and referenced multiple times.
* In other words, don't subscribe to it multiple times from different
* threads.
* <p>
* It IS thread-safe from within it while receiving onNext events from multiple threads.
*
* It IS thread-safe from within it while receiving onNext events from
* multiple threads.
*
* @param <T>
*/
private static class Skip<T> implements Func1<Observer<T>, Subscription> {
private final int num;
private final Observable<T> items;
@@ -63,7 +70,8 @@ public final class OperationSkip {
}
/**
* Used to subscribe to the 'items' Observable sequence and forward to the actualObserver up to 'num' count.
* Used to subscribe to the 'items' Observable sequence and forward to
* the actualObserver up to 'num' count.
*/
private class ItemObserver implements Observer<T> {
@@ -87,12 +95,11 @@ public final class OperationSkip {
@Override
public void onNext(T args) {
// skip them until we reach the 'num' value
if (counter.incrementAndGet() > num) {
if (counter.incrementAndGet() > num)
observer.onNext(args);
}
}
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -23,29 +23,32 @@ import rx.util.SynchronizedObserver;
import rx.util.functions.Func1;
/**
* An observable that wraps an observable of the same type and then enforces the semantics
* expected of a well-behaved observable.
* An observable that wraps an observable of the same type and then enforces the
* semantics expected of a well-behaved observable.
* <p>
* An observable that ensures onNext, onCompleted, or onError calls on its subscribers are
* not interleaved, onCompleted and onError are only called once respectively, and no
* onNext calls follow onCompleted and onError calls.
* An observable that ensures onNext, onCompleted, or onError calls on its
* subscribers are not interleaved, onCompleted and onError are only called once
* respectively, and no onNext calls follow onCompleted and onError calls.
* <p>
* NOTE: {@link Observable#create} already wraps Observables so this is generally redundant.
*
* @param <T>
* The type of the observable sequence.
* NOTE: {@link Observable#create} already wraps Observables so this is
* generally redundant.
*
* @param <T> The type of the observable sequence.
*/
public final class OperationSynchronize<T> {
/**
* Accepts an observable and wraps it in another observable which ensures that the resulting observable is well-behaved.
*
* A well-behaved observable ensures onNext, onCompleted, or onError calls to its subscribers are
* not interleaved, onCompleted and onError are only called once respectively, and no
* onNext calls follow onCompleted and onError calls.
*
* Accepts an observable and wraps it in another observable which ensures
* that the resulting observable is well-behaved.
*
* A well-behaved observable ensures onNext, onCompleted, or onError calls
* to its subscribers are not interleaved, onCompleted and onError are only
* called once respectively, and no onNext calls follow onCompleted and
* onError calls.
*
* @param observable
* @param <T>
*
* @return
*/
public static <T> Func1<Observer<T>, Subscription> synchronize(Observable<T> observable) {
@@ -69,4 +72,4 @@ public final class OperationSynchronize<T> {
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -25,15 +25,18 @@ import rx.util.AtomicObservableSubscription;
import rx.util.functions.Func1;
/**
* Returns a specified number of contiguous values from the start of an observable sequence.
* Returns a specified number of contiguous values from the start of an
* observable sequence.
*/
public final class OperationTake {
/**
* Returns a specified number of contiguous values from the start of an observable sequence.
*
* Returns a specified number of contiguous values from the start of an
* observable sequence.
*
* @param items
* @param num
*
* @return
*/
public static <T> Func1<Observer<T>, Subscription> take(final Observable<T> items, final int num) {
@@ -42,17 +45,24 @@ public final class OperationTake {
}
/**
* This class is NOT thread-safe if invoked and referenced multiple times. In other words, don't subscribe to it multiple times from different threads.
* This class is NOT thread-safe if invoked and referenced multiple times.
* In other words, don't subscribe to it multiple times from different
* threads.
* <p>
* It IS thread-safe from within it while receiving onNext events from multiple threads.
* It IS thread-safe from within it while receiving onNext events from
* multiple threads.
* <p>
* This should all be fine as long as it's kept as a private class and a new instance created from static factory method above.
* This should all be fine as long as it's kept as a private class and a new
* instance created from static factory method above.
* <p>
* Note how the take() factory method above protects us from a single instance being exposed with the Observable wrapper handling the subscribe flow.
*
* Note how the take() factory method above protects us from a single
* instance being exposed with the Observable wrapper handling the subscribe
* flow.
*
* @param <T>
*/
private static class Take<T> implements Func1<Observer<T>, Subscription> {
private final AtomicInteger counter = new AtomicInteger();
private final Observable<T> items;
private final int num;
@@ -66,21 +76,17 @@ public final class OperationTake {
@Override
public Subscription call(Observer<T> observer) {
if (num < 1) {
items.subscribe(new Observer<T>()
{
items.subscribe(new Observer<T>() {
@Override
public void onCompleted()
{
public void onCompleted() {
}
@Override
public void onError(Exception e)
{
public void onError(Exception e) {
}
@Override
public void onNext(T args)
{
public void onNext(T args) {
}
}).unsubscribe();
observer.onCompleted();
@@ -91,6 +97,7 @@ public final class OperationTake {
}
private class ItemObserver implements Observer<T> {
private final Observer<T> observer;
public ItemObserver(Observer<T> observer) {
@@ -99,16 +106,14 @@ public final class OperationTake {
@Override
public void onCompleted() {
if (counter.getAndSet(num) < num) {
if (counter.getAndSet(num) < num)
observer.onCompleted();
}
}
@Override
public void onError(Exception e) {
if (counter.getAndSet(num) < num) {
if (counter.getAndSet(num) < num)
observer.onError(e);
}
}
@Override
@@ -116,14 +121,12 @@ public final class OperationTake {
final int count = counter.incrementAndGet();
if (count <= num) {
observer.onNext(args);
if (count == num) {
if (count == num)
observer.onCompleted();
}
}
if (count >= num) {
if (count >= num)
// this will work if the sequence is asynchronous, it will have no effect on a synchronous observable
subscription.unsubscribe();
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -25,7 +25,8 @@ import rx.util.AtomicObservableSubscription;
import rx.util.functions.Func1;
/**
* Returns a specified number of contiguous elements from the end of an observable sequence.
* Returns a specified number of contiguous elements from the end of an
* observable sequence.
*/
public final class OperationTakeLast {
@@ -34,6 +35,7 @@ public final class OperationTakeLast {
}
private static class TakeLast<T> implements Func1<Observer<T>, Subscription> {
private final int count;
private final Observable<T> items;
private final AtomicObservableSubscription subscription = new AtomicObservableSubscription();
@@ -60,9 +62,8 @@ public final class OperationTakeLast {
@Override
public void onCompleted() {
Iterator<T> reverse = deque.descendingIterator();
while (reverse.hasNext()) {
while (reverse.hasNext())
observer.onNext(reverse.next());
}
observer.onCompleted();
}
@@ -73,9 +74,8 @@ public final class OperationTakeLast {
@Override
public void onNext(T args) {
while (!deque.offerFirst(args)) {
while (!deque.offerFirst(args))
deque.removeLast();
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -26,28 +26,33 @@ import rx.util.functions.Func1;
import rx.util.functions.Func2;
/**
* Returns values from an observable sequence as long as a specified condition is true, and then skips the remaining values.
* Returns values from an observable sequence as long as a specified condition
* is true, and then skips the remaining values.
*/
public final class OperationTakeWhile {
/**
* Returns a specified number of contiguous values from the start of an observable sequence.
*
* Returns a specified number of contiguous values from the start of an
* observable sequence.
*
* @param items
* @param predicate
* a function to test each source element for a condition
* @param predicate a function to test each source element for a condition
*
* @return
*/
public static <T> Func1<Observer<T>, Subscription> takeWhile(final Observable<T> items, final Func1<T, Boolean> predicate) {
return takeWhileWithIndex(items, OperationTakeWhile.<T> skipIndex(predicate));
return takeWhileWithIndex(items, OperationTakeWhile.<T>skipIndex(predicate));
}
/**
* Returns values from an observable sequence as long as a specified condition is true, and then skips the remaining values.
*
* Returns values from an observable sequence as long as a specified
* condition is true, and then skips the remaining values.
*
* @param items
* @param predicate
* a function to test each element for a condition; the second parameter of the function represents the index of the source element; otherwise, false.
* @param predicate a function to test each element for a condition; the
* second parameter of the function represents the index of the source
* element; otherwise, false.
*
* @return
*/
public static <T> Func1<Observer<T>, Subscription> takeWhileWithIndex(final Observable<T> items, final Func2<T, Integer, Boolean> predicate) {
@@ -60,17 +65,24 @@ public final class OperationTakeWhile {
}
/**
* This class is NOT thread-safe if invoked and referenced multiple times. In other words, don't subscribe to it multiple times from different threads.
* This class is NOT thread-safe if invoked and referenced multiple times.
* In other words, don't subscribe to it multiple times from different
* threads.
* <p>
* It IS thread-safe from within it while receiving onNext events from multiple threads.
* It IS thread-safe from within it while receiving onNext events from
* multiple threads.
* <p>
* This should all be fine as long as it's kept as a private class and a new instance created from static factory method above.
* This should all be fine as long as it's kept as a private class and a new
* instance created from static factory method above.
* <p>
* Note how the takeWhileWithIndex() factory method above protects us from a single instance being exposed with the Observable wrapper handling the subscribe flow.
*
* Note how the takeWhileWithIndex() factory method above protects us from a
* single instance being exposed with the Observable wrapper handling the
* subscribe flow.
*
* @param <T>
*/
private static class TakeWhile<T> implements Func1<Observer<T>, Subscription> {
private final AtomicInteger counter = new AtomicInteger();
private final Observable<T> items;
private final Func2<T, Integer, Boolean> predicate;
@@ -87,6 +99,7 @@ public final class OperationTakeWhile {
}
private class ItemObserver implements Observer<T> {
private final Observer<T> observer;
public ItemObserver(Observer<T> observer) {
@@ -115,9 +128,9 @@ public final class OperationTakeWhile {
observer.onError(e);
return;
}
if (isSelected) {
if (isSelected)
observer.onNext(args);
} else {
else {
observer.onCompleted();
// this will work if the sequence is asynchronous, it will have no effect on a synchronous observable
subscription.unsubscribe();

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -24,7 +24,9 @@ import rx.subscriptions.Subscriptions;
import rx.util.functions.Func1;
public class OperationToObservableFuture {
private static class ToObservableFuture<T> implements Func1<Observer<T>, Subscription> {
private final Future<T> that;
private final Long time;
private final TimeUnit unit;
@@ -46,9 +48,8 @@ public class OperationToObservableFuture {
try {
T value = (time == null) ? that.get() : that.get(time, unit);
if (!that.isCancelled()) {
if (!that.isCancelled())
observer.onNext(value);
}
observer.onCompleted();
} catch (Exception e) {
observer.onError(e);

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -22,9 +22,8 @@ import rx.util.functions.Func1;
/**
* Accepts an Iterable object and exposes it as an Observable.
*
* @param <T>
* The type of the Iterable sequence.
*
* @param <T> The type of the Iterable sequence.
*/
public final class OperationToObservableIterable<T> {
@@ -37,4 +36,4 @@ public final class OperationToObservableIterable<T> {
return Subscriptions.empty();
};
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -38,11 +38,12 @@ public final class OperationToObservableList<T> {
this.that = that;
}
@Override
@Override
public Subscription call(final Observer<List<T>> observer) {
return that.subscribe(new Observer<T>() {
final ConcurrentLinkedQueue<T> list = new ConcurrentLinkedQueue<>();
@Override
public void onNext(T value) {
// onNext can be concurrently executed so list must be thread-safe
@@ -75,4 +76,4 @@ public final class OperationToObservableList<T> {
});
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -27,18 +27,19 @@ import rx.util.functions.Func1;
import rx.util.functions.Func2;
/**
* Similar to toList in that it converts a sequence<T> into a List<T> except that it accepts a Function that will provide an implementation of Comparator.
*
* Similar to toList in that it converts a sequence<T> into a List<T> except
* that it accepts a Function that will provide an implementation of Comparator.
*
* @param <T>
*/
public final class OperationToObservableSortedList<T> {
/**
* Sort T objects by their natural order (object must implement Comparable).
*
*
* @param sequence
* @throws ClassCastException
* if T objects do not implement Comparable
*
* @throws ClassCastException if T objects do not implement Comparable
* @return
*/
public static <T> Func1<Observer<List<T>>, Subscription> toSortedList(Observable<T> sequence) {
@@ -47,9 +48,10 @@ public final class OperationToObservableSortedList<T> {
/**
* Sort T objects using the defined sort function.
*
*
* @param sequence
* @param sortFunction
*
* @return
*/
public static <T> Func1<Observer<List<T>>, Subscription> toSortedList(Observable<T> sequence, Func2<T, T, Integer> sortFunction) {
@@ -92,9 +94,8 @@ public final class OperationToObservableSortedList<T> {
try {
// copy from LinkedQueue to List since ConcurrentLinkedQueue does not implement the List interface
ArrayList<T> l = new ArrayList<>(list.size());
for (T t : list) {
for (T t : list)
l.add(t);
}
// sort the list before delivery
Collections.sort(l, (T o1, T o2) -> sortFunction.call(o1, o2));
@@ -127,4 +128,4 @@ public final class OperationToObservableSortedList<T> {
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -61,6 +61,7 @@ public final class OperationZip {
* ThreadSafe
*/
private static class ZipObserver<R, T> implements Observer<T> {
final Observable<T> w;
final Aggregator<R> a;
private final AtomicObservableSubscription subscription = new AtomicObservableSubscription();
@@ -72,10 +73,9 @@ public final class OperationZip {
}
public void startWatching() {
if (subscribed.compareAndSet(false, true)) {
if (subscribed.compareAndSet(false, true))
// only subscribe once even if called more than once
subscription.wrap(w.subscribe(this));
}
}
@Override
@@ -99,10 +99,12 @@ public final class OperationZip {
}
/**
* Receive notifications from each of the Observables we are reducing and execute the zipFunction whenever we have received events from all Observables.
*
* Receive notifications from each of the Observables we are reducing and
* execute the zipFunction whenever we have received events from all
* Observables.
*
* This class is thread-safe.
*
*
* @param <T>
*/
private static class Aggregator<T> implements Func1<Observer<T>, Subscription> {
@@ -113,9 +115,17 @@ public final class OperationZip {
private final AtomicBoolean running = new AtomicBoolean(true);
private final ConcurrentHashMap<ZipObserver<T, ?>, Boolean> completed = new ConcurrentHashMap<>();
/* we use ConcurrentHashMap despite synchronization of methods because stop() does NOT use synchronization and this map is used by it and can be called by other threads */
/*
* we use ConcurrentHashMap despite synchronization of methods because
* stop() does NOT use synchronization and this map is used by it and
* can be called by other threads
*/
private final ConcurrentHashMap<ZipObserver<T, ?>, ConcurrentLinkedQueue<Object>> receivedValuesPerObserver = new ConcurrentHashMap<>();
/* we use a ConcurrentLinkedQueue to retain ordering (I'd like to just use a ConcurrentLinkedHashMap for 'receivedValuesPerObserver' but that doesn't exist in standard java */
/*
* we use a ConcurrentLinkedQueue to retain ordering (I'd like to just
* use a ConcurrentLinkedHashMap for 'receivedValuesPerObserver' but
* that doesn't exist in standard java
*/
private final ConcurrentLinkedQueue<ZipObserver<T, ?>> observers = new ConcurrentLinkedQueue<>();
public Aggregator(FuncN<T> zipFunction) {
@@ -123,10 +133,13 @@ public final class OperationZip {
}
/**
* Receive notification of a Observer starting (meaning we should require it for aggregation)
* Receive notification of a Observer starting (meaning we should
* require it for aggregation)
*
* Thread Safety => Invoke ONLY from the static factory methods at top
* of this class which are always an atomic execution by a single
* thread.
*
* Thread Safety => Invoke ONLY from the static factory methods at top of this class which are always an atomic execution by a single thread.
*
* @param w
*/
private void addObserver(ZipObserver<T, ?> w) {
@@ -137,32 +150,33 @@ public final class OperationZip {
/**
* Receive notification of a Observer completing its iterations.
*
*
* @param w
*/
void complete(ZipObserver<T, ?> w) {
// store that this ZipObserver is completed
completed.put(w, Boolean.TRUE);
// if all ZipObservers are completed, we mark the whole thing as completed
if (completed.size() == observers.size()) {
if (running.compareAndSet(true, false)) {
if (completed.size() == observers.size())
if (running.compareAndSet(true, false))
// this thread succeeded in setting running=false so let's propagate the completion
// mark ourselves as done
observer.onCompleted();
}
}
}
/**
* Receive error for a Observer. Throw the error up the chain and stop processing.
*
* Receive error for a Observer. Throw the error up the chain and stop
* processing.
*
* @param w
*/
void error(ZipObserver<T, ?> w, Exception e) {
if (running.compareAndSet(true, false)) {
// this thread succeeded in setting running=false so let's propagate the error
observer.onError(e);
/* since we receive an error we want to tell everyone to stop */
/*
* since we receive an error we want to tell everyone to stop
*/
stop();
}
}
@@ -170,20 +184,23 @@ public final class OperationZip {
/**
* Receive the next value from a Observer.
* <p>
* If we have received values from all Observers, trigger the zip function, otherwise store the value and keep waiting.
*
* If we have received values from all Observers, trigger the zip
* function, otherwise store the value and keep waiting.
*
* @param w
* @param arg
*/
void next(ZipObserver<T, ?> w, Object arg) {
if (observer == null) {
if (observer == null)
throw new RuntimeException("This shouldn't be running if a Observer isn't registered");
}
/* if we've been 'unsubscribed' don't process anything further even if the things we're watching keep sending (likely because they are not responding to the unsubscribe call) */
if (!running.get()) {
/*
* if we've been 'unsubscribed' don't process anything further even
* if the things we're watching keep sending (likely because they
* are not responding to the unsubscribe call)
*/
if (!running.get())
return;
}
// store the value we received and below we'll decide if we are to send it to the Observer
receivedValuesPerObserver.get(w).add(arg);
@@ -191,20 +208,21 @@ public final class OperationZip {
// define here so the variable is out of the synchronized scope
Object[] argsToZip = new Object[observers.size()];
/* we have to synchronize here despite using concurrent data structures because the compound logic here must all be done atomically */
/*
* we have to synchronize here despite using concurrent data
* structures because the compound logic here must all be done
* atomically
*/
synchronized (this) {
// if all ZipObservers in 'receivedValues' map have a value, invoke the zipFunction
for (ZipObserver<T, ?> rw : receivedValuesPerObserver.keySet()) {
if (receivedValuesPerObserver.get(rw).peek() == null) {
for (ZipObserver<T, ?> rw : receivedValuesPerObserver.keySet())
if (receivedValuesPerObserver.get(rw).peek() == null)
// we have a null meaning the queues aren't all populated so won't do anything
return;
}
}
// if we get to here this means all the queues have data
int i = 0;
for (ZipObserver<T, ?> rw : observers) {
for (ZipObserver<T, ?> rw : observers)
argsToZip[i++] = receivedValuesPerObserver.get(rw).remove();
}
}
// if we did not return above from the synchronized block we can now invoke the zipFunction with all of the args
// we do this outside the synchronized block as it is now safe to call this concurrently and don't need to block other threads from calling
@@ -217,41 +235,48 @@ public final class OperationZip {
if (started.compareAndSet(false, true)) {
AtomicObservableSubscription subscription = new AtomicObservableSubscription();
this.observer = new SynchronizedObserver<>(observer, subscription);
/* start the Observers */
for (ZipObserver<T, ?> rw : observers) {
/*
* start the Observers
*/
for (ZipObserver<T, ?> rw : observers)
rw.startWatching();
}
return subscription.wrap(this::stop);
} else {
/* a Observer already has subscribed so blow up */
} else
/*
* a Observer already has subscribed so blow up
*/
throw new IllegalStateException("Only one Observer can subscribe to this Observable.");
}
}
/*
* Do NOT synchronize this because it gets called via unsubscribe which can occur on other threads
* Do NOT synchronize this because it gets called via unsubscribe which
* can occur on other threads
* and result in deadlocks. (http://jira/browse/API-4060)
*
* AtomicObservableSubscription uses compareAndSet instead of locking to avoid deadlocks but ensure single-execution.
*
*
* AtomicObservableSubscription uses compareAndSet instead of locking to
* avoid deadlocks but ensure single-execution.
*
* We do the same in the implementation of this method.
*
*
* ThreadSafety of this method is provided by:
* - AtomicBoolean[running].compareAndSet
* - ConcurrentLinkedQueue[Observers]
* - ZipObserver.subscription being an AtomicObservableSubscription
*/
private void stop() {
/* tell ourselves to stop processing onNext events by setting running=false */
if (running.compareAndSet(true, false)) {
/* propogate to all Observers to unsubscribe if this thread succeeded in setting running=false */
for (ZipObserver<T, ?> o : observers) {
if (o.subscription != null) {
/*
* tell ourselves to stop processing onNext events by setting
* running=false
*/
if (running.compareAndSet(true, false))
/*
* propogate to all Observers to unsubscribe if this thread
* succeeded in setting running=false
*/
for (ZipObserver<T, ?> o : observers)
if (o.subscription != null)
o.subscription.unsubscribe();
}
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -42,10 +42,11 @@ public final class OperatorGroupBy {
}
public static <K, T> Func1<Observer<GroupedObservable<K, T>>, Subscription> groupBy(Observable<T> source, final Func1<T, K> keySelector) {
return groupBy(source, keySelector, Functions.<T> identity());
return groupBy(source, keySelector, Functions.<T>identity());
}
private static class GroupBy<K, V> implements Func1<Observer<GroupedObservable<K, V>>, Subscription> {
private final Observable<KeyValue<K, V>> source;
private final ConcurrentHashMap<K, Boolean> keys = new ConcurrentHashMap<K, Boolean>();
@@ -72,9 +73,8 @@ public final class OperatorGroupBy {
public void onNext(final KeyValue<K, V> args) {
K key = args.key;
boolean newGroup = keys.putIfAbsent(key, true) == null;
if (newGroup) {
if (newGroup)
observer.onNext(buildObservableFor(source, key));
}
}
});
@@ -95,15 +95,16 @@ public final class OperatorGroupBy {
});
return new GroupedObservable<K, R>(key, new Func1<Observer<R>, Subscription>() {
@Override
public Subscription call(Observer<R> observer) {
return observable.subscribe(observer);
}
@Override
public Subscription call(Observer<R> observer) {
return observable.subscribe(observer);
}
});
});
}
private static class KeyValue<K, V> {
private final K key;
private final V value;

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -23,17 +23,18 @@ import rx.util.functions.Func1;
public class OperatorTakeUntil {
/**
* Returns the values from the source observable sequence until the other observable sequence produces a value.
*
* @param source
* the source sequence to propagate elements for.
* @param other
* the observable sequence that terminates propagation of elements of the source sequence.
* @param <T>
* the type of source.
* @param <E>
* the other type.
* @return An observable sequence containing the elements of the source sequence up to the point the other sequence interrupted further propagation.
* Returns the values from the source observable sequence until the other
* observable sequence produces a value.
*
* @param source the source sequence to propagate elements for.
* @param other the observable sequence that terminates propagation of
* elements of the source sequence.
* @param <T> the type of source.
* @param <E> the other type.
*
* @return An observable sequence containing the elements of the source
* sequence up to the point the other sequence interrupted further
* propagation.
*/
public static <T, E> Observable<T> takeUntil(final Observable<T> source, final Observable<E> other) {
Observable<Notification<T>> s = Observable.create(new SourceObservable<T>(source));
@@ -41,9 +42,9 @@ public class OperatorTakeUntil {
@SuppressWarnings("unchecked")
/**
* In JDK 7 we could use 'varargs' instead of 'unchecked'.
* See http://stackoverflow.com/questions/1445233/is-it-possible-to-solve-the-a-generic-array-of-t-is-created-for-a-varargs-param
* and http://hg.openjdk.java.net/jdk7/tl/langtools/rev/46cf751559ae
* In JDK 7 we could use 'varargs' instead of 'unchecked'. See
* http://stackoverflow.com/questions/1445233/is-it-possible-to-solve-the-a-generic-array-of-t-is-created-for-a-varargs-param
* and http://hg.openjdk.java.net/jdk7/tl/langtools/rev/46cf751559ae
*/
Observable<Notification<T>> result = Observable.merge(s, o);
@@ -61,6 +62,7 @@ public class OperatorTakeUntil {
}
private static class Notification<T> {
private final boolean halt;
private final T value;
@@ -80,6 +82,7 @@ public class OperatorTakeUntil {
}
private static class SourceObservable<T> implements Func1<Observer<Notification<T>>, Subscription> {
private final Observable<T> sequence;
private SourceObservable(Observable<T> sequence) {
@@ -91,7 +94,7 @@ public class OperatorTakeUntil {
return sequence.subscribe(new Observer<T>() {
@Override
public void onCompleted() {
notificationObserver.onNext(Notification.<T> halt());
notificationObserver.onNext(Notification.<T>halt());
}
@Override
@@ -108,6 +111,7 @@ public class OperatorTakeUntil {
}
private static class OtherObservable<T, E> implements Func1<Observer<Notification<T>>, Subscription> {
private final Observable<E> sequence;
private OtherObservable(Observable<E> sequence) {
@@ -129,7 +133,7 @@ public class OperatorTakeUntil {
@Override
public void onNext(E args) {
notificationObserver.onNext(Notification.<T> halt());
notificationObserver.onNext(Notification.<T>halt());
}
});
}

View File

@@ -16,12 +16,12 @@ public class OperatorToIterator {
/**
* Returns an iterator that iterates all values of the observable.
*
* @param that
* an observable sequence to get an iterator for.
* @param <T>
* the type of source.
* @return the iterator that could be used to iterate over the elements of the observable.
*
* @param that an observable sequence to get an iterator for.
* @param <T> the type of source.
*
* @return the iterator that could be used to iterate over the elements of
* the observable.
*/
public static <T> Iterator<T> toIterator(Observable<T> that) {
final BlockingQueue<Notification<T>> notifications = new LinkedBlockingQueue<Notification<T>>();
@@ -48,20 +48,17 @@ public class OperatorToIterator {
@Override
public boolean hasNext() {
if (buf == null) {
if (buf == null)
buf = take();
}
return !buf.isOnCompleted();
}
@Override
public T next() {
if (buf == null) {
if (buf == null)
buf = take();
}
if (buf.isOnError()) {
if (buf.isOnError())
throw Exceptions.propagate(buf.getException());
}
T result = buf.getValue();
buf = null;

View File

@@ -19,7 +19,9 @@ import rx.Observer;
import rx.Scheduler;
import rx.util.functions.Action0;
/* package */
/*
* package
*/
class ScheduledObserver<T> implements Observer<T> {
private final Observer<T> underlying;

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -19,20 +19,24 @@ import rx.Observable;
import rx.Observer;
/**
* Abstract class for defining error handling logic in addition to the normal {@link Observer#onError(Exception)} behavior.
* Abstract class for defining error handling logic in addition to the normal
* {@link Observer#onError(Exception)} behavior.
* <p>
* For example, all Exceptions can be logged using this handler even if {@link Observer#onError(Exception)} is ignored or not provided when an {@link Observable} is subscribed to.
* For example, all Exceptions can be logged using this handler even if
* {@link Observer#onError(Exception)} is ignored or not provided when an
* {@link Observable} is subscribed to.
* <p>
* See {@link RxJavaPlugins} or the RxJava GitHub Wiki for information on configuring plugins: <a
* See {@link RxJavaPlugins} or the RxJava GitHub Wiki for information on
* configuring plugins: <a
* href="https://github.com/Netflix/RxJava/wiki/Plugins">https://github.com/Netflix/RxJava/wiki/Plugins</a>.
*/
public abstract class RxJavaErrorHandler {
/**
* Receives all Exceptions from an {@link Observable} passed to {@link Observer#onError(Exception)}.
*
* @param e
* Exception
* Receives all Exceptions from an {@link Observable} passed to
* {@link Observer#onError(Exception)}.
*
* @param e Exception
*/
public void handleError(Exception e) {
// do nothing by default

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -17,7 +17,7 @@ package rx.plugins;
/**
* Default implementation of {@link RxJavaErrorHandler} that does nothing.
*
*
* @ExcludeFromJavadoc
*/
public class RxJavaErrorHandlerDefault extends RxJavaErrorHandler {

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -21,31 +21,43 @@ import rx.Subscription;
import rx.util.functions.Func1;
/**
* Abstract ExecutionHook with invocations at different lifecycle points of {@link Observable} execution with a default no-op implementation.
* Abstract ExecutionHook with invocations at different lifecycle points of
* {@link Observable} execution with a default no-op implementation.
* <p>
* See {@link RxJavaPlugins} or the RxJava GitHub Wiki for information on configuring plugins: <a
* See {@link RxJavaPlugins} or the RxJava GitHub Wiki for information on
* configuring plugins: <a
* href="https://github.com/Netflix/RxJava/wiki/Plugins">https://github.com/Netflix/RxJava/wiki/Plugins</a>.
* <p>
* <b>Note on thread-safety and performance</b>
* <p>
* A single implementation of this class will be used globally so methods on this class will be invoked concurrently from multiple threads so all functionality must be thread-safe.
* A single implementation of this class will be used globally so methods on
* this class will be invoked concurrently from multiple threads so all
* functionality must be thread-safe.
* <p>
* Methods are also invoked synchronously and will add to execution time of the observable so all behavior should be fast. If anything time-consuming is to be done it should be spawned asynchronously
* onto separate worker threads.
*
* */
* Methods are also invoked synchronously and will add to execution time of the
* observable so all behavior should be fast. If anything time-consuming is to
* be done it should be spawned asynchronously onto separate worker threads.
*
*
*/
public abstract class RxJavaObservableExecutionHook {
/**
* Invoked before {@link Observable#subscribe(rx.Observer)} is about to be executed.
* Invoked before {@link Observable#subscribe(rx.Observer)} is about to be
* executed.
* <p>
* This can be used to decorate or replace the <code>onSubscribe</code> function or just perform extra logging, metrics and other such things and pass-thru the function.
*
* @param observableInstance
* The executing {@link Observable} instance.
* @param onSubscribe
* original {@link Func1}<{@link Observer}{@code<T>}, {@link Subscription}> to be executed
* @return {@link Func1}<{@link Observer}{@code<T>}, {@link Subscription}> function that can be modified, decorated, replaced or just returned as a pass-thru.
* This can be used to decorate or replace the <code>onSubscribe</code>
* function or just perform extra logging, metrics and other such things and
* pass-thru the function.
*
* @param observableInstance The executing {@link Observable} instance.
* @param onSubscribe original {@link Func1}<{@link
* Observer}{@code<T>},
* {@link Subscription}> to be executed
*
* @return {@link Func1}<{@link Observer}{@code<T>}, {@link Subscription}>
* function that can be modified, decorated, replaced or just returned as a
* pass-thru.
*/
public <T> Func1<Observer<T>, Subscription> onSubscribeStart(Observable<T> observableInstance, Func1<Observer<T>, Subscription> onSubscribe) {
// pass-thru by default
@@ -53,15 +65,19 @@ public abstract class RxJavaObservableExecutionHook {
}
/**
* Invoked after successful execution of {@link Observable#subscribe(rx.Observer)} with returned {@link Subscription}.
* Invoked after successful execution of
* {@link Observable#subscribe(rx.Observer)} with returned
* {@link Subscription}.
* <p>
* This can be used to decorate or replace the {@link Subscription} instance or just perform extra logging, metrics and other such things and pass-thru the subscription.
*
* @param observableInstance
* The executing {@link Observable} instance.
* @param subscription
* original {@link Subscription}
* @return {@link Subscription} subscription that can be modified, decorated, replaced or just returned as a pass-thru.
* This can be used to decorate or replace the {@link Subscription} instance
* or just perform extra logging, metrics and other such things and
* pass-thru the subscription.
*
* @param observableInstance The executing {@link Observable} instance.
* @param subscription original {@link Subscription}
*
* @return {@link Subscription} subscription that can be modified,
* decorated, replaced or just returned as a pass-thru.
*/
public <T> Subscription onSubscribeReturn(Observable<T> observableInstance, Subscription subscription) {
// pass-thru by default
@@ -69,16 +85,19 @@ public abstract class RxJavaObservableExecutionHook {
}
/**
* Invoked after failed execution of {@link Observable#subscribe(Observer)} with thrown Exception.
* Invoked after failed execution of {@link Observable#subscribe(Observer)}
* with thrown Exception.
* <p>
* This is NOT errors emitted via {@link Observer#onError(Exception)} but exceptions thrown when attempting
* to subscribe to a {@link Func1}<{@link Observer}{@code<T>}, {@link Subscription}>.
*
* @param observableInstance
* The executing {@link Observable} instance.
* @param e
* Exception thrown by {@link Observable#subscribe(Observer)}
* @return Exception that can be decorated, replaced or just returned as a pass-thru.
* This is NOT errors emitted via {@link Observer#onError(Exception)} but
* exceptions thrown when attempting to subscribe to a {@link Func1}<{@link
* Observer}{@code<T>}, {@link Subscription}>.
*
* @param observableInstance The executing {@link Observable} instance.
* @param e Exception thrown by
* {@link Observable#subscribe(Observer)}
*
* @return Exception that can be decorated, replaced or just returned as a
* pass-thru.
*/
public <T> Exception onSubscribeError(Observable<T> observableInstance, Exception e) {
// pass-thru by default

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -18,7 +18,10 @@ package rx.plugins;
/**
* Default no-op implementation of {@link RxJavaObservableExecutionHook}
*/
/* package */class RxJavaObservableExecutionHookDefault extends RxJavaObservableExecutionHook {
/*
* package
*/
class RxJavaObservableExecutionHookDefault extends RxJavaObservableExecutionHook {
private static RxJavaObservableExecutionHookDefault INSTANCE = new RxJavaObservableExecutionHookDefault();

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -18,15 +18,21 @@ package rx.plugins;
import java.util.concurrent.atomic.AtomicReference;
/**
* Registry for plugin implementations that allows global override and handles the retrieval of correct implementation based on order of precedence:
* Registry for plugin implementations that allows global override and handles
* the retrieval of correct implementation based on order of precedence:
* <ol>
* <li>plugin registered globally via <code>register</code> methods in this class</li>
* <li>plugin registered and retrieved using {@link java.lang.System#getProperty(String)} (see get methods for property names)</li>
* <li>plugin registered globally via <code>register</code> methods in this
* class</li>
* <li>plugin registered and retrieved using
* {@link java.lang.System#getProperty(String)} (see get methods for property
* names)</li>
* <li>default implementation</li>
* </ol>
* See the RxJava GitHub Wiki for more information: <a href="https://github.com/Netflix/RxJava/wiki/Plugins">https://github.com/Netflix/RxJava/wiki/Plugins</a>.
* See the RxJava GitHub Wiki for more information:
* <a href="https://github.com/Netflix/RxJava/wiki/Plugins">https://github.com/Netflix/RxJava/wiki/Plugins</a>.
*/
public class RxJavaPlugins {
private final static RxJavaPlugins INSTANCE = new RxJavaPlugins();
private final AtomicReference<RxJavaErrorHandler> errorHandler = new AtomicReference<RxJavaErrorHandler>();
@@ -41,79 +47,82 @@ public class RxJavaPlugins {
}
/**
* Retrieve instance of {@link RxJavaErrorHandler} to use based on order of precedence as defined in {@link RxJavaPlugins} class header.
* Retrieve instance of {@link RxJavaErrorHandler} to use based on order of
* precedence as defined in {@link RxJavaPlugins} class header.
* <p>
* Override default by using {@link #registerErrorHandler(RxJavaErrorHandler)} or setting property: <code>rxjava.plugin.RxJavaErrorHandler.implementation</code> with the full classname to
* load.
*
* Override default by using
* {@link #registerErrorHandler(RxJavaErrorHandler)} or setting property:
* <code>rxjava.plugin.RxJavaErrorHandler.implementation</code> with the
* full classname to load.
*
* @return {@link RxJavaErrorHandler} implementation to use
*/
public RxJavaErrorHandler getErrorHandler() {
if (errorHandler.get() == null) {
// check for an implementation from System.getProperty first
Object impl = getPluginImplementationViaProperty(RxJavaErrorHandler.class);
if (impl == null) {
// nothing set via properties so initialize with default
errorHandler.compareAndSet(null, RxJavaErrorHandlerDefault.getInstance());
// we don't return from here but call get() again in case of thread-race so the winner will always get returned
} else {
if (impl == null)
// nothing set via properties so initialize with default
errorHandler.compareAndSet(null, RxJavaErrorHandlerDefault.getInstance()); // we don't return from here but call get() again in case of thread-race so the winner will always get returned
else
// we received an implementation from the system property so use it
errorHandler.compareAndSet(null, (RxJavaErrorHandler) impl);
}
}
return errorHandler.get();
}
/**
* Register a {@link RxJavaErrorHandler} implementation as a global override of any injected or default implementations.
*
* @param impl
* {@link RxJavaErrorHandler} implementation
* @throws IllegalStateException
* if called more than once or after the default was initialized (if usage occurs before trying to register)
* Register a {@link RxJavaErrorHandler} implementation as a global override
* of any injected or default implementations.
*
* @param impl {@link RxJavaErrorHandler} implementation
*
* @throws IllegalStateException if called more than once or after the
* default was initialized (if usage occurs before trying to register)
*/
public void registerErrorHandler(RxJavaErrorHandler impl) {
if (!errorHandler.compareAndSet(null, impl)) {
if (!errorHandler.compareAndSet(null, impl))
throw new IllegalStateException("Another strategy was already registered.");
}
}
/**
* Retrieve instance of {@link RxJavaObservableExecutionHook} to use based on order of precedence as defined in {@link RxJavaPlugins} class header.
* Retrieve instance of {@link RxJavaObservableExecutionHook} to use based
* on order of precedence as defined in {@link RxJavaPlugins} class header.
* <p>
* Override default by using {@link #registerObservableExecutionHook(RxJavaObservableExecutionHook)} or setting property: <code>rxjava.plugin.RxJavaObservableExecutionHook.implementation</code>
* Override default by using
* {@link #registerObservableExecutionHook(RxJavaObservableExecutionHook)}
* or setting property:
* <code>rxjava.plugin.RxJavaObservableExecutionHook.implementation</code>
* with the full classname to load.
*
*
* @return {@link RxJavaObservableExecutionHook} implementation to use
*/
public RxJavaObservableExecutionHook getObservableExecutionHook() {
if (observableExecutionHook.get() == null) {
// check for an implementation from System.getProperty first
Object impl = getPluginImplementationViaProperty(RxJavaObservableExecutionHook.class);
if (impl == null) {
// nothing set via properties so initialize with default
observableExecutionHook.compareAndSet(null, RxJavaObservableExecutionHookDefault.getInstance());
// we don't return from here but call get() again in case of thread-race so the winner will always get returned
} else {
if (impl == null)
// nothing set via properties so initialize with default
observableExecutionHook.compareAndSet(null, RxJavaObservableExecutionHookDefault.getInstance()); // we don't return from here but call get() again in case of thread-race so the winner will always get returned
else
// we received an implementation from the system property so use it
observableExecutionHook.compareAndSet(null, (RxJavaObservableExecutionHook) impl);
}
}
return observableExecutionHook.get();
}
/**
* Register a {@link RxJavaObservableExecutionHook} implementation as a global override of any injected or default implementations.
*
* @param impl
* {@link RxJavaObservableExecutionHook} implementation
* @throws IllegalStateException
* if called more than once or after the default was initialized (if usage occurs before trying to register)
* Register a {@link RxJavaObservableExecutionHook} implementation as a
* global override of any injected or default implementations.
*
* @param impl {@link RxJavaObservableExecutionHook} implementation
*
* @throws IllegalStateException if called more than once or after the
* default was initialized (if usage occurs before trying to register)
*/
public void registerObservableExecutionHook(RxJavaObservableExecutionHook impl) {
if (!observableExecutionHook.compareAndSet(null, impl)) {
if (!observableExecutionHook.compareAndSet(null, impl))
throw new IllegalStateException("Another strategy was already registered.");
}
}
private static Object getPluginImplementationViaProperty(Class<?> pluginClass) {
@@ -121,11 +130,12 @@ public class RxJavaPlugins {
/*
* Check system properties for plugin class.
* <p>
* This will only happen during system startup thus it's okay to use the synchronized System.getProperties
* This will only happen during system startup thus it's okay to use the
* synchronized System.getProperties
* as it will never get called in normal operations.
*/
String implementingClass = System.getProperty("rxjava.plugin." + classSimpleName + ".implementation");
if (implementingClass != null) {
if (implementingClass != null)
try {
Class<?> cls = Class.forName(implementingClass);
// narrow the scope (cast) to the type we're expecting
@@ -140,8 +150,7 @@ public class RxJavaPlugins {
} catch (IllegalAccessException e) {
throw new RuntimeException(classSimpleName + " implementation not able to be accessed: " + implementingClass, e);
}
} else {
else
return null;
}
}
}

View File

@@ -6,9 +6,11 @@ import rx.Observable;
import rx.Subscription;
/**
* Subscription that can be checked for status such as in a loop inside an {@link Observable} to exit the loop if unsubscribed.
*
* @see Rx.Net equivalent BooleanDisposable at http://msdn.microsoft.com/en-us/library/system.reactive.disposables.booleandisposable(v=vs.103).aspx
* Subscription that can be checked for status such as in a loop inside an
* {@link Observable} to exit the loop if unsubscribed.
*
* @see Rx.Net equivalent BooleanDisposable at
* http://msdn.microsoft.com/en-us/library/system.reactive.disposables.booleandisposable(v=vs.103).aspx
*/
public class BooleanSubscription implements Subscription {

View File

@@ -6,9 +6,10 @@ import rx.util.functions.FuncN;
import rx.util.functions.Functions;
public class Subscriptions {
/**
* A {@link Subscription} that does nothing.
*
*
* @return {@link Subscription}
*/
public static Subscription empty() {
@@ -17,7 +18,7 @@ public class Subscriptions {
/**
* A {@link Subscription} implemented via a Func
*
*
* @return {@link Subscription}
*/
public static Subscription create(final Action0 unsubscribe) {
@@ -25,8 +26,9 @@ public class Subscriptions {
}
/**
* A {@link Subscription} implemented via an anonymous function (such as closures from other languages).
*
* A {@link Subscription} implemented via an anonymous function (such as
* closures from other languages).
*
* @return {@link Subscription}
*/
public static Subscription create(final Object unsubscribe) {
@@ -35,7 +37,9 @@ public class Subscriptions {
}
/**
* A {@link Subscription} that does nothing when its unsubscribe method is called.
* A {@link Subscription} that does nothing when its unsubscribe method is
* called.
*/
private static final Subscription EMPTY = () -> { };
private static final Subscription EMPTY = () -> {
};
}

View File

@@ -51,8 +51,9 @@ public final class AtomicObservableSubscription implements Subscription {
* constructed)
*
* @param actualSubscription
*
* @throws IllegalStateException if trying to set more than once (or use
* this method after setting via constructor)
* this method after setting via constructor)
*/
public AtomicObservableSubscription wrap(Subscription actualSubscription) {
if (!this.actualSubscription.compareAndSet(null, actualSubscription))

View File

@@ -9,33 +9,38 @@ import rx.plugins.RxJavaPlugins;
/**
* Wrapper around Observer to ensure compliance with Rx contract.
* <p>
* The following is taken from the Rx Design Guidelines document: http://go.microsoft.com/fwlink/?LinkID=205219
* The following is taken from the Rx Design Guidelines document:
* http://go.microsoft.com/fwlink/?LinkID=205219
* <pre>
* Messages sent to instances of the IObserver interface follow the following grammar:
*
*
* OnNext* (OnCompleted | OnError)?
*
*
* This grammar allows observable sequences to send any amount (0 or more) of OnNext messages to the subscribed
* observer instance, optionally followed by a single success (OnCompleted) or failure (OnError) message.
*
*
* The single message indicating that an observable sequence has finished ensures that consumers of the observable
* sequence can deterministically establish that it is safe to perform cleanup operations.
*
*
* A single failure further ensures that abort semantics can be maintained for operators that work on
* multiple observable sequences (see paragraph 6.6).
* </pre>
*
*
* <p>
* This wrapper will do the following:
* <ul>
* <li>Allow only single execution of either onError or onCompleted.</li>
* <li>Once an onComplete or onError are performed, no further calls can be executed</li>
* <li>If unsubscribe is called, this means we call completed() and don't allow any further onNext calls.</li>
* <li>When onError or onComplete occur it will unsubscribe from the Observable (if executing asynchronously).</li>
* <li>Once an onComplete or onError are performed, no further calls can be
* executed</li>
* <li>If unsubscribe is called, this means we call completed() and don't allow
* any further onNext calls.</li>
* <li>When onError or onComplete occur it will unsubscribe from the Observable
* (if executing asynchronously).</li>
* </ul>
* <p>
* It will not synchronize onNext execution. Use the {@link SynchronizedObserver} to do that.
*
* It will not synchronize onNext execution. Use the
* {@link SynchronizedObserver} to do that.
*
* @param <T>
*/
public class AtomicObserver<T> implements Observer<T> {
@@ -85,9 +90,8 @@ public class AtomicObserver<T> implements Observer<T> {
@Override
public void onNext(T args) {
try {
if (!isFinished.get()) {
if (!isFinished.get())
actual.onNext(args);
}
} catch (Exception e) {
// handle errors if the onNext implementation fails, not just if the Observable fails
onError(e);

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,16 +16,16 @@
package rx.util;
public class Exceptions {
private Exceptions() {
}
public static RuntimeException propagate(Throwable t) {
if (t instanceof RuntimeException) {
if (t instanceof RuntimeException)
throw (RuntimeException) t;
} else {
else
throw new RuntimeException(t);
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -19,6 +19,7 @@ import java.util.Iterator;
import java.util.NoSuchElementException;
public final class Range implements Iterable<Integer> {
private final int start;
private final int end;
private final int step;
@@ -53,9 +54,8 @@ public final class Range implements Iterable<Integer> {
@Override
public Integer next() {
if (!hasNext()) {
if (!hasNext())
throw new NoSuchElementException("No more elements");
}
int result = current;
current += step;
return result;
@@ -72,4 +72,4 @@ public final class Range implements Iterable<Integer> {
public String toString() {
return "Range (" + start + ", " + end + "), step " + step;
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -22,29 +22,36 @@ import rx.Observer;
* <p>
* Execution rules are:
* <ul>
* <li>Allow only single-threaded, synchronous, ordered execution of onNext, onCompleted, onError</li>
* <li>Once an onComplete or onError are performed, no further calls can be executed</li>
* <li>If unsubscribe is called, this means we call completed() and don't allow any further onNext calls.</li>
* <li>Allow only single-threaded, synchronous, ordered execution of onNext,
* onCompleted, onError</li>
* <li>Once an onComplete or onError are performed, no further calls can be
* executed</li>
* <li>If unsubscribe is called, this means we call completed() and don't allow
* any further onNext calls.</li>
* </ul>
*
*
* @param <T>
*/
public final class SynchronizedObserver<T> implements Observer<T> {
/**
* Intrinsic synchronized locking with double-check short-circuiting was chosen after testing several other implementations.
*
* The code and results can be found here:
* - https://github.com/benjchristensen/JavaLockPerformanceTests/tree/master/results/Observer
* - https://github.com/benjchristensen/JavaLockPerformanceTests/tree/master/src/com/benjchristensen/performance/locks/Observer
*
* The major characteristic that made me choose synchronized instead of Reentrant or a customer AbstractQueueSynchronizer implementation
* is that intrinsic locking performed better when nested, and AtomicObserver will end up nested most of the time since Rx is
* compositional by its very nature.
*
* // TODO composing of this class should rarely happen now with updated design so this decision should be revisited
* Intrinsic synchronized locking with double-check short-circuiting was
* chosen after testing several other implementations.
*
* The code and results can be found here: -
* https://github.com/benjchristensen/JavaLockPerformanceTests/tree/master/results/Observer
* -
* https://github.com/benjchristensen/JavaLockPerformanceTests/tree/master/src/com/benjchristensen/performance/locks/Observer
*
* The major characteristic that made me choose synchronized instead of
* Reentrant or a customer AbstractQueueSynchronizer implementation is that
* intrinsic locking performed better when nested, and AtomicObserver will
* end up nested most of the time since Rx is compositional by its very
* nature.
*
* // TODO composing of this class should rarely happen now with updated
* design so this decision should be revisited
*/
private final Observer<T> observer;
private final AtomicObservableSubscription subscription;
private volatile boolean finishRequested = false;
@@ -57,32 +64,28 @@ public final class SynchronizedObserver<T> implements Observer<T> {
@Override
public void onNext(T arg) {
if (finished || finishRequested || subscription.isUnsubscribed()) {
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 (this) {
// check again since this could have changed while waiting
if (finished || finishRequested || subscription.isUnsubscribed()) {
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);
}
}
@Override
public void onError(Exception e) {
if (finished || subscription.isUnsubscribed()) {
if (finished || subscription.isUnsubscribed())
// another thread has already finished us, so we won't proceed
return;
}
finishRequested = true;
synchronized (this) {
// check again since this could have changed while waiting
if (finished || subscription.isUnsubscribed()) {
if (finished || subscription.isUnsubscribed())
return;
}
observer.onError(e);
finished = true;
}
@@ -90,19 +93,17 @@ public final class SynchronizedObserver<T> implements Observer<T> {
@Override
public void onCompleted() {
if (finished || subscription.isUnsubscribed()) {
if (finished || subscription.isUnsubscribed())
// another thread has already finished us, so we won't proceed
return;
}
finishRequested = true;
synchronized (this) {
// check again since this could have changed while waiting
if (finished || subscription.isUnsubscribed()) {
if (finished || subscription.isUnsubscribed())
return;
}
observer.onCompleted();
finished = true;
}
}
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Action0 extends Function {
public void call();
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Action1<T1> extends Function {
public void call(T1 t1);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Action2<T1, T2> extends Function {
public void call(T1 t1, T2 t2);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Action3<T1, T2, T3> extends Function {
public void call(T1 t1, T2 t2, T3 t3);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func0<R> extends Function {
public R call();
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func1<T1, R> extends Function {
public R call(T1 t1);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func2<T1, T2, R> extends Function {
public R call(T1 t1, T2 t2);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func3<T1, T2, T3, R> extends Function {
public R call(T1 t1, T2 t2, T3 t3);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func4<T1, T2, T3, T4, R> extends Function {
public R call(T1 t1, T2 t2, T3 t3, T4 t4);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func5<T1, T2, T3, T4, T5, R> extends Function {
public R call(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func6<T1, T2, T3, T4, T5, T6, R> extends Function {
public R call(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func7<T1, T2, T3, T4, T5, T6, T7, R> extends Function {
public R call(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func8<T1, T2, T3, T4, T5, T6, T7, T8, R> extends Function {
public R call(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface Func9<T1, T2, T3, T4, T5, T6, T7, T8, T9, R> extends Function {
public R call(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8, T9 t9);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -16,5 +16,6 @@
package rx.util.functions;
public interface FuncN<R> extends Function {
public R call(Object... args);
}
}

View File

@@ -1,12 +1,12 @@
/**
* Copyright 2013 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.
@@ -19,9 +19,10 @@ public interface FunctionLanguageAdaptor {
/**
* Invoke the function and return the results.
*
*
* @param function
* @param args
*
* @return Object results from function execution
*/
Object call(Object function, Object[] args);
@@ -32,7 +33,7 @@ public interface FunctionLanguageAdaptor {
* Example: groovy.lang.Closure
* <p>
* This should not return classes of java.* packages.
*
*
* @return Class[] of classes that this adaptor should be invoked for.
*/
public Class<?>[] getFunctionClass();

View File

@@ -1,17 +1,17 @@
/**
* Copyright 2013 Netflix, Inc.
* <p>
* 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
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.
* 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.util.functions;
@@ -74,16 +74,20 @@ public class Functions {
*
* @param function
*/
@SuppressWarnings({"rawtypes"})
@SuppressWarnings({ "rawtypes" })
public static FuncN from(final Object function) {
if (function == null)
throw new RuntimeException("function is null. Can't send arguments to null function.");
/* check for typed Rx Function implementation first */
/*
* check for typed Rx Function implementation first
*/
if (function instanceof Function)
return fromFunction((Function) function);
else
/* not an Rx Function so try language adaptors */
/*
* not an Rx Function so try language adaptors
*/
// check for language adaptor
for (final Class c : languageAdaptors.keySet())
@@ -107,7 +111,7 @@ public class Functions {
//
// @SuppressWarnings("unchecked")
// private static <R> R executionRxFunction(Function function, Object... args) {
// // check Func* classes
// // check Func* classes
// if (function instanceof Func0) {
// Func0<R> f = (Func0<R>) function;
// if (args.length != 0) {
@@ -203,9 +207,9 @@ public class Functions {
//
// throw new RuntimeException("Unknown implementation of Function: " + function.getClass().getSimpleName());
// }
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({ "unchecked", "rawtypes" })
private static FuncN fromFunction(Function function) {
// check Func* classes
// check Func* classes
if (function instanceof Func0)
return fromFunc((Func0) function);
else if (function instanceof Func1)
@@ -245,6 +249,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <R> FuncN<R> fromFunc(final Func0<R> f) {
@@ -260,6 +265,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, R> FuncN<R> fromFunc(final Func1<T0, R> f) {
@@ -275,6 +281,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1, R> FuncN<R> fromFunc(final Func2<T0, T1, R> f) {
@@ -290,6 +297,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1, T2, R> FuncN<R> fromFunc(final Func3<T0, T1, T2, R> f) {
@@ -305,6 +313,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1, T2, T3, R> FuncN<R> fromFunc(final Func4<T0, T1, T2, T3, R> f) {
@@ -320,6 +329,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1, T2, T3, T4, R> FuncN<R> fromFunc(final Func5<T0, T1, T2, T3, T4, R> f) {
@@ -335,6 +345,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1, T2, T3, T4, T5, R> FuncN<R> fromFunc(final Func6<T0, T1, T2, T3, T4, T5, R> f) {
@@ -350,6 +361,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1, T2, T3, T4, T5, T6, R> FuncN<R> fromFunc(final Func7<T0, T1, T2, T3, T4, T5, T6, R> f) {
@@ -365,6 +377,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1, T2, T3, T4, T5, T6, T7, R> FuncN<R> fromFunc(final Func8<T0, T1, T2, T3, T4, T5, T6, T7, R> f) {
@@ -380,6 +393,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1, T2, T3, T4, T5, T6, T7, T8, R> FuncN<R> fromFunc(final Func9<T0, T1, T2, T3, T4, T5, T6, T7, T8, R> f) {
@@ -395,6 +409,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static FuncN<Void> fromAction(final Action0 f) {
@@ -411,6 +426,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0> FuncN<Void> fromAction(final Action1<T0> f) {
@@ -427,6 +443,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1> FuncN<Void> fromAction(final Action2<T0, T1> f) {
@@ -443,6 +460,7 @@ public class Functions {
* with different arities.
*
* @param f
*
* @return {@link FuncN}
*/
public static <T0, T1, T2> FuncN<Void> fromAction(final Action3<T0, T1, T2> f) {