Skip to content

Commit 4d325c6

Browse files
authored
3.x: Workaround for FutureTask.toString + JDK 11 build (#7173)
1 parent 8dd6f21 commit 4d325c6

File tree

7 files changed

+177
-2
lines changed

7 files changed

+177
-2
lines changed

Diff for: .github/workflows/gradle_jdk11.yml

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# This workflow will build a Java project with Gradle
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
3+
4+
name: JDK 11
5+
6+
on:
7+
push:
8+
branches: [ 3.x ]
9+
pull_request:
10+
branches: [ 3.x ]
11+
12+
jobs:
13+
build:
14+
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v2
18+
- name: Set up JDK 11
19+
uses: actions/setup-java@v1
20+
with:
21+
java-version: 11
22+
- name: Cache Gradle packages
23+
uses: actions/cache@v2
24+
with:
25+
path: ~/.gradle/caches
26+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
27+
restore-keys: ${{ runner.os }}-gradle
28+
- name: Grant execute permission for gradlew
29+
run: chmod +x gradlew
30+
- name: Build PR
31+
run: ./gradlew -PreleaseMode=pr build --stacktrace
32+
#- name: Upload to Codecov
33+
# uses: codecov/codecov-action@v1

Diff for: src/main/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTask.java

+20
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,24 @@ public final void setFuture(Future<?> future) {
8383
public Runnable getWrappedRunnable() {
8484
return runnable;
8585
}
86+
87+
@Override
88+
public String toString() {
89+
String status;
90+
Future<?> f = get();
91+
if (f == FINISHED) {
92+
status = "Finished";
93+
} else if (f == DISPOSED) {
94+
status = "Disposed";
95+
} else {
96+
Thread r = runner;
97+
if (r != null) {
98+
status = "Running on " + runner;
99+
} else {
100+
status = "Waiting";
101+
}
102+
}
103+
104+
return getClass().getSimpleName() + "[" + status + "]";
105+
}
86106
}

Diff for: src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledDirectPeriodicTask.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ public void run() {
3939
runner = null;
4040
} catch (Throwable ex) {
4141
// Exceptions.throwIfFatal(ex); nowhere to go
42-
runner = null;
4342
dispose();
43+
runner = null;
4444
RxJavaPlugins.onError(ex);
4545
throw ex;
4646
}

Diff for: src/main/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnable.java

+23-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ public void run() {
6969
throw e;
7070
}
7171
} finally {
72-
lazySet(THREAD_INDEX, null);
7372
Object o = get(PARENT_INDEX);
7473
if (o != PARENT_DISPOSED && compareAndSet(PARENT_INDEX, o, DONE) && o != null) {
7574
((DisposableContainer)o).delete(this);
@@ -81,6 +80,7 @@ public void run() {
8180
break;
8281
}
8382
}
83+
lazySet(THREAD_INDEX, null);
8484
}
8585
}
8686

@@ -137,4 +137,26 @@ public boolean isDisposed() {
137137
Object o = get(PARENT_INDEX);
138138
return o == PARENT_DISPOSED || o == DONE;
139139
}
140+
141+
@Override
142+
public String toString() {
143+
String state;
144+
Object o = get(FUTURE_INDEX);
145+
if (o == DONE) {
146+
state = "Finished";
147+
} else if (o == SYNC_DISPOSED) {
148+
state = "Disposed(Sync)";
149+
} else if (o == ASYNC_DISPOSED) {
150+
state = "Disposed(Async)";
151+
} else {
152+
o = get(THREAD_INDEX);
153+
if (o == null) {
154+
state = "Waiting";
155+
} else {
156+
state = "Running on " + o;
157+
}
158+
}
159+
160+
return getClass().getSimpleName() + "[" + state + "]";
161+
}
140162
}

Diff for: src/test/java/io/reactivex/rxjava3/internal/schedulers/AbstractDirectTaskTest.java

+27
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,31 @@ public void run() {
241241
TestHelper.race(r1, r2);
242242
}
243243
}
244+
245+
static class TestDirectTask extends AbstractDirectTask {
246+
private static final long serialVersionUID = 587679821055711738L;
247+
248+
TestDirectTask() {
249+
super(Functions.EMPTY_RUNNABLE);
250+
}
251+
}
252+
253+
@Test
254+
public void toStringStates() {
255+
TestDirectTask task = new TestDirectTask();
256+
257+
assertEquals("TestDirectTask[Waiting]", task.toString());
258+
259+
task.runner = Thread.currentThread();
260+
261+
assertEquals("TestDirectTask[Running on " + Thread.currentThread() + "]", task.toString());
262+
263+
task.dispose();
264+
265+
assertEquals("TestDirectTask[Disposed]", task.toString());
266+
267+
task.set(AbstractDirectTask.FINISHED);
268+
269+
assertEquals("TestDirectTask[Finished]", task.toString());
270+
}
244271
}

Diff for: src/test/java/io/reactivex/rxjava3/internal/schedulers/ScheduledRunnableTest.java

+25
Original file line numberDiff line numberDiff line change
@@ -399,4 +399,29 @@ public void withParentIsDisposed() {
399399

400400
assertFalse(set.remove(run));
401401
}
402+
403+
@Test
404+
public void toStringStates() {
405+
CompositeDisposable set = new CompositeDisposable();
406+
ScheduledRunnable task = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set);
407+
408+
assertEquals("ScheduledRunnable[Waiting]", task.toString());
409+
410+
task.set(ScheduledRunnable.THREAD_INDEX, Thread.currentThread());
411+
412+
assertEquals("ScheduledRunnable[Running on " + Thread.currentThread() + "]", task.toString());
413+
414+
task.dispose();
415+
416+
assertEquals("ScheduledRunnable[Disposed(Sync)]", task.toString());
417+
418+
task.set(ScheduledRunnable.FUTURE_INDEX, ScheduledRunnable.DONE);
419+
420+
assertEquals("ScheduledRunnable[Finished]", task.toString());
421+
422+
task = new ScheduledRunnable(Functions.EMPTY_RUNNABLE, set);
423+
task.dispose();
424+
425+
assertEquals("ScheduledRunnable[Disposed(Async)]", task.toString());
426+
}
402427
}

Diff for: src/test/java/io/reactivex/rxjava3/schedulers/AbstractSchedulerTests.java

+48
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.reactivestreams.*;
2828

2929
import io.reactivex.rxjava3.core.*;
30+
import io.reactivex.rxjava3.core.Scheduler.Worker;
3031
import io.reactivex.rxjava3.disposables.Disposable;
3132
import io.reactivex.rxjava3.functions.*;
3233
import io.reactivex.rxjava3.internal.disposables.SequentialDisposable;
@@ -771,4 +772,51 @@ public void schedulePeriodicallyDirectNullRunnable() {
771772
assertEquals("run is null", npe.getMessage());
772773
}
773774
}
775+
776+
void schedulePrint(Function<Runnable, Disposable> onSchedule) {
777+
CountDownLatch waitForBody = new CountDownLatch(1);
778+
CountDownLatch waitForPrint = new CountDownLatch(1);
779+
780+
try {
781+
Disposable d = onSchedule.apply(() -> {
782+
waitForBody.countDown();
783+
try {
784+
waitForPrint.await();
785+
} catch (InterruptedException ex) {
786+
ex.printStackTrace();
787+
}
788+
});
789+
790+
waitForBody.await();
791+
792+
assertNotEquals("", d.toString());
793+
} catch (Throwable ex) {
794+
throw new AssertionError(ex);
795+
} finally {
796+
waitForPrint.countDown();
797+
}
798+
}
799+
800+
@Test
801+
public void scheduleDirectPrint() {
802+
if (getScheduler() instanceof TrampolineScheduler) {
803+
// no concurrency with Trampoline
804+
return;
805+
}
806+
schedulePrint(r -> getScheduler().scheduleDirect(r));
807+
}
808+
809+
@Test
810+
public void schedulePrint() {
811+
if (getScheduler() instanceof TrampolineScheduler) {
812+
// no concurrency with Trampoline
813+
return;
814+
}
815+
Worker worker = getScheduler().createWorker();
816+
try {
817+
schedulePrint(worker::schedule);
818+
} finally {
819+
worker.dispose();
820+
}
821+
}
774822
}

0 commit comments

Comments
 (0)