blob: 4eedfff994f6727c1e620b017f49b340e2a4a8cc [file] [log] [blame] [view]
Roman Elizarov7deefb82017-01-31 10:33:17 +03001# Guide to kotlinx.coroutines by example
2
3This is a short guide on core features of `kotlinx.coroutines` with a series of examples.
4
Roman Elizarov1293ccd2017-02-01 18:49:54 +03005## Table of contents
6
7* [Coroutine basics](#coroutine-basics)
8 * [Your first coroutine](#your-first-coroutine)
9 * [Bridging blocking and non-blocking worlds](#bridging-blocking-and-non-blocking-worlds)
10 * [Waiting for a job](#waiting-for-a-job)
11 * [Extract function refactoring](#extract-function-refactoring)
12 * [Coroutines ARE light-weight](#coroutines-are-light-weight)
13 * [Coroutines are like daemon threads](#coroutines-are-like-daemon-threads)
14* [Cancellation and timeouts](#cancellation-and-timeouts)
15 * [Cancelling coroutine execution](#cancelling-coroutine-execution)
16 * [Cancellation is cooperative](#cancellation-is-cooperative)
17 * [Making computation code cancellable](#making-computation-code-cancellable)
18 * [Closing resources with finally](#closing-resources-with-finally)
19 * [Run non-cancellable block](#run-non-cancellable-block)
20 * [Timeout](#timeout)
21* [Composing suspending functions](#composing-suspending-functions)
22 * [Sequential by default](#sequential-by-default)
23 * [Concurrent using deferred value](#concurrent-using-deferred-value)
24 * [Lazily deferred value](#lazily-deferred-value)
Roman Elizarovb3d55a52017-02-03 12:47:21 +030025
26<!--- KNIT kotlinx-coroutines-core/src/test/kotlin/guide/.*\.kt -->
Roman Elizarov1293ccd2017-02-01 18:49:54 +030027
Roman Elizarovb3d55a52017-02-03 12:47:21 +030028<!--- INCLUDE .*/example-([0-9]+)\.kt
29// This file was automatically generated from coroutines-guide.md by Knit tool. Do not edit.
30package guide.example$$1
31
32import kotlinx.coroutines.experimental.*
33-->
34
Roman Elizarov1293ccd2017-02-01 18:49:54 +030035## Coroutine basics
36
37This section covers basic coroutine concepts.
38
39### Your first coroutine
Roman Elizarov7deefb82017-01-31 10:33:17 +030040
41Run the following code:
42
43```kotlin
44fun main(args: Array<String>) {
45 launch(CommonPool) { // create new coroutine in common thread pool
46 delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
47 println("World!") // print after delay
48 }
49 println("Hello,") // main function continues while coroutine is delayed
50 Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
51}
52```
53
Roman Elizarovb3d55a52017-02-03 12:47:21 +030054> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-11.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +030055
56Run this code:
57
58```
59Hello,
60World!
61```
62
63Essentially, coroutines are light-weight threads. You can achieve the same result replacing
64`launch(CommonPool) { ... }` with `thread { ... }` and `delay(...)` with `Thread.sleep(...)`. Try it.
65
66If you start by replacing `launch(CommonPool)` by `thread`, the compiler produces the following error:
67
68```
69Error: Kotlin: Suspend functions are only allowed to be called from a coroutine or another suspend function
70```
71
72That is because `delay` is a special _suspending function_ that does not block a thread, but _suspends_
73coroutine and it can be only used from a coroutine.
74
Roman Elizarov1293ccd2017-02-01 18:49:54 +030075### Bridging blocking and non-blocking worlds
Roman Elizarov7deefb82017-01-31 10:33:17 +030076
77The first example mixes _non-blocking_ `delay(...)` and _blocking_ `Thread.sleep(...)` in the same
78code of `main` function. It is easy to get lost. Let's cleanly separate blocking and non-blocking
79worlds by using `runBlocking { ... }`:
80
81```kotlin
82fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
83 launch(CommonPool) { // create new coroutine in common thread pool
84 delay(1000L)
85 println("World!")
86 }
87 println("Hello,") // main coroutine continues while child is delayed
88 delay(2000L) // non-blocking delay for 2 seconds to keep JVM alive
89}
90```
91
Roman Elizarovb3d55a52017-02-03 12:47:21 +030092> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-12.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +030093
94The result is the same, but this code uses only non-blocking `delay`.
95
96`runBlocking { ... }` works as an adaptor that is used here to start the top-level main coroutine.
97The regular code outside of `runBlocking` _blocks_, until the coroutine inside `runBlocking` is active.
98
99This is also a way to write unit-tests for suspending functions:
100
101```kotlin
102class MyTest {
103 @Test
104 fun testMySuspendingFunction() = runBlocking<Unit> {
105 // here we can use suspending functions using any assertion style that we like
106 }
107}
108```
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300109
110<!--- CLEAR -->
Roman Elizarov7deefb82017-01-31 10:33:17 +0300111
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300112### Waiting for a job
Roman Elizarov7deefb82017-01-31 10:33:17 +0300113
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300114Delaying for a time while another coroutine is working is not a good approach. Let's explicitly
115wait (in a non-blocking way) until the background job coroutine that we have launched is complete:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300116
117```kotlin
118fun main(args: Array<String>) = runBlocking<Unit> {
119 val job = launch(CommonPool) { // create new coroutine and keep a reference to its Job
120 delay(1000L)
121 println("World!")
122 }
123 println("Hello,")
124 job.join() // wait until child coroutine completes
125}
126```
127
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300128> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-13.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300129
130Now the result is still the same, but the code of the main coroutine is not tied to the duration of
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300131the background job in any way. Much better.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300132
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300133### Extract function refactoring
Roman Elizarov7deefb82017-01-31 10:33:17 +0300134
135Let's extract the block of code inside `launch(CommonPool} { ... }` into a separate function. When you
136perform "Extract function" refactoring on this code you get a new function with `suspend` modifier.
137That is your first _suspending function_. Suspending functions can be used inside coroutines
138just like regular functions, but their additional feature is that they can, in turn,
139use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
140
141```kotlin
142fun main(args: Array<String>) = runBlocking<Unit> {
143 val job = launch(CommonPool) { doWorld() }
144 println("Hello,")
145 job.join()
146}
147
148// this is your first suspending function
149suspend fun doWorld() {
150 delay(1000L)
151 println("World!")
152}
153```
154
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300155> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-14.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300156
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300157### Coroutines ARE light-weight
Roman Elizarov7deefb82017-01-31 10:33:17 +0300158
159Run the following code:
160
161```kotlin
162fun main(args: Array<String>) = runBlocking<Unit> {
163 val jobs = List(100_000) { // create a lot of coroutines and list their jobs
164 launch(CommonPool) {
165 delay(1000L)
166 print(".")
167 }
168 }
169 jobs.forEach { it.join() } // wait for all jobs to complete
170}
171```
172
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300173> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-15.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300174
175It starts 100K coroutines and, after a second, each coroutine prints a dot.
176Now, try that with threads. What would happen? (Most likely your code will produce some sort of out-of-memory error)
177
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300178### Coroutines are like daemon threads
Roman Elizarov7deefb82017-01-31 10:33:17 +0300179
180The following code launches a long-running coroutine that prints "I'm sleeping" twice a second and then
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300181returns from the main function after some delay:
Roman Elizarov7deefb82017-01-31 10:33:17 +0300182
183```kotlin
184fun main(args: Array<String>) = runBlocking<Unit> {
185 launch(CommonPool) {
186 repeat(1000) { i ->
187 println("I'm sleeping $i ...")
188 delay(500L)
189 }
190 }
191 delay(1300L) // just quit after delay
192}
193```
194
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300195> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-16.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300196
197You can run and see that it prints three lines and terminates:
198
199```
200I'm sleeping 0 ...
201I'm sleeping 1 ...
202I'm sleeping 2 ...
203```
204
205Active coroutines do not keep the process alive. They are like daemon threads.
206
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300207## Cancellation and timeouts
208
209This section covers coroutine cancellation and timeouts.
210
211### Cancelling coroutine execution
Roman Elizarov7deefb82017-01-31 10:33:17 +0300212
213In small application the return from "main" method might sound like a good idea to get all coroutines
214implicitly terminated. In a larger, long-running application, you need finer-grained control.
215The `launch` function returns a `Job` that can be used to cancel running coroutine:
216
217```kotlin
218fun main(args: Array<String>) = runBlocking<Unit> {
219 val job = launch(CommonPool) {
220 repeat(1000) { i ->
221 println("I'm sleeping $i ...")
222 delay(500L)
223 }
224 }
225 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300226 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300227 job.cancel() // cancels the job
228 delay(1300L) // delay a bit to ensure it was cancelled indeed
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300229 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300230}
231```
232
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300233> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-21.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300234
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300235It produces the following output:
236
237```
238I'm sleeping 0 ...
239I'm sleeping 1 ...
240I'm sleeping 2 ...
241main: I'm tired of waiting!
242main: Now I can quit.
243```
244
245As soon as main invokes `job.cancel`, we don't see any output from the other coroutine because it was cancelled.
246
247### Cancellation is cooperative
Roman Elizarov7deefb82017-01-31 10:33:17 +0300248
Tair Rzayevaf734622017-02-01 22:30:16 +0200249Coroutine cancellation is _cooperative_. A coroutine code has to cooperate to be cancellable.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300250All the suspending functions in `kotlinx.coroutines` are _cancellable_. They check for cancellation of
251coroutine and throw `CancellationException` when cancelled. However, if a coroutine is working in
252a computation and does not check for cancellation, then it cannot be cancelled, like the following
253example shows:
254
255```kotlin
256fun main(args: Array<String>) = runBlocking<Unit> {
257 val job = launch(CommonPool) {
258 var nextPrintTime = 0L
259 var i = 0
260 while (true) { // computation loop
261 val currentTime = System.currentTimeMillis()
262 if (currentTime >= nextPrintTime) {
263 println("I'm sleeping ${i++} ...")
264 nextPrintTime = currentTime + 500L
265 }
266 }
267 }
268 delay(1300L) // delay a bit
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300269 println("main: I'm tired of waiting!")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300270 job.cancel() // cancels the job
271 delay(1300L) // delay a bit to see if it was cancelled....
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300272 println("main: Now I can quit.")
Roman Elizarov7deefb82017-01-31 10:33:17 +0300273}
274```
275
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300276> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-22.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300277
278Run it to see that it continues to print "I'm sleeping" even after cancellation.
279
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300280### Making computation code cancellable
Roman Elizarov7deefb82017-01-31 10:33:17 +0300281
282There are two approaches to making computation code cancellable. The first one is to periodically
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300283invoke a suspending function. There is a `yield` function that is a good choice for that purpose.
284The other one is to explicitly check the cancellation status. Let us try the later approach.
Roman Elizarov7deefb82017-01-31 10:33:17 +0300285
286Replace `while (true)` in the previous example with `while (isActive)` and rerun it.
287
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300288```kotlin
289fun main(args: Array<String>) = runBlocking<Unit> {
290 val job = launch(CommonPool) {
291 var nextPrintTime = 0L
292 var i = 0
293 while (isActive) { // cancellable computation loop
294 val currentTime = System.currentTimeMillis()
295 if (currentTime >= nextPrintTime) {
296 println("I'm sleeping ${i++} ...")
297 nextPrintTime = currentTime + 500L
298 }
299 }
300 }
301 delay(1300L) // delay a bit
302 println("main: I'm tired of waiting!")
303 job.cancel() // cancels the job
304 delay(1300L) // delay a bit to see if it was cancelled....
305 println("main: Now I can quit.")
306}
307```
308
309> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-23.kt)
Roman Elizarov7deefb82017-01-31 10:33:17 +0300310
311As you can see, now this loop can be cancelled. `isActive` is a property that is available inside
312the code of coroutines via `CoroutineScope` object.
313
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300314### Closing resources with finally
315
316Cancellable suspending functions throw `CancellationException` on cancellation which can be handled in
317all the usual way. For example, the `try {...} finally {...}` and Kotlin `use` function execute their
318finalization actions normally when coroutine is cancelled:
319
320```kotlin
321fun main(args: Array<String>) = runBlocking<Unit> {
322 val job = launch(CommonPool) {
323 try {
324 repeat(1000) { i ->
325 println("I'm sleeping $i ...")
326 delay(500L)
327 }
328 } finally {
329 println("I'm running finally")
330 }
331 }
332 delay(1300L) // delay a bit
333 println("main: I'm tired of waiting!")
334 job.cancel() // cancels the job
335 delay(1300L) // delay a bit to ensure it was cancelled indeed
336 println("main: Now I can quit.")
337}
338```
339
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300340> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-24.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300341
342The example above produces the following output:
343
344```
345I'm sleeping 0 ...
346I'm sleeping 1 ...
347I'm sleeping 2 ...
348main: I'm tired of waiting!
349I'm running finally
350main: Now I can quit.
351```
352
353### Run non-cancellable block
354
355Any attempt to use a suspending function in the `finally` block of the previous example will cause
356`CancellationException`, because the coroutine running this code is cancelled. Usually, this is not a
357problem, since all well-behaving closing operations (closing a file, cancelling a job, or closing any kind of a
358communication channel) are usually non-blocking and do not involve any suspending functions. However, in the
359rare case when you need to suspend in the cancelled coroutine you can wrap the corresponding code in
360`run(NonCancellable) {...}` as the following example shows:
361
362```kotlin
363fun main(args: Array<String>) = runBlocking<Unit> {
364 val job = launch(CommonPool) {
365 try {
366 repeat(1000) { i ->
367 println("I'm sleeping $i ...")
368 delay(500L)
369 }
370 } finally {
371 run(NonCancellable) {
372 println("I'm running finally")
373 delay(1000L)
374 println("And I've just delayed for 1 sec because I'm non-cancellable")
375 }
376 }
377 }
378 delay(1300L) // delay a bit
379 println("main: I'm tired of waiting!")
380 job.cancel() // cancels the job
381 delay(1300L) // delay a bit to ensure it was cancelled indeed
382 println("main: Now I can quit.")
383}
384```
385
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300386> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-25.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300387
388### Timeout
389
390The most obvious reason to cancel coroutine execution in practice,
391is because its execution time has exceeded some timeout.
392While you can manually track the reference to the corresponding `job` and launch a separate coroutine to cancel
393the tracked one after delay, there is a ready to use `withTimeout(...) {...}` function that does it.
394Look at the following example:
395
396```kotlin
397fun main(args: Array<String>) = runBlocking<Unit> {
398 withTimeout(1300L) {
399 repeat(1000) { i ->
400 println("I'm sleeping $i ...")
401 delay(500L)
402 }
403 }
404}
405```
406
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300407> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-26.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300408
409It produces the following output:
410
411```
412I'm sleeping 0 ...
413I'm sleeping 1 ...
414I'm sleeping 2 ...
415Exception in thread "main" java.util.concurrent.CancellationException: Timed out waiting for 1300 MILLISECONDS
416```
417
418We have not seen the `CancellationException` stack trace printed on the console before. That is because
419inside a cancelled coroutine `CancellationException` is a considered a normal reason for coroutine completion.
420However, in this example we have used `withTimeout` right inside the `main` function.
421
422Because cancellation is just an exception, all the resources will be closed in a usual way.
423You can wrap the code with timeout in `try {...} catch (e: CancellationException) {...}` block if
424you need to do some additional action specifically on timeout.
425
426## Composing suspending functions
427
428This section covers various approaches to composition of suspending functions.
429
430### Sequential by default
431
432Assume that we have two suspending functions defined elsewhere that do something useful like some kind of
433remote service call or computation. We'll just pretend they are useful, but each one will just actaully
434delay for a second for the purpose of this example:
435
436```kotlin
437suspend fun doSomethingUsefulOne(): Int {
438 delay(1000L) // pretend we are doing something useful here
439 return 13
440}
441
442suspend fun doSomethingUsefulTwo(): Int {
443 delay(1000L) // pretend we are doing something useful here, too
444 return 29
445}
446```
447
448What do we do if need to invoke them _sequentially_ -- first `doSomethingUsefulOne` _and then_
449`doSomethingUsefulTwo` and compute the sum of their results?
450In practise we do this if we use the results of the first function to make a decision on whether we need
451to invoke the second one or to decide on how to invoke it.
452
453We just use a normal sequential invocation, because the code in the coroutine, just like in the regular
454code, is _sequential_ by default. The following example demonstrates that by measuring the total
455time it takes to execute both suspending functions:
456
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300457<!--- INCLUDE .*/example-3[1-9].kt
458import kotlin.system.measureTimeMillis
459-->
460
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300461```kotlin
462fun main(args: Array<String>) = runBlocking<Unit> {
463 val time = measureTimeMillis {
464 val one = doSomethingUsefulOne()
465 val two = doSomethingUsefulTwo()
466 println("The answer is ${one + two}")
467 }
468 println("Completed in $time ms")
469}
470```
471
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300472> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-31.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300473
474It produces something like this:
475
476```
477The answer is 42
478Completed in 2017 ms
479```
480
481### Concurrent using deferred value
482
483What if there are no dependencies between invocation of `doSomethingUsefulOne` and `doSomethingUsefulTwo` and
484we want to get the answer faster, by doing both _concurrently_? This is where `defer` comes to helps.
485
486Conceptually, `defer` is just like `launch`. It starts a separate coroutine which is a light-weight thread
487that works concurrently with all the other coroutines. The difference is that `launch` returns a `Job` and
488does not carry any resulting value, while `defer` returns a `Deferred` -- a kind of light-weight non-blocking future
489that represent a promise to provide result later. You can use `.await()` on a deferred value to get its eventual result,
490but `Deferred` is also a `Job`, so you can cancel it if needed.
491
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300492<!--- INCLUDE .*/example-3[2-9].kt
493
494suspend fun doSomethingUsefulOne(): Int {
495 delay(1000L) // pretend we are doing something useful here
496 return 13
497}
498
499suspend fun doSomethingUsefulTwo(): Int {
500 delay(1000L) // pretend we are doing something useful here, too
501 return 29
502}
503-->
504
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300505```kotlin
506fun main(args: Array<String>) = runBlocking<Unit> {
507 val time = measureTimeMillis {
508 val one = defer(CommonPool) { doSomethingUsefulOne() }
509 val two = defer(CommonPool) { doSomethingUsefulTwo() }
510 println("The answer is ${one.await() + two.await()}")
511 }
512 println("Completed in $time ms")
513}
514```
515
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300516> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-32.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300517
518It produces something like this:
519
520```
521The answer is 42
522Completed in 1017 ms
523```
524
525This is twice as fast, because we have concurrent execution of two coroutines.
526Note, that concurrency with coroutines is always explicit.
527
528### Lazily deferred value
529
530There is a lazy alternative to `defer` that is called `lazyDefer`. It is just like `defer`, but it
531starts coroutine only when its result is needed by some `await` or if a special `start` function
532is invoked. Run the following example:
533
534```kotlin
535fun main(args: Array<String>) = runBlocking<Unit> {
536 val time = measureTimeMillis {
537 val one = lazyDefer(CommonPool) { doSomethingUsefulOne() }
538 val two = lazyDefer(CommonPool) { doSomethingUsefulTwo() }
539 println("The answer is ${one.await() + two.await()}")
540 }
541 println("Completed in $time ms")
542}
543```
544
Roman Elizarovb3d55a52017-02-03 12:47:21 +0300545> You can get full code [here](kotlinx-coroutines-core/src/test/kotlin/guide/example-33.kt)
Roman Elizarov1293ccd2017-02-01 18:49:54 +0300546
547It produces something like this:
548
549```
550The answer is 42
551Completed in 2017 ms
552```
553
554So, we are back to two sequential execution, because we _first_ await for the `one` deferred, _and then_ await
555for the second one. It is not the intended use-case for `lazyDefer`. It is designed as a replacement for
556the standard `lazy` function in cases when computation of the value involve suspending functions.
557
558
Roman Elizarov7deefb82017-01-31 10:33:17 +0300559