Browse Source

[all] Updated according to the final drafts

master
Miguel Castiblanco 3 years ago
parent
commit
04dd43010e
  1. 5
      src/main/kotlin/chapter1/section1/lightweight.kt
  2. 3
      src/main/kotlin/chapter1/section3/cpu_bound.kt
  3. 2
      src/main/kotlin/chapter1/section4/atomicity_violation.kt
  4. 1
      src/main/kotlin/chapter1/section4/deadlock.kt
  5. 7
      src/main/kotlin/chapter1/section4/race_condition.kt
  6. 4
      src/main/kotlin/chapter1/section5/explicit.kt
  7. 5
      src/main/kotlin/chapter1/section5/readable.kt
  8. 22
      src/main/kotlin/chapter2/async/async.kt
  9. 1
      src/main/kotlin/chapter2/dispatcher/launch.kt
  10. 2
      src/main/kotlin/chapter2/launch/launch.kt
  11. 5
      src/main/kotlin/chapter3/deferred/exception/await/await.kt
  12. 8
      src/main/kotlin/chapter3/deferred/exception/await/trycatch/trycatch.kt
  13. 4
      src/main/kotlin/chapter3/deferred/exception/exception.kt
  14. 4
      src/main/kotlin/chapter3/job/cancellation/cancelled/exception/handler/handler.kt
  15. 5
      src/main/kotlin/chapter3/job/cancellation/cancelled/exception/handler/oncompletion/on_completion.kt
  16. 2
      src/main/kotlin/chapter3/job/lazy/join/join_start.kt
  17. 3
      src/main/kotlin/chapter3/job/lazy/start/lazy_start.kt
  18. 3
      src/main/kotlin/chapter4/client/deferred/deferred_impl.kt
  19. 3
      src/main/kotlin/chapter4/client/suspending/suspend_impl.kt
  20. 1
      src/main/kotlin/chapter4/context/dispatcher/dispatcher.kt
  21. 7
      src/main/kotlin/chapter4/context/exception/exception_handling.kt
  22. 7
      src/main/kotlin/chapter4/context/mix/join/join.kt
  23. 7
      src/main/kotlin/chapter4/context/mix/separate/separate.kt
  24. 7
      src/main/kotlin/chapter4/context/noncancellable/noncancellable.kt
  25. 4
      src/main/kotlin/chapter4/context/switch/switch.kt
  26. 3
      src/main/kotlin/chapter4/suspending/suspending.kt
  27. 3
      src/main/kotlin/chapter5/iterator/examples.kt
  28. 4
      src/main/kotlin/chapter5/iterator/fibonacci/fibonacci_iterator.kt
  29. 6
      src/main/kotlin/chapter5/producer/examples.kt
  30. 3
      src/main/kotlin/chapter5/producer/fibonacci/fibonacci.kt
  31. 3
      src/main/kotlin/chapter5/sequence/examples.kt
  32. 1
      src/main/kotlin/chapter5/sequence/fibonacci/sequence.kt
  33. 3
      src/main/kotlin/chapter6/buffered/array/array.kt
  34. 3
      src/main/kotlin/chapter6/buffered/conflated/conflated.kt
  35. 3
      src/main/kotlin/chapter6/buffered/linked/linked.kt
  36. 3
      src/main/kotlin/chapter6/interaction/receive/receive.kt
  37. 3
      src/main/kotlin/chapter6/interaction/send/send.kt
  38. 3
      src/main/kotlin/chapter6/unbufffered/rendezvous/rendezvous.kt
  39. 3
      src/main/kotlin/chapter7/actor/interaction/actor_samples.kt
  40. 3
      src/main/kotlin/chapter7/atomic/atomic.kt
  41. 3
      src/main/kotlin/chapter7/atomicity/atomicity_violation.kt
  42. 2
      src/main/kotlin/chapter7/confinement/thread_confinement.kt
  43. 1
      src/main/kotlin/chapter7/mutex/interaction/mutex_interaction.kt
  44. 3
      src/main/kotlin/chapter7/mutex/mutex.kt
  45. 7
      src/main/kotlin/chapter7/volatile/volatile.kt
  46. 3
      src/main/kotlin/chapter8/debugging.kt
  47. 4
      src/main/kotlin/chapter8/test_feature.kt
  48. 3
      src/test/kotlin/chapter8/SampleAppFT.kt

5
src/main/kotlin/chapter1/section1/lightweight.kt

@ -7,6 +7,11 @@ import kotlinx.coroutines.experimental.runBlocking
import kotlin.system.measureTimeMillis
/**
* Init, suspend, and resume three coroutines. They will
* potentially be resumed in different threads than the ones
* they were created on.
*/
fun main(args: Array<String>) = runBlocking {
println("${Thread.activeCount()} threads active at the start")
val time = measureTimeMillis {

3
src/main/kotlin/chapter1/section3/cpu_bound.kt

@ -2,6 +2,9 @@ package chapter1.section3
val words = listOf("level", "pope", "needle", "Anna", "Pete", "noon", "stats")
/**
* CPU-bound algorithm.
*/
fun main(args: Array<String>) {
filterPalindromes(words).forEach {
println(it)

2
src/main/kotlin/chapter1/section4/atomicity_violation.kt

@ -3,7 +3,7 @@ package chapter1.section4
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.runBlocking
// This method will print values lower than 2100 often
// This method will often print values lower than 2100
fun main(args: Array<String>) = runBlocking {
val workerA = asyncIncrement(2000)
val workerB = asyncIncrement(100)

1
src/main/kotlin/chapter1/section4/deadlock.kt

@ -8,6 +8,7 @@ import kotlinx.coroutines.experimental.runBlocking
lateinit var jobA : Job
lateinit var jobB : Job
// This will never complete execution.
fun main(args: Array<String>) = runBlocking {
jobA = launch {
delay(1000)

7
src/main/kotlin/chapter1/section4/race_condition.kt

@ -8,6 +8,11 @@ data class UserInfo(val name: String, val lastName: String, val id: Int)
lateinit var user: UserInfo
/**
* This will crash because the information is not ready by the
* time we try to use it.
*/
fun main(args: Array<String>) = runBlocking {
asyncGetUserInfo(1)
// Do some other operations
@ -18,5 +23,5 @@ fun main(args: Array<String>) = runBlocking {
fun asyncGetUserInfo(id: Int) = async {
delay(1100)
user = UserInfo(id = id, name = "Miguel", lastName = "Castiblanco")
user = UserInfo(id = id, name = "Susan", lastName = "Calvin")
}

4
src/main/kotlin/chapter1/section5/explicit.kt

@ -5,6 +5,10 @@ import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.runBlocking
import kotlin.system.measureTimeMillis
/**
* In this example, `async()` is being used to indicate
* explicitly that it's an asynchronous operation.
*/
fun main(args: Array<String>) = runBlocking {
val time = measureTimeMillis {
val name = async { getName() }

5
src/main/kotlin/chapter1/section5/readable.kt

@ -2,6 +2,11 @@ package chapter1.section5
import kotlinx.coroutines.experimental.async
/**
* This file contains logic that is asynchronous
* but can be read easily.
*/
class Profile(userInfo: UserInfo, contactInfo: ContactInfo)
class UserInfo(name:String, lastName: String)
class ContactInfo(address: String, zipCode: Int)

22
src/main/kotlin/chapter2/async/async.kt

@ -3,6 +3,9 @@ package chapter2.async
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.runBlocking
/**
* Async examples
*/
fun main(args: Array<String>) = runBlocking {
val task = async {
doSomething()
@ -13,22 +16,19 @@ fun main(args: Array<String>) = runBlocking {
println("Completed")
/* This code will wait for the async to end and validate its output
// This code will wait for the async to end and validate its output.
// Comment line `15` for this to work
task.join()
if (task.isCompletedExceptionally) {
val exception = task.getCompletionExceptionOrNull()!!
// If the code below executes the `else` branch, please replace
// `isCancelled` with `isCompletedExceptionally`. For more info see
// https://github.com/Kotlin/kotlinx.coroutines/issues/220
if (task.isCancelled) {
val exception = task.getCancellationException()
println("Error with message: ${exception.message}")
} else {
println("Success")
}*/
/* This code will have the application end without any error
task.join()
println("Completed")
*/
}
}
fun doSomething() {

1
src/main/kotlin/chapter2/dispatcher/launch.kt

@ -4,6 +4,7 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.newSingleThreadContext
import kotlinx.coroutines.experimental.runBlocking
// Use a ThreadPoolDispatcher to run the coroutine
fun main(args: Array<String>) = runBlocking {
val netDispatcher = newSingleThreadContext(name = "ServiceCall")

2
src/main/kotlin/chapter2/launch/launch.kt

@ -4,6 +4,7 @@ import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
// Use laynch to start a coroutine that crashes.
fun main(args: Array<String>) = runBlocking {
val task = launch {
@ -19,5 +20,4 @@ suspend fun doSomething() {
println("Half-way to crash")
delay(100)
throw UnsupportedOperationException("Can't do")
}

5
src/main/kotlin/chapter3/deferred/exception/await/await.kt

@ -5,9 +5,8 @@ import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.runBlocking
/**
* An example having an exception propagate because
* we are listening to the Deferred using await().
* Please notice that the last line will never be executed.
* In this example the exception will be propagated because we
* are calling await()
*/
fun main(args: Array<String>) = runBlocking<Unit> {
val deferred = async {

8
src/main/kotlin/chapter3/deferred/exception/await/trycatch/trycatch.kt

@ -4,11 +4,10 @@ import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.runBlocking
/**
* An example having an exception propagate because
* we are listening to the Deferred using await().
* Please notice that the last line will never be executed.
* In this example with handle an exception by using a
* try-catch block
*/
fun main(args: Array<String>) = runBlocking<Unit> {
fun main(args: Array<String>) = runBlocking {
val deferred = async {
TODO("Not implemented yet!")
}
@ -18,5 +17,4 @@ fun main(args: Array<String>) = runBlocking<Unit> {
} catch (throwable: Throwable) {
println("Deferred cancelled due to ${throwable.message}")
}
}

4
src/main/kotlin/chapter3/deferred/exception/exception.kt

@ -5,8 +5,8 @@ import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.runBlocking
/**
* An example of how to wrap an exception
* inside a Deferred
* In this example the exception will not be propagated
* because `await()` isn't being called
*/
fun main(args: Array<String>) = runBlocking {
val deferred = async {

4
src/main/kotlin/chapter3/job/cancellation/cancelled/exception/handler/handler.kt

@ -6,6 +6,10 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import kotlin.coroutines.experimental.CoroutineContext
/**
* Handle the exception in a Job using
* a CoroutineExceptionHandler
*/
fun main(args: Array<String>) = runBlocking {
val exceptionHandler = CoroutineExceptionHandler {
_: CoroutineContext, throwable: Throwable ->

5
src/main/kotlin/chapter3/job/cancellation/cancelled/exception/handler/oncompletion/on_completion.kt

@ -4,7 +4,10 @@ import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
fun main(args: Array<String>) = runBlocking<Unit> {
/**
* Handle the exception of a Job using `invokeOnCompletion`
*/
fun main(args: Array<String>) = runBlocking {
launch {
TODO("Not implemented yet!")
}.invokeOnCompletion { cause ->

2
src/main/kotlin/chapter3/job/lazy/join/join_start.kt

@ -6,7 +6,7 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
/**
* This code start a Job lazily, and waits for its execution to complete
* This code start a job lazily, and waits for its execution to complete
*/
fun main(args: Array<String>) = runBlocking {
val job = launch(start = CoroutineStart.LAZY) {

3
src/main/kotlin/chapter3/job/lazy/start/lazy_start.kt

@ -6,11 +6,12 @@ import kotlinx.coroutines.experimental.launch
/**
* This code start a coroutine lazily but doesn't wait
* for it to complete
* for it to complete, so the log entry is never printed.
*/
fun main(args: Array<String>) {
val job = launch(start = CoroutineStart.LAZY) {
delay(3000)
println("job completed")
}
job.start()

3
src/main/kotlin/chapter4/client/deferred/deferred_impl.kt

@ -4,6 +4,9 @@ import kotlinx.coroutines.experimental.Deferred
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.runBlocking
/**
* Implementation using deferred.
*/
fun main(args: Array<String>) = runBlocking {
val client : ProfileServiceRepository = ProfileServiceClient()

3
src/main/kotlin/chapter4/client/suspending/suspend_impl.kt

@ -2,6 +2,9 @@ package chapter4.client.suspending
import kotlinx.coroutines.experimental.runBlocking
/**
* Implementation using suspending functions.
*/
fun main(args: Array<String>) = runBlocking {
val repository: ProfileServiceRepository = ProfileServiceClient()

1
src/main/kotlin/chapter4/context/dispatcher/dispatcher.kt

@ -5,7 +5,6 @@ import kotlinx.coroutines.experimental.*
/**
* This file contains examples of different types of dispatchers
*/
fun main(args: Array<String>) {
commonPool()
defaultDispatcher()

7
src/main/kotlin/chapter4/context/exception/exception_handling.kt

@ -5,11 +5,14 @@ import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
/**
* Using CoroutineExceptionHandler to log an exception.
*/
fun main(args: Array<String>) = runBlocking {
val handler = CoroutineExceptionHandler({ context, throwable ->
val handler = CoroutineExceptionHandler { context, throwable ->
println("Error captured in $context")
println("Message: ${throwable.message}")
})
}
launch(handler) {
TODO("Not implemented yet!")

7
src/main/kotlin/chapter4/context/mix/join/join.kt

@ -5,12 +5,15 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.newSingleThreadContext
import kotlinx.coroutines.experimental.runBlocking
/**
* Join two contexts using the `+` operator
*/
fun main(args: Array<String>) = runBlocking {
val dispatcher = newSingleThreadContext("myDispatcher")
val handler = CoroutineExceptionHandler({ _, throwable ->
val handler = CoroutineExceptionHandler { _, throwable ->
println("Error captured")
println("Message: ${throwable.message}")
})
}
// Combine two contexts together
val context = dispatcher + handler

7
src/main/kotlin/chapter4/context/mix/separate/separate.kt

@ -5,12 +5,15 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.newSingleThreadContext
import kotlinx.coroutines.experimental.runBlocking
/**
* Use `minusKey()` to separate two contexts previously joined.
*/
fun main(args: Array<String>) = runBlocking {
val dispatcher = newSingleThreadContext("myDispatcher")
val handler = CoroutineExceptionHandler({ _, throwable ->
val handler = CoroutineExceptionHandler { _, throwable ->
println("Error captured")
println("Message: ${throwable.message}")
})
}
// Combine two contexts together
val context = dispatcher + handler

7
src/main/kotlin/chapter4/context/noncancellable/noncancellable.kt

@ -3,9 +3,12 @@ package chapter4.context.noncancellable
import kotlinx.coroutines.experimental.*
import kotlin.system.measureTimeMillis
/**
* Examples using cancellation.
*/
fun main(args: Array<String>) = runBlocking {
//cancellation()
//cancellationDelay()
cancellation()
cancellationDelay()
nonCancellable()
}

4
src/main/kotlin/chapter4/context/switch/switch.kt

@ -2,6 +2,10 @@ package chapter4.context.switch
import kotlinx.coroutines.experimental.*
/**
* Switch context using `withContext` instead of the complete
* coroutine builder
*/
fun main(args: Array<String>) = runBlocking {
before()
after()

3
src/main/kotlin/chapter4/suspending/suspending.kt

@ -3,6 +3,9 @@ package chapter4.suspending
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.runBlocking
/**
* Basic suspending function.
*/
fun main(args: Array<String>) {
runBlocking {
greetDelayed(1000)

3
src/main/kotlin/chapter5/iterator/examples.kt

@ -2,6 +2,9 @@ package chapter5.iterator
import kotlin.coroutines.experimental.buildIterator
/**
* Examples of the usage of an iterator.
*/
fun main(args: Array<String>) {
yieldValues()
buildingIterators()

4
src/main/kotlin/chapter5/iterator/fibonacci/fibonacci_iterator.kt

@ -3,6 +3,10 @@ package chapter5.iterator.fibonacci
import kotlinx.coroutines.experimental.runBlocking
import kotlin.coroutines.experimental.buildIterator
/**
* Implementation of a Fibonacci sequence using
* an iterator.
*/
fun main(args: Array<String>) = runBlocking {
val fibonacci = buildIterator {
yield(1L)

6
src/main/kotlin/chapter5/producer/examples.kt

@ -6,7 +6,11 @@ import kotlinx.coroutines.experimental.runBlocking
fun main(args: Array<String>)= runBlocking {
creation()
//sample()
readingAllTheElements()
singleElement()
groupOfElements()
moreThanAvailable()
moreThanAvailableException()
}
suspend fun creation() {

3
src/main/kotlin/chapter5/producer/fibonacci/fibonacci.kt

@ -8,6 +8,9 @@ import kotlinx.coroutines.experimental.runBlocking
val context = newSingleThreadContext("myThread")
/**
* Fibonacci sequence using a producer.
*/
val fibonacci = produce(context) {
send(1L)
var current = 1L

3
src/main/kotlin/chapter5/sequence/examples.kt

@ -2,6 +2,9 @@ package chapter5.sequence
import kotlin.coroutines.experimental.buildSequence
/**
* Interacting with sequences.
*/
fun main(args: Array<String>) {
simpleSequences()
readingAllTheValues()

1
src/main/kotlin/chapter5/sequence/fibonacci/sequence.kt

@ -2,6 +2,7 @@ package chapter5.sequence.fibonacci
import kotlin.coroutines.experimental.buildSequence
// Fibonacci sequence using a sequence.
fun main(args: Array<String>) {
val fibonacci = buildSequence {

3
src/main/kotlin/chapter6/buffered/array/array.kt

@ -7,6 +7,9 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import kotlin.system.measureTimeMillis
/**
* Creating an ArrayChannel
*/
fun main(args: Array<String>) = runBlocking {
val time = measureTimeMillis {
val channel = Channel<Int>(4)

3
src/main/kotlin/chapter6/buffered/conflated/conflated.kt

@ -8,6 +8,9 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import kotlin.system.measureTimeMillis
/**
* Creating a Conflated channel.
*/
fun main(args: Array<String>) = runBlocking {
val time = measureTimeMillis {
val channel = Channel<Int>(Channel.CONFLATED)

3
src/main/kotlin/chapter6/buffered/linked/linked.kt

@ -6,6 +6,9 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import kotlin.system.measureTimeMillis
/**
* Creating a LinkedListChannel
*/
fun main(args: Array<String>) = runBlocking {
val time = measureTimeMillis {
val channel = Channel<Int>(Channel.UNLIMITED)

3
src/main/kotlin/chapter6/interaction/receive/receive.kt

@ -4,6 +4,9 @@ import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.channels.ClosedReceiveChannelException
import kotlinx.coroutines.experimental.runBlocking
/**
* Interaction with a ReceiveChannel
*/
fun main(args: Array<String>) = runBlocking {
isClosedForReceive()
receiveException()

3
src/main/kotlin/chapter6/interaction/send/send.kt

@ -5,6 +5,9 @@ import kotlinx.coroutines.experimental.channels.ClosedSendChannelException
import kotlinx.coroutines.experimental.channels.take
import kotlinx.coroutines.experimental.runBlocking
/**
* Interaction with a SendChannel
*/
fun main(args: Array<String>) = runBlocking {
isClosed()
isFull()

3
src/main/kotlin/chapter6/unbufffered/rendezvous/rendezvous.kt

@ -5,6 +5,9 @@ import kotlinx.coroutines.experimental.launch
import kotlinx.coroutines.experimental.runBlocking
import kotlin.system.measureTimeMillis
/**
* Creating a RendezvousChannel.
*/
fun main(args: Array<String>) = runBlocking {
val time = measureTimeMillis {
val channel = Channel<Int>()

3
src/main/kotlin/chapter7/actor/interaction/actor_samples.kt

@ -5,6 +5,9 @@ import kotlinx.coroutines.experimental.channels.actor
import kotlinx.coroutines.experimental.newFixedThreadPoolContext
import kotlinx.coroutines.experimental.runBlocking
/**
* Interacting with an actor.
*/
fun main(args: Array<String>) = runBlocking {
bufferedActor()
actorWithContext()

3
src/main/kotlin/chapter7/atomic/atomic.kt

@ -4,7 +4,8 @@ import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.runBlocking
import java.util.concurrent.atomic.AtomicInteger
// This method will print values lower than 2100 often
// This method will print the correct value `2100`
// because it's calculated using an AtomicInteger.
fun main(args: Array<String>) = runBlocking {
val workerA = asyncIncrement(2000)
val workerB = asyncIncrement(100)

3
src/main/kotlin/chapter7/atomicity/atomicity_violation.kt

@ -3,7 +3,8 @@ package chapter7.atomicity
import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.runBlocking
// This method will print values lower than 2100 often
// This method will print values lower than 2100 often,
// because of an atomicity violation on this implementation.
fun main(args: Array<String>) = runBlocking {
val workerA = asyncIncrement(2000)
val workerB = asyncIncrement(100)

2
src/main/kotlin/chapter7/confinement/thread_confinement.kt

@ -5,7 +5,7 @@ import kotlinx.coroutines.experimental.newSingleThreadContext
import kotlinx.coroutines.experimental.runBlocking
// This implementation executes all the increments in the same
//thread, so it will always increase up to 2100
// thread, so it will always increase up to 2100
fun main(args: Array<String>) = runBlocking {
val workerA = asyncIncrement(2000)
val workerB = asyncIncrement(100)

1
src/main/kotlin/chapter7/mutex/interaction/mutex_interaction.kt

@ -4,6 +4,7 @@ import kotlinx.coroutines.experimental.runBlocking
import kotlinx.coroutines.experimental.sync.Mutex
import kotlinx.coroutines.experimental.sync.withLock
// Interacting with a mutex.
fun main(args: Array<String>) = runBlocking {
useWithLock()
manualLock()

3
src/main/kotlin/chapter7/mutex/mutex.kt

@ -7,7 +7,8 @@ import kotlinx.coroutines.experimental.sync.withLock
// This implementation locks the code that modifies counter
// so that it's only executed by one coroutine at the time.
// This implementation will always increase counter to 2100
// This implementation will always increase counter to the
// correct value `2100`.
fun main(args: Array<String>) = runBlocking {
val workerA = asyncIncrement(2000)
val workerB = asyncIncrement(100)

7
src/main/kotlin/chapter7/volatile/volatile.kt

@ -1,8 +1,7 @@
package chapter7.volatile
// Example of the correct usage of the annotation.
class DataProcessor {
@Volatile
private var shutdownRequested = false
@ -15,8 +14,4 @@ class DataProcessor {
// process away
}
}
}
fun main(args: Array<String>) {
}

3
src/main/kotlin/chapter8/debugging.kt

@ -71,7 +71,8 @@ suspend fun breakpoints() {
val year = Calendar.getInstance().get(Calendar.YEAR)
withContext(ctx + CoroutineName("inner")) {
// TODO: Set a breakpoint in the line below
// TODO: Set a breakpoint in the line below and use the
// watch to see the current value
println(year)
}
}.await()

4
src/main/kotlin/chapter8/test_feature.kt

@ -5,6 +5,10 @@ import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.delay
import java.util.Calendar
/**
* This file defines code to be tested with
* functional tests. Please see the tests packages.
*/
data class User(
val name: String,
val age: Int,

3
src/test/kotlin/chapter8/SampleAppFT.kt

@ -7,6 +7,9 @@ import java.util.Calendar
import kotlin.test.Test
import kotlin.test.assertTrue
/**
* Functional tets for the chapter 8.
*/
class SampleAppFT {
@Test

Loading…
Cancel
Save