Skip to content

Commit f1be5f4

Browse files
committed
Non-blocking implementation of ScheduledObserver
1 parent e94d213 commit f1be5f4

File tree

1 file changed

+33
-37
lines changed

1 file changed

+33
-37
lines changed

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

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@
2121
import rx.util.functions.Action0;
2222

2323
import java.util.concurrent.ConcurrentLinkedQueue;
24+
import java.util.concurrent.atomic.AtomicInteger;
2425

2526
/* package */class ScheduledObserver<T> implements Observer<T> {
2627
private final Observer<T> underlying;
2728
private final Scheduler scheduler;
2829

2930
private final ConcurrentLinkedQueue<Notification<T>> queue = new ConcurrentLinkedQueue<Notification<T>>();
30-
private final Object lock = new Object();
31+
private final AtomicInteger counter = new AtomicInteger(0);
3132

3233
public ScheduledObserver(Observer<T> underlying, Scheduler scheduler) {
3334
this.underlying = underlying;
@@ -50,48 +51,43 @@ public void onNext(final T args) {
5051
}
5152

5253
private void enqueue(Notification<T> notification) {
53-
boolean schedule;
54-
synchronized (lock) {
55-
schedule = queue.isEmpty();
54+
int count = counter.getAndIncrement();
5655

57-
queue.offer(notification);
56+
queue.offer(notification);
57+
58+
if (count == 0) {
59+
processQueue();
5860
}
61+
}
5962

60-
if (schedule) {
61-
scheduler.schedule(new Action0() {
62-
@Override
63-
public void call() {
64-
Notification<T> not = dequeue();
65-
66-
if (not == null) {
67-
return;
68-
}
69-
70-
switch (not.getKind()) {
71-
case OnNext:
72-
underlying.onNext(not.getValue());
73-
break;
74-
case OnError:
75-
underlying.onError(not.getException());
76-
break;
77-
case OnCompleted:
78-
underlying.onCompleted();
79-
break;
80-
default:
81-
throw new IllegalStateException("Unknown kind of notification " + not);
82-
83-
}
63+
private void processQueue() {
64+
scheduler.schedule(new Action0() {
65+
@Override
66+
public void call() {
67+
int count = counter.decrementAndGet();
68+
69+
Notification<T> not = queue.poll();
70+
71+
switch (not.getKind()) {
72+
case OnNext:
73+
underlying.onNext(not.getValue());
74+
break;
75+
case OnError:
76+
underlying.onError(not.getException());
77+
break;
78+
case OnCompleted:
79+
underlying.onCompleted();
80+
break;
81+
default:
82+
throw new IllegalStateException("Unknown kind of notification " + not);
8483

85-
scheduler.schedule(this);
84+
}
8685

86+
if (count > 0) {
87+
scheduler.schedule(this);
8788
}
88-
});
89-
}
90-
}
9189

92-
private Notification<T> dequeue() {
93-
synchronized (lock) {
94-
return queue.poll();
95-
}
90+
}
91+
});
9692
}
9793
}

0 commit comments

Comments
 (0)