Structured concurrency implementation:
  * Introducing async, launch, produce, actor and broadcast extensions on CoroutineScope
  * Deprecate top-level coroutine builders
  * Introducing currentScope and coroutineScope for manipulation with CoroutineScope interface
  * Introducing CoroutineScope factories
  * Introducing extension CoroutineScope.isActive

Fixes #410
diff --git a/common/kotlinx-coroutines-core-common/test/AsyncTest.kt b/common/kotlinx-coroutines-core-common/test/AsyncTest.kt
index de7e004..0496904 100644
--- a/common/kotlinx-coroutines-core-common/test/AsyncTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/AsyncTest.kt
@@ -6,7 +6,6 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
 class AsyncTest : TestBase() {
@@ -221,5 +220,22 @@
         finish(2)
     }
 
+    @Test
+    fun testOverriddenParent() = runTest {
+        val parent = Job()
+        val deferred = async(parent, CoroutineStart.ATOMIC) {
+            expect(2)
+            delay(Long.MAX_VALUE)
+        }
+
+        parent.cancel()
+        try {
+            expect(1)
+            deferred.await()
+        } catch (e: JobCancellationException) {
+            finish(3)
+        }
+    }
+
     private class TestException : Exception()
 }
diff --git a/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt b/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt
new file mode 100644
index 0000000..22652f2
--- /dev/null
+++ b/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.coroutines.experimental
+
+import kotlin.test.*
+
+class CoroutineScopeTest : TestBase() {
+
+    @Test
+    fun testScope() = runTest {
+        suspend fun callJobScoped() = coroutineScope {
+            expect(2)
+
+            launch {
+                expect(4)
+            }
+
+            launch {
+                expect(5)
+
+                launch {
+                    expect(7)
+                }
+
+                expect(6)
+
+            }
+
+            expect(3)
+            42
+        }
+
+
+        expect(1)
+        val result = callJobScoped()
+        assertEquals(42, result)
+        yield() // Check we're not cancelled
+        finish(8)
+    }
+
+    @Test
+    fun testScopeCancelledFromWithin() = runTest {
+        expect(1)
+        suspend fun callJobScoped() = coroutineScope {
+
+            launch {
+                expect(2)
+                delay(Long.MAX_VALUE)
+            }
+
+            launch {
+                expect(3)
+                throw IllegalArgumentException()
+            }
+        }
+
+        try {
+            callJobScoped()
+            expectUnreached()
+        } catch (e: IllegalArgumentException) {
+            expect(4)
+        }
+
+        yield() // Check we're not cancelled
+        finish(5)
+    }
+
+    @Test
+    fun testScopeBlockThrows() = runTest {
+        expect(1)
+        suspend fun callJobScoped(): Unit = coroutineScope {
+
+            launch {
+                expect(2)
+                delay(Long.MAX_VALUE)
+            }
+
+            yield() // let launch sleep
+            throw NotImplementedError()
+        }
+
+        try {
+            callJobScoped()
+            expectUnreached()
+        } catch (e: NotImplementedError) {
+            expect(3)
+        }
+
+        yield() // Check we're not cancelled
+        finish(4)
+    }
+
+    @Test
+    fun testOuterJobIsCancelled() = runTest {
+
+        suspend fun callJobScoped() = coroutineScope {
+
+            launch {
+                expect(3)
+                try {
+                    delay(Long.MAX_VALUE)
+                } finally {
+                    expect(4)
+                }
+            }
+
+            expect(2)
+            delay(Long.MAX_VALUE)
+            42
+        }
+
+
+        val outerJob = launch(coroutineContext.minusKey(Job)) {
+            expect(1)
+            try {
+                callJobScoped()
+                expectUnreached()
+            } catch (e: JobCancellationException) {
+                expect(5)
+                assertNull(e.cause)
+            }
+        }
+
+        repeat(3) { yield() } // let everything to start properly
+        outerJob.cancel()
+        outerJob.join()
+        finish(6)
+    }
+
+    @Test
+    @Suppress("UNREACHABLE_CODE")
+    fun testDocumentationExample() = runTest {
+        suspend fun loadData() = coroutineScope {
+            expect(1)
+            val data = async {
+                try {
+                    delay(Long.MAX_VALUE)
+                } finally {
+                    expect(3)
+                }
+            }
+
+            yield()
+
+            // UI updater
+            withContext(coroutineContext) {
+                expect(2)
+                throw AssertionError()
+                data.await() // Actually unreached
+                expectUnreached()
+            }
+        }
+
+
+        try {
+            loadData()
+            expectUnreached()
+        } catch (e: AssertionError) {
+            finish(4)
+        }
+    }
+}
diff --git a/common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt b/common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt
index 70d89ca..283a6d4 100644
--- a/common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt
@@ -6,7 +6,6 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
 class CoroutinesTest : TestBase() {
diff --git a/common/kotlinx-coroutines-core-common/test/CurrentScopeTest.kt b/common/kotlinx-coroutines-core-common/test/CurrentScopeTest.kt
new file mode 100644
index 0000000..db17064
--- /dev/null
+++ b/common/kotlinx-coroutines-core-common/test/CurrentScopeTest.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED") // KT-21913
+
+package kotlinx.coroutines.experimental
+
+import kotlin.test.*
+
+class CurrentScopeTest : TestBase() {
+
+    @Test
+    fun testScope() = runTest {
+        suspend fun callJobScoped() = currentScope {
+            launch {
+                finish(3)
+            }
+        }
+
+
+        expect(1)
+        callJobScoped()
+        expect(2)
+    }
+
+    @Test
+    fun testNestedScope() = runTest {
+        suspend fun callJobScoped() = currentScope {
+            launch {
+                expect(2)
+            }
+        }
+
+        expect(1)
+        coroutineScope {
+            callJobScoped()
+        }
+
+        finish(3)
+    }
+
+    @Test
+    fun testThrowException() = runTest(expected = { it is IndexOutOfBoundsException }) {
+        suspend fun callJobScoped() = currentScope {
+            launch {
+                finish(3)
+                throw IndexOutOfBoundsException()
+            }
+        }
+
+        expect(1)
+        callJobScoped()
+        expect(2)
+    }
+}
diff --git a/common/kotlinx-coroutines-core-common/test/JobTest.kt b/common/kotlinx-coroutines-core-common/test/JobTest.kt
index 1beccb8..f83a893 100644
--- a/common/kotlinx-coroutines-core-common/test/JobTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/JobTest.kt
@@ -4,7 +4,6 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
 class JobTest : TestBase() {
@@ -175,4 +174,18 @@
         job.cancelAndJoin()
         finish(4)
     }
+
+    @Test
+    fun testOverriddenParent() = runTest {
+        val parent = Job()
+        val deferred = launch(parent, CoroutineStart.ATOMIC) {
+            expect(2)
+            delay(Long.MAX_VALUE)
+        }
+
+        parent.cancel()
+        expect(1)
+        deferred.join()
+        finish(3)
+    }
 }
diff --git a/common/kotlinx-coroutines-core-common/test/WithContextTest.kt b/common/kotlinx-coroutines-core-common/test/WithContextTest.kt
index 9e40c1b..bed85d9 100644
--- a/common/kotlinx-coroutines-core-common/test/WithContextTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/WithContextTest.kt
@@ -145,8 +145,7 @@
 
         try {
             withContext(job + wrapperDispatcher(coroutineContext), CoroutineStart.ATOMIC) {
-                require(isActive)
-                // but start atomically
+                require(!isActive) // but it had still started, because atomically
                 expect(2)
                 yield() // but will cancel here
                 expectUnreached()
@@ -165,7 +164,7 @@
         val job = Job()
         job.cancel() // try to cancel before it has a chance to run
         withContext(job + wrapperDispatcher(coroutineContext), CoroutineStart.UNDISPATCHED) { // but start atomically
-            require(isActive)
+            require(!isActive) // but it had still started, because undispatched
             finish(2)
             yield() // but will cancel here
             expectUnreached()
diff --git a/common/kotlinx-coroutines-core-common/test/channels/BroadcastTest.kt b/common/kotlinx-coroutines-core-common/test/channels/BroadcastTest.kt
index 0f0d059..74bdb44 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/BroadcastTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/BroadcastTest.kt
@@ -12,7 +12,7 @@
     @Test
     fun testBroadcastBasic() = runTest {
         expect(1)
-        val b = broadcast(coroutineContext) {
+        val b = broadcast {
             expect(4)
             send(1) // goes to receiver
             expect(5)
diff --git a/common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt b/common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt
index 70252a7..40b4e5b 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt
@@ -12,7 +12,7 @@
 
     @Test
     fun testBasic() = runTest {
-        val c = produce(coroutineContext) {
+        val c = produce {
             expect(2)
             send(1)
             expect(3)
@@ -30,7 +30,7 @@
 
     @Test
     fun testCancelWithoutCause() = runTest {
-        val c = produce(coroutineContext) {
+        val c = produce {
             expect(2)
             send(1)
             expect(3)
@@ -54,7 +54,7 @@
 
     @Test
     fun testCancelWithCause() = runTest {
-        val c = produce(coroutineContext) {
+        val c = produce {
             expect(2)
             send(1)
             expect(3)
@@ -92,7 +92,7 @@
         cancelOnCompletion(coroutineContext)
     }
 
-    private suspend fun cancelOnCompletion(coroutineContext: CoroutineContext) {
+    private suspend fun cancelOnCompletion(coroutineContext: CoroutineContext) = currentScope {
         val source = Channel<Int>()
         expect(1)
         val produced = produce<Int>(coroutineContext, onCompletion = source.consumes()) {