Skip to content

Commit 7c726b1

Browse files
committed
Fix the ticker channel example giving wrong results on the website
https://play.kotlinlang.org/ of the example that's being changed here is currently unreliable: the last line is occasionally `null`. By increasing all time intervals twofold, we reduce the impact of the CPU scheduling in the constrained environment. With this change, the results are consistent across dozens of runs: <https://pl.kotl.in/uCa-60j43> Originally reported by `@PetrakovichVictoria`
1 parent 515308d commit 7c726b1

File tree

2 files changed

+22
-22
lines changed

2 files changed

+22
-22
lines changed

docs/topics/channels.md

+13-13
Original file line numberDiff line numberDiff line change
@@ -576,25 +576,25 @@ import kotlinx.coroutines.channels.*
576576

577577
//sampleStart
578578
fun main() = runBlocking<Unit> {
579-
val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
579+
val tickerChannel = ticker(delayMillis = 200, initialDelayMillis = 0) // create a ticker channel
580580
var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
581581
println("Initial element is available immediately: $nextElement") // no initial delay
582582

583-
nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
584-
println("Next element is not ready in 50 ms: $nextElement")
583+
nextElement = withTimeoutOrNull(100) { tickerChannel.receive() } // all subsequent elements have 200ms delay
584+
println("Next element is not ready in 100 ms: $nextElement")
585585

586-
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
587-
println("Next element is ready in 100 ms: $nextElement")
586+
nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
587+
println("Next element is ready in 200 ms: $nextElement")
588588

589589
// Emulate large consumption delays
590-
println("Consumer pauses for 150ms")
591-
delay(150)
590+
println("Consumer pauses for 300ms")
591+
delay(300)
592592
// Next element is available immediately
593593
nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
594594
println("Next element is available immediately after large consumer delay: $nextElement")
595595
// Note that the pause between `receive` calls is taken into account and next element arrives faster
596-
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
597-
println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
596+
nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
597+
println("Next element is ready in 100ms after consumer pause in 300ms: $nextElement")
598598

599599
tickerChannel.cancel() // indicate that no more elements are needed
600600
}
@@ -610,11 +610,11 @@ It prints following lines:
610610

611611
```text
612612
Initial element is available immediately: kotlin.Unit
613-
Next element is not ready in 50 ms: null
614-
Next element is ready in 100 ms: kotlin.Unit
615-
Consumer pauses for 150ms
613+
Next element is not ready in 10 ms: null
614+
Next element is ready in 200 ms: kotlin.Unit
615+
Consumer pauses for 300ms
616616
Next element is available immediately after large consumer delay: kotlin.Unit
617-
Next element is ready in 50ms after consumer pause in 150ms: kotlin.Unit
617+
Next element is ready in 100ms after consumer pause in 300ms: kotlin.Unit
618618
```
619619

620620
<!--- TEST -->

kotlinx-coroutines-core/jvm/test/guide/example-channel-10.kt

+9-9
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,25 @@ import kotlinx.coroutines.*
55
import kotlinx.coroutines.channels.*
66

77
fun main() = runBlocking<Unit> {
8-
val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
8+
val tickerChannel = ticker(delayMillis = 200, initialDelayMillis = 0) // create a ticker channel
99
var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
1010
println("Initial element is available immediately: $nextElement") // no initial delay
1111

12-
nextElement = withTimeoutOrNull(50) { tickerChannel.receive() } // all subsequent elements have 100ms delay
13-
println("Next element is not ready in 50 ms: $nextElement")
12+
nextElement = withTimeoutOrNull(100) { tickerChannel.receive() } // all subsequent elements have 200ms delay
13+
println("Next element is not ready in 100 ms: $nextElement")
1414

15-
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
16-
println("Next element is ready in 100 ms: $nextElement")
15+
nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
16+
println("Next element is ready in 200 ms: $nextElement")
1717

1818
// Emulate large consumption delays
19-
println("Consumer pauses for 150ms")
20-
delay(150)
19+
println("Consumer pauses for 300ms")
20+
delay(300)
2121
// Next element is available immediately
2222
nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
2323
println("Next element is available immediately after large consumer delay: $nextElement")
2424
// Note that the pause between `receive` calls is taken into account and next element arrives faster
25-
nextElement = withTimeoutOrNull(60) { tickerChannel.receive() }
26-
println("Next element is ready in 50ms after consumer pause in 150ms: $nextElement")
25+
nextElement = withTimeoutOrNull(120) { tickerChannel.receive() }
26+
println("Next element is ready in 100ms after consumer pause in 300ms: $nextElement")
2727

2828
tickerChannel.cancel() // indicate that no more elements are needed
2929
}

0 commit comments

Comments
 (0)