18
18
import java .util .Iterator ;
19
19
import java .util .NoSuchElementException ;
20
20
import java .util .concurrent .Semaphore ;
21
- import java .util .concurrent .locks .Lock ;
22
- import java .util .concurrent .locks .ReentrantLock ;
21
+ import java .util .concurrent .atomic .AtomicReference ;
23
22
import rx .Notification ;
24
23
import rx .Observable ;
25
24
import rx .Observer ;
@@ -39,136 +38,67 @@ public static <T> Iterable<T> latest(final Observable<? extends T> source) {
39
38
@ Override
40
39
public Iterator <T > iterator () {
41
40
LatestObserverIterator <T > lio = new LatestObserverIterator <T >();
42
- source .subscribe (lio );
41
+ source .materialize (). subscribe (lio );
43
42
return lio ;
44
43
}
45
44
};
46
45
}
47
46
48
47
/** Observer of source, iterator for output. */
49
- static final class LatestObserverIterator <T > implements Observer <T >, Iterator <T > {
50
- final Lock lock = new ReentrantLock ();
48
+ static final class LatestObserverIterator <T > implements Observer <Notification <? extends T >>, Iterator <T > {
51
49
final Semaphore notify = new Semaphore (0 );
52
- // observer's values
53
- boolean oHasValue ;
54
- Notification .Kind oKind ;
55
- T oValue ;
56
- Throwable oError ;
50
+ // observer's notification
51
+ final AtomicReference <Notification <? extends T >> reference = new AtomicReference <Notification <? extends T >>();
57
52
@ Override
58
- public void onNext (T args ) {
59
- boolean wasntAvailable ;
60
- lock .lock ();
61
- try {
62
- wasntAvailable = !oHasValue ;
63
- oHasValue = true ;
64
- oValue = args ;
65
- oKind = Notification .Kind .OnNext ;
66
- } finally {
67
- lock .unlock ();
68
- }
53
+ public void onNext (Notification <? extends T > args ) {
54
+ boolean wasntAvailable = reference .getAndSet (args ) == null ;
69
55
if (wasntAvailable ) {
70
56
notify .release ();
71
57
}
72
58
}
73
59
74
60
@ Override
75
61
public void onError (Throwable e ) {
76
- boolean wasntAvailable ;
77
- lock .lock ();
78
- try {
79
- wasntAvailable = !oHasValue ;
80
- oHasValue = true ;
81
- oValue = null ;
82
- oError = e ;
83
- oKind = Notification .Kind .OnError ;
84
- } finally {
85
- lock .unlock ();
86
- }
87
- if (wasntAvailable ) {
88
- notify .release ();
89
- }
62
+ // not expected
90
63
}
91
64
92
65
@ Override
93
66
public void onCompleted () {
94
- boolean wasntAvailable ;
95
- lock .lock ();
96
- try {
97
- wasntAvailable = !oHasValue ;
98
- oHasValue = true ;
99
- oValue = null ;
100
- oKind = Notification .Kind .OnCompleted ;
101
- } finally {
102
- lock .unlock ();
103
- }
104
- if (wasntAvailable ) {
105
- notify .release ();
106
- }
67
+ // not expected
107
68
}
108
69
109
- // iterator's values
110
-
111
- boolean iDone ;
112
- boolean iHasValue ;
113
- T iValue ;
114
- Throwable iError ;
115
- Notification .Kind iKind ;
116
-
70
+ // iterator's notification
71
+ Notification <? extends T > iNotif ;
117
72
@ Override
118
73
public boolean hasNext () {
119
- if (iError != null ) {
120
- Exceptions .propagate (iError );
74
+ if (iNotif != null && iNotif . isOnError () ) {
75
+ throw Exceptions .propagate (iNotif . getThrowable () );
121
76
}
122
- if (! iDone ) {
123
- if (! iHasValue ) {
77
+ if (iNotif == null || ! iNotif . isOnCompleted () ) {
78
+ if (iNotif == null ) {
124
79
try {
125
80
notify .acquire ();
126
81
} catch (InterruptedException ex ) {
127
- iError = ex ;
128
- iHasValue = true ;
129
- iKind = Notification .Kind .OnError ;
130
- return true ;
82
+ Thread .currentThread ().interrupt ();
83
+ iNotif = new Notification <T >(ex );
84
+ throw Exceptions .propagate (ex );
131
85
}
132
86
133
- lock .lock ();
134
- try {
135
- iKind = oKind ;
136
- switch (oKind ) {
137
- case OnNext :
138
- iValue = oValue ;
139
- oValue = null ; // handover
140
- break ;
141
- case OnError :
142
- iError = oError ;
143
- oError = null ; // handover
144
- if (iError != null ) {
145
- Exceptions .propagate (iError );
146
- }
147
- break ;
148
- case OnCompleted :
149
- iDone = true ;
150
- break ;
151
- }
152
- oHasValue = false ;
153
- } finally {
154
- lock .unlock ();
87
+ iNotif = reference .getAndSet (null );
88
+ if (iNotif .isOnError ()) {
89
+ throw Exceptions .propagate (iNotif .getThrowable ());
155
90
}
156
- iHasValue = true ;
157
91
}
158
92
}
159
- return !iDone ;
93
+ return !iNotif . isOnCompleted () ;
160
94
}
161
95
162
96
@ Override
163
97
public T next () {
164
- if (iKind == Notification .Kind .OnError ) {
165
- Exceptions .propagate (iError );
166
- }
167
98
if (hasNext ()) {
168
- if (iKind == Notification .Kind .OnNext ) {
169
- T v = iValue ;
170
- iValue = null ; // handover
171
- iHasValue = false ;
99
+ if (iNotif .isOnNext ()) {
100
+ T v = iNotif .getValue ();
101
+ iNotif = null ;
172
102
return v ;
173
103
}
174
104
}
0 commit comments