16
16
package rx .internal .operators ;
17
17
18
18
import java .util .Iterator ;
19
+ import java .util .NoSuchElementException ;
19
20
20
21
import rx .Observable ;
21
22
import rx .Subscriber ;
@@ -41,54 +42,24 @@ public final class BlockingOperatorMostRecent {
41
42
* {@code initialValue} if {@code source} has not yet emitted any items
42
43
*/
43
44
public static <T > Iterable <T > mostRecent (final Observable <? extends T > source , final T initialValue ) {
44
-
45
45
return new Iterable <T >() {
46
46
@ Override
47
47
public Iterator <T > iterator () {
48
48
MostRecentObserver <T > mostRecentObserver = new MostRecentObserver <T >(initialValue );
49
- final MostRecentIterator <T > nextIterator = new MostRecentIterator <T >(mostRecentObserver );
50
49
51
50
/**
52
51
* Subscribe instead of unsafeSubscribe since this is the final subscribe in the chain
53
52
* since it is for BlockingObservable.
54
53
*/
55
54
source .subscribe (mostRecentObserver );
56
55
57
- return nextIterator ;
56
+ return mostRecentObserver . getIterable () ;
58
57
}
59
58
};
60
-
61
- }
62
-
63
- private static class MostRecentIterator <T > implements Iterator <T > {
64
-
65
- private final MostRecentObserver <T > observer ;
66
-
67
- private MostRecentIterator (MostRecentObserver <T > observer ) {
68
- this .observer = observer ;
69
- }
70
-
71
- @ Override
72
- public boolean hasNext () {
73
- return !observer .isCompleted ();
74
- }
75
-
76
- @ Override
77
- public T next () {
78
- if (observer .getThrowable () != null ) {
79
- throw Exceptions .propagate (observer .getThrowable ());
80
- }
81
- return observer .getRecentValue ();
82
- }
83
-
84
- @ Override
85
- public void remove () {
86
- throw new UnsupportedOperationException ("Read only iterator" );
87
- }
88
59
}
89
60
90
61
private static class MostRecentObserver <T > extends Subscriber <T > {
91
- static final NotificationLite <Object > nl = NotificationLite .instance ();
62
+ final NotificationLite <T > nl = NotificationLite .instance ();
92
63
volatile Object value ;
93
64
94
65
private MostRecentObserver (T value ) {
@@ -110,19 +81,47 @@ public void onNext(T args) {
110
81
value = nl .next (args );
111
82
}
112
83
113
- private boolean isCompleted () {
114
- return nl .isCompleted (value );
115
- }
116
-
117
- private Throwable getThrowable () {
118
- Object v = value ;
119
- return nl .isError (v ) ? nl .getError (v ) : null ;
120
- }
121
-
122
- @ SuppressWarnings ("unchecked" )
123
- private T getRecentValue () {
124
- return (T )value ;
84
+ /**
85
+ * The {@link Iterator} return is not thread safe. In other words don't call {@link Iterator#hasNext()} in one
86
+ * thread expect {@link Iterator#next()} called from a different thread to work.
87
+ * @return
88
+ */
89
+ public Iterator <T > getIterable () {
90
+ return new Iterator <T >() {
91
+ /**
92
+ * buffer to make sure that the state of the iterator doesn't change between calling hasNext() and next().
93
+ */
94
+ private Object buf = null ;
95
+
96
+ @ Override
97
+ public boolean hasNext () {
98
+ buf = value ;
99
+ return !nl .isCompleted (buf );
100
+ }
101
+
102
+ @ Override
103
+ public T next () {
104
+ try {
105
+ // if hasNext wasn't called before calling next.
106
+ if (buf == null )
107
+ buf = value ;
108
+ if (nl .isCompleted (buf ))
109
+ throw new NoSuchElementException ();
110
+ if (nl .isError (buf )) {
111
+ throw Exceptions .propagate (nl .getError (buf ));
112
+ }
113
+ return nl .getValue (buf );
114
+ }
115
+ finally {
116
+ buf = null ;
117
+ }
118
+ }
119
+
120
+ @ Override
121
+ public void remove () {
122
+ throw new UnsupportedOperationException ("Read only iterator" );
123
+ }
124
+ };
125
125
}
126
-
127
126
}
128
127
}
0 commit comments