Merge branch 'develop' into handle-exception-fix
diff --git a/binary-compatibility-validator/build.gradle b/binary-compatibility-validator/build.gradle
index 16539d6..785848c 100644
--- a/binary-compatibility-validator/build.gradle
+++ b/binary-compatibility-validator/build.gradle
@@ -20,9 +20,8 @@
 
     testArtifacts project(':kotlinx-coroutines-guava')
     testArtifacts project(':kotlinx-coroutines-jdk8')
-    testArtifacts project(':kotlinx-coroutines-nio')
-    testArtifacts project(':kotlinx-coroutines-quasar')
     testArtifacts project(':kotlinx-coroutines-slf4j')
+    testArtifacts project(path: ':kotlinx-coroutines-play-services', configuration: 'default')
 
     testArtifacts project(':kotlinx-coroutines-android')
     testArtifacts project(':kotlinx-coroutines-javafx')
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-android.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-android.txt
index d8ed275..9f3922d 100644
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-android.txt
+++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-android.txt
@@ -1,8 +1,3 @@
-public final class kotlinx/coroutines/experimental/android/AndroidExceptionPreHandler : kotlin/coroutines/experimental/AbstractCoroutineContextElement, kotlinx/coroutines/experimental/CoroutineExceptionHandler {
-	public fun <init> ()V
-	public fun handleException (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Throwable;)V
-}
-
 public final class kotlinx/coroutines/experimental/android/HandlerContext : kotlinx/coroutines/experimental/android/HandlerDispatcher, kotlinx/coroutines/experimental/Delay {
 	public fun <init> (Landroid/os/Handler;Ljava/lang/String;)V
 	public synthetic fun <init> (Landroid/os/Handler;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
@@ -12,9 +7,9 @@
 	public fun getImmediate ()Lkotlinx/coroutines/experimental/android/HandlerContext;
 	public synthetic fun getImmediate ()Lkotlinx/coroutines/experimental/android/HandlerDispatcher;
 	public fun hashCode ()I
-	public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
 	public fun isDispatchNeeded (Lkotlin/coroutines/experimental/CoroutineContext;)Z
-	public fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public fun scheduleResumeAfterDelay (JLkotlinx/coroutines/experimental/CancellableContinuation;)V
 	public fun toString ()Ljava/lang/String;
 }
 
@@ -24,14 +19,17 @@
 }
 
 public abstract class kotlinx/coroutines/experimental/android/HandlerDispatcher : kotlinx/coroutines/experimental/CoroutineDispatcher, kotlinx/coroutines/experimental/Delay {
-	public fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public synthetic fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public fun delay (JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public abstract fun getImmediate ()Lkotlinx/coroutines/experimental/android/HandlerDispatcher;
-	public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
 }
 
 public final class kotlinx/coroutines/experimental/android/HandlerDispatcherKt {
-	public static final fun asCoroutineDispatcher (Landroid/os/Handler;)Lkotlinx/coroutines/experimental/android/HandlerDispatcher;
 	public static final fun awaitFrame (Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static final fun from (Landroid/os/Handler;)Lkotlinx/coroutines/experimental/android/HandlerDispatcher;
 	public static final fun getMain (Lkotlinx/coroutines/experimental/Dispatchers;)Lkotlinx/coroutines/experimental/android/HandlerDispatcher;
 }
 
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt
index 816a6a2..b1c6765 100644
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt
+++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-core.txt
@@ -23,22 +23,27 @@
 }
 
 public final class kotlinx/coroutines/experimental/BuildersKt {
+	public static final fun async (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/Deferred;
+	public static synthetic fun async$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/Deferred;
 	public static final fun launch (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/Job;
 	public static final synthetic fun launch (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/Job;
 	public static final fun launch (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/Job;
 	public static final synthetic fun launch (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/Job;
 	public static final fun launch (Lkotlin/coroutines/experimental/CoroutineContext;ZLkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/Job;
 	public static final fun launch (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/Job;
+	public static final fun launch (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/Job;
 	public static synthetic fun launch$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/Job;
 	public static synthetic fun launch$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/Job;
 	public static synthetic fun launch$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/Job;
 	public static synthetic fun launch$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/Job;
 	public static synthetic fun launch$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/Job;
+	public static synthetic fun launch$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/Job;
 	public static final synthetic fun run (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static final fun run (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static synthetic fun run$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
 	public static final fun runBlocking (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object;
 	public static synthetic fun runBlocking$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/lang/Object;
+	public static final fun withContext (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static final synthetic fun withContext (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static final fun withContext (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static synthetic fun withContext$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
@@ -136,10 +141,6 @@
 }
 
 public final class kotlinx/coroutines/experimental/CoroutineContextKt {
-	public static final field DEBUG_PROPERTY_NAME Ljava/lang/String;
-	public static final field DEBUG_PROPERTY_VALUE_AUTO Ljava/lang/String;
-	public static final field DEBUG_PROPERTY_VALUE_OFF Ljava/lang/String;
-	public static final field DEBUG_PROPERTY_VALUE_ON Ljava/lang/String;
 	public static final fun getDefaultDispatcher ()Lkotlinx/coroutines/experimental/CoroutineDispatcher;
 	public static final fun getIO ()Lkotlinx/coroutines/experimental/CoroutineDispatcher;
 	public static final fun newCoroutineContext (Lkotlin/coroutines/experimental/CoroutineContext;)Lkotlin/coroutines/experimental/CoroutineContext;
@@ -152,7 +153,7 @@
 	public fun <init> ()V
 	public abstract fun dispatch (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Runnable;)V
 	public fun dispatchYield (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Runnable;)V
-	public fun interceptContinuation (Lkotlin/coroutines/experimental/Continuation;)Lkotlin/coroutines/experimental/Continuation;
+	public final fun interceptContinuation (Lkotlin/coroutines/experimental/Continuation;)Lkotlin/coroutines/experimental/Continuation;
 	public fun isDispatchNeeded (Lkotlin/coroutines/experimental/CoroutineContext;)Z
 	public final fun plus (Lkotlinx/coroutines/experimental/CoroutineDispatcher;)Lkotlinx/coroutines/experimental/CoroutineDispatcher;
 	public fun toString ()Ljava/lang/String;
@@ -224,6 +225,13 @@
 	public static fun values ()[Lkotlinx/coroutines/experimental/CoroutineStart;
 }
 
+public final class kotlinx/coroutines/experimental/DebugKt {
+	public static final field DEBUG_PROPERTY_NAME Ljava/lang/String;
+	public static final field DEBUG_PROPERTY_VALUE_AUTO Ljava/lang/String;
+	public static final field DEBUG_PROPERTY_VALUE_OFF Ljava/lang/String;
+	public static final field DEBUG_PROPERTY_VALUE_ON Ljava/lang/String;
+}
+
 public abstract interface class kotlinx/coroutines/experimental/Deferred : kotlinx/coroutines/experimental/Job {
 	public abstract fun await (Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public abstract fun getCompleted ()Ljava/lang/Object;
@@ -259,20 +267,27 @@
 }
 
 public abstract interface class kotlinx/coroutines/experimental/Delay {
-	public abstract fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public abstract fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
-	public abstract fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public abstract synthetic fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public abstract fun delay (JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public abstract fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public abstract synthetic fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public abstract synthetic fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public abstract fun scheduleResumeAfterDelay (JLkotlinx/coroutines/experimental/CancellableContinuation;)V
 }
 
 public final class kotlinx/coroutines/experimental/Delay$DefaultImpls {
-	public static fun delay (Lkotlinx/coroutines/experimental/Delay;JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static synthetic fun delay (Lkotlinx/coroutines/experimental/Delay;JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static fun delay (Lkotlinx/coroutines/experimental/Delay;JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static synthetic fun delay$default (Lkotlinx/coroutines/experimental/Delay;JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-	public static fun invokeOnTimeout (Lkotlinx/coroutines/experimental/Delay;JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public static fun invokeOnTimeout (Lkotlinx/coroutines/experimental/Delay;JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public static synthetic fun invokeOnTimeout (Lkotlinx/coroutines/experimental/Delay;JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public static synthetic fun scheduleResumeAfterDelay (Lkotlinx/coroutines/experimental/Delay;JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
 }
 
 public final class kotlinx/coroutines/experimental/DelayKt {
-	public static final fun delay (ILkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static final synthetic fun delay (ILkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static final fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static final fun delay (JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static synthetic fun delay$default (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
 }
 
@@ -338,37 +353,48 @@
 
 public abstract class kotlinx/coroutines/experimental/ExecutorCoroutineDispatcher : kotlinx/coroutines/experimental/CloseableCoroutineDispatcher, java/io/Closeable {
 	public fun <init> ()V
+	public abstract fun close ()V
 	public abstract fun getExecutor ()Ljava/util/concurrent/Executor;
 }
 
 public abstract class kotlinx/coroutines/experimental/ExecutorCoroutineDispatcherBase : kotlinx/coroutines/experimental/ExecutorCoroutineDispatcher, kotlinx/coroutines/experimental/Delay {
 	public fun <init> ()V
 	public fun close ()V
-	public fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public synthetic fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public fun delay (JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public fun dispatch (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Runnable;)V
 	public fun equals (Ljava/lang/Object;)Z
 	public fun hashCode ()I
-	public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
-	public fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public fun scheduleResumeAfterDelay (JLkotlinx/coroutines/experimental/CancellableContinuation;)V
 	public fun toString ()Ljava/lang/String;
 }
 
 public final class kotlinx/coroutines/experimental/ExecutorsKt {
-	public static final fun asCoroutineDispatcher (Ljava/util/concurrent/Executor;)Lkotlinx/coroutines/experimental/CoroutineDispatcher;
 	public static final synthetic fun asCoroutineDispatcher (Ljava/util/concurrent/ExecutorService;)Lkotlinx/coroutines/experimental/CloseableCoroutineDispatcher;
 	public static final fun asCoroutineDispatcher (Ljava/util/concurrent/ExecutorService;)Lkotlinx/coroutines/experimental/ExecutorCoroutineDispatcher;
+	public static final fun from (Ljava/util/concurrent/Executor;)Lkotlinx/coroutines/experimental/CoroutineDispatcher;
 	public static final fun toCoroutineDispatcher (Ljava/util/concurrent/Executor;)Lkotlinx/coroutines/experimental/CoroutineDispatcher;
 }
 
+public abstract interface annotation class kotlinx/coroutines/experimental/ExperimentalCoroutinesApi : java/lang/annotation/Annotation {
+}
+
 public final class kotlinx/coroutines/experimental/GlobalScope : kotlinx/coroutines/experimental/CoroutineScope {
 	public static final field INSTANCE Lkotlinx/coroutines/experimental/GlobalScope;
 	public fun getCoroutineContext ()Lkotlin/coroutines/experimental/CoroutineContext;
 	public synthetic fun isActive ()Z
 }
 
+public abstract interface annotation class kotlinx/coroutines/experimental/InternalCoroutinesApi : java/lang/annotation/Annotation {
+}
+
 public abstract interface class kotlinx/coroutines/experimental/Job : kotlin/coroutines/experimental/CoroutineContext$Element {
 	public static final field Key Lkotlinx/coroutines/experimental/Job$Key;
 	public abstract fun attachChild (Lkotlinx/coroutines/experimental/ChildJob;)Lkotlinx/coroutines/experimental/ChildHandle;
+	public abstract fun cancel ()Z
 	public abstract fun cancel (Ljava/lang/Throwable;)Z
 	public abstract synthetic fun cancelChildren (Ljava/lang/Throwable;)V
 	public abstract fun getCancellationException ()Ljava/util/concurrent/CancellationException;
@@ -414,11 +440,14 @@
 }
 
 public final class kotlinx/coroutines/experimental/JobKt {
+	public static final fun DisposableHandle (Lkotlin/jvm/functions/Function0;)Lkotlinx/coroutines/experimental/DisposableHandle;
 	public static final fun Job (Lkotlinx/coroutines/experimental/Job;)Lkotlinx/coroutines/experimental/Job;
 	public static synthetic fun Job$default (Lkotlinx/coroutines/experimental/Job;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/Job;
+	public static final fun cancel (Lkotlin/coroutines/experimental/CoroutineContext;)Z
 	public static final fun cancel (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Throwable;)Z
 	public static synthetic fun cancel$default (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Throwable;ILjava/lang/Object;)Z
 	public static final fun cancelAndJoin (Lkotlinx/coroutines/experimental/Job;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static final fun cancelChildren (Lkotlin/coroutines/experimental/CoroutineContext;)V
 	public static final fun cancelChildren (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Throwable;)V
 	public static final fun cancelChildren (Lkotlinx/coroutines/experimental/Job;Ljava/lang/Throwable;)V
 	public static synthetic fun cancelChildren$default (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Throwable;ILjava/lang/Object;)V
@@ -440,6 +469,7 @@
 public final class kotlinx/coroutines/experimental/NonCancellable : kotlin/coroutines/experimental/AbstractCoroutineContextElement, kotlinx/coroutines/experimental/Job {
 	public static final field INSTANCE Lkotlinx/coroutines/experimental/NonCancellable;
 	public fun attachChild (Lkotlinx/coroutines/experimental/ChildJob;)Lkotlinx/coroutines/experimental/ChildHandle;
+	public fun cancel ()Z
 	public fun cancel (Ljava/lang/Throwable;)Z
 	public synthetic fun cancelChildren (Ljava/lang/Throwable;)V
 	public fun getCancellationException ()Ljava/util/concurrent/CancellationException;
@@ -465,15 +495,18 @@
 	public fun toString ()Ljava/lang/String;
 }
 
+public abstract interface annotation class kotlinx/coroutines/experimental/ObsoleteCoroutinesApi : java/lang/annotation/Annotation {
+}
+
 public final class kotlinx/coroutines/experimental/RunnableKt {
 	public static final fun Runnable (Lkotlin/jvm/functions/Function0;)Ljava/lang/Runnable;
 }
 
 public final class kotlinx/coroutines/experimental/ScheduledKt {
-	public static final fun withTimeout (ILkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static final synthetic fun withTimeout (ILkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static final fun withTimeout (JLjava/util/concurrent/TimeUnit;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static synthetic fun withTimeout$default (JLjava/util/concurrent/TimeUnit;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-	public static final fun withTimeoutOrNull (ILkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static final synthetic fun withTimeoutOrNull (ILkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static final fun withTimeoutOrNull (JLjava/util/concurrent/TimeUnit;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static synthetic fun withTimeoutOrNull$default (JLjava/util/concurrent/TimeUnit;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
 }
@@ -502,10 +535,12 @@
 }
 
 public final class kotlinx/coroutines/experimental/ThreadPoolDispatcherKt {
-	public static final fun newFixedThreadPoolContext (ILjava/lang/String;)Lkotlinx/coroutines/experimental/ThreadPoolDispatcher;
+	public static final fun newFixedThreadPoolContext (ILjava/lang/String;)Lkotlinx/coroutines/experimental/ExecutorCoroutineDispatcher;
+	public static final synthetic fun newFixedThreadPoolContext (ILjava/lang/String;)Lkotlinx/coroutines/experimental/ThreadPoolDispatcher;
 	public static final fun newFixedThreadPoolContext (ILjava/lang/String;Lkotlinx/coroutines/experimental/Job;)Lkotlin/coroutines/experimental/CoroutineContext;
 	public static synthetic fun newFixedThreadPoolContext$default (ILjava/lang/String;Lkotlinx/coroutines/experimental/Job;ILjava/lang/Object;)Lkotlin/coroutines/experimental/CoroutineContext;
-	public static final fun newSingleThreadContext (Ljava/lang/String;)Lkotlinx/coroutines/experimental/ThreadPoolDispatcher;
+	public static final fun newSingleThreadContext (Ljava/lang/String;)Lkotlinx/coroutines/experimental/ExecutorCoroutineDispatcher;
+	public static final synthetic fun newSingleThreadContext (Ljava/lang/String;)Lkotlinx/coroutines/experimental/ThreadPoolDispatcher;
 	public static final fun newSingleThreadContext (Ljava/lang/String;Lkotlinx/coroutines/experimental/Job;)Lkotlin/coroutines/experimental/CoroutineContext;
 	public static synthetic fun newSingleThreadContext$default (Ljava/lang/String;Lkotlinx/coroutines/experimental/Job;ILjava/lang/Object;)Lkotlin/coroutines/experimental/CoroutineContext;
 }
@@ -514,6 +549,11 @@
 	public fun <init> (Ljava/lang/String;)V
 }
 
+public final class kotlinx/coroutines/experimental/TimeoutKt {
+	public static final fun withTimeout (JLkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static final fun withTimeoutOrNull (JLkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+}
+
 public final class kotlinx/coroutines/experimental/Unconfined : kotlinx/coroutines/experimental/CoroutineDispatcher {
 	public static final field INSTANCE Lkotlinx/coroutines/experimental/Unconfined;
 	public fun dispatch (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Runnable;)V
@@ -527,6 +567,7 @@
 
 public abstract class kotlinx/coroutines/experimental/channels/AbstractChannel : kotlinx/coroutines/experimental/channels/AbstractSendChannel, kotlinx/coroutines/experimental/channels/Channel {
 	public fun <init> ()V
+	public fun cancel ()Z
 	public fun cancel (Ljava/lang/Throwable;)Z
 	protected fun cleanupSendQueueOnCancel ()V
 	protected final fun describeTryPoll ()Lkotlinx/coroutines/experimental/channels/AbstractChannel$TryPollDesc;
@@ -677,11 +718,13 @@
 public abstract interface class kotlinx/coroutines/experimental/channels/Channel : kotlinx/coroutines/experimental/channels/ReceiveChannel, kotlinx/coroutines/experimental/channels/SendChannel {
 	public static final field CONFLATED I
 	public static final field Factory Lkotlinx/coroutines/experimental/channels/Channel$Factory;
+	public static final field RENDEZVOUS I
 	public static final field UNLIMITED I
 }
 
 public final class kotlinx/coroutines/experimental/channels/Channel$Factory {
 	public static final field CONFLATED I
+	public static final field RENDEZVOUS I
 	public static final field UNLIMITED I
 	public final synthetic fun invoke (I)Lkotlinx/coroutines/experimental/channels/Channel;
 	public static synthetic fun invoke$default (Lkotlinx/coroutines/experimental/channels/Channel$Factory;IILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/Channel;
@@ -693,8 +736,9 @@
 }
 
 public final class kotlinx/coroutines/experimental/channels/ChannelKt {
-	public static final fun Channel ()Lkotlinx/coroutines/experimental/channels/Channel;
+	public static final synthetic fun Channel ()Lkotlinx/coroutines/experimental/channels/Channel;
 	public static final fun Channel (I)Lkotlinx/coroutines/experimental/channels/Channel;
+	public static synthetic fun Channel$default (IILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/Channel;
 }
 
 public final class kotlinx/coroutines/experimental/channels/ChannelsKt {
@@ -899,11 +943,13 @@
 	public static final fun produce (Lkotlin/coroutines/experimental/CoroutineContext;ILkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 	public static final synthetic fun produce (Lkotlin/coroutines/experimental/CoroutineContext;ILkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 	public static final fun produce (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;ILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
+	public static final fun produce (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;ILkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 	public static synthetic fun produce$default (Lkotlin/coroutines/experimental/CoroutineContext;ILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 	public static synthetic fun produce$default (Lkotlin/coroutines/experimental/CoroutineContext;ILkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/ProducerJob;
 	public static synthetic fun produce$default (Lkotlin/coroutines/experimental/CoroutineContext;ILkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 	public static synthetic fun produce$default (Lkotlin/coroutines/experimental/CoroutineContext;ILkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 	public static synthetic fun produce$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;ILkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
+	public static synthetic fun produce$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;ILkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 }
 
 public abstract interface class kotlinx/coroutines/experimental/channels/ProducerJob : kotlinx/coroutines/experimental/Job, kotlinx/coroutines/experimental/channels/ReceiveChannel {
@@ -928,6 +974,7 @@
 }
 
 public abstract interface class kotlinx/coroutines/experimental/channels/ReceiveChannel {
+	public abstract fun cancel ()Z
 	public abstract fun cancel (Ljava/lang/Throwable;)Z
 	public abstract fun getOnReceive ()Lkotlinx/coroutines/experimental/selects/SelectClause1;
 	public abstract fun getOnReceiveOrNull ()Lkotlinx/coroutines/experimental/selects/SelectClause1;
@@ -997,7 +1044,9 @@
 }
 
 public final class kotlinx/coroutines/experimental/channels/TickerChannelsKt {
+	public static final fun ticker (JJLkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/channels/TickerMode;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 	public static final fun ticker (JLjava/util/concurrent/TimeUnit;JLkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/channels/TickerMode;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
+	public static synthetic fun ticker$default (JJLkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/channels/TickerMode;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 	public static synthetic fun ticker$default (JLjava/util/concurrent/TimeUnit;JLkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/channels/TickerMode;ILjava/lang/Object;)Lkotlinx/coroutines/experimental/channels/ReceiveChannel;
 }
 
@@ -1028,10 +1077,12 @@
 	public abstract fun invoke (Lkotlinx/coroutines/experimental/selects/SelectClause2;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
 	public abstract fun invoke (Lkotlinx/coroutines/experimental/selects/SelectClause2;Lkotlin/jvm/functions/Function2;)V
 	public abstract fun onTimeout (JLjava/util/concurrent/TimeUnit;Lkotlin/jvm/functions/Function1;)V
+	public abstract fun onTimeout (JLkotlin/jvm/functions/Function1;)V
 }
 
 public final class kotlinx/coroutines/experimental/selects/SelectBuilder$DefaultImpls {
 	public static fun invoke (Lkotlinx/coroutines/experimental/selects/SelectBuilder;Lkotlinx/coroutines/experimental/selects/SelectClause2;Lkotlin/jvm/functions/Function2;)V
+	public static fun onTimeout (Lkotlinx/coroutines/experimental/selects/SelectBuilder;JLjava/util/concurrent/TimeUnit;Lkotlin/jvm/functions/Function1;)V
 	public static synthetic fun onTimeout$default (Lkotlinx/coroutines/experimental/selects/SelectBuilder;JLjava/util/concurrent/TimeUnit;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
 }
 
@@ -1048,6 +1099,7 @@
 	public fun invoke (Lkotlinx/coroutines/experimental/selects/SelectClause2;Lkotlin/jvm/functions/Function2;)V
 	public fun isSelected ()Z
 	public fun onTimeout (JLjava/util/concurrent/TimeUnit;Lkotlin/jvm/functions/Function1;)V
+	public fun onTimeout (JLkotlin/jvm/functions/Function1;)V
 	public fun performAtomicIfNotSelected (Lkotlinx/coroutines/experimental/internal/AtomicDesc;)Ljava/lang/Object;
 	public fun performAtomicTrySelect (Lkotlinx/coroutines/experimental/internal/AtomicDesc;)Ljava/lang/Object;
 	public fun resume (Ljava/lang/Object;)V
@@ -1089,10 +1141,7 @@
 	public fun invoke (Lkotlinx/coroutines/experimental/selects/SelectClause2;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
 	public fun invoke (Lkotlinx/coroutines/experimental/selects/SelectClause2;Lkotlin/jvm/functions/Function2;)V
 	public fun onTimeout (JLjava/util/concurrent/TimeUnit;Lkotlin/jvm/functions/Function1;)V
-}
-
-public final class kotlinx/coroutines/experimental/selects/WhileSelectKt {
-	public static final fun whileSelect (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public fun onTimeout (JLkotlin/jvm/functions/Function1;)V
 }
 
 public abstract interface class kotlinx/coroutines/experimental/sync/Mutex {
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-guava.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-guava.txt
index efb5ce2..49f14a7 100644
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-guava.txt
+++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-guava.txt
@@ -6,10 +6,12 @@
 	public static final fun future (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/google/common/util/concurrent/ListenableFuture;
 	public static final synthetic fun future (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function2;)Lcom/google/common/util/concurrent/ListenableFuture;
 	public static final fun future (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/google/common/util/concurrent/ListenableFuture;
+	public static final fun future (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;)Lcom/google/common/util/concurrent/ListenableFuture;
 	public static synthetic fun future$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/google/common/util/concurrent/ListenableFuture;
 	public static synthetic fun future$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/google/common/util/concurrent/ListenableFuture;
 	public static synthetic fun future$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/google/common/util/concurrent/ListenableFuture;
 	public static synthetic fun future$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/google/common/util/concurrent/ListenableFuture;
 	public static synthetic fun future$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/google/common/util/concurrent/ListenableFuture;
+	public static synthetic fun future$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/google/common/util/concurrent/ListenableFuture;
 }
 
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-javafx.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-javafx.txt
index 06955a4..69c98bb 100644
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-javafx.txt
+++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-javafx.txt
@@ -1,15 +1,18 @@
-public final class kotlinx/coroutines/experimental/javafx/JavaFx : kotlinx/coroutines/experimental/javafx/JavaFxDispatcher, kotlinx/coroutines/experimental/Delay {
+public final class kotlinx/coroutines/experimental/javafx/JavaFx : kotlinx/coroutines/experimental/javafx/JavaFxDispatcher {
 	public static final field INSTANCE Lkotlinx/coroutines/experimental/javafx/JavaFx;
 	public final fun awaitPulse (Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public fun dispatch (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Runnable;)V
-	public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
-	public fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public fun scheduleResumeAfterDelay (JLkotlinx/coroutines/experimental/CancellableContinuation;)V
 	public fun toString ()Ljava/lang/String;
 }
 
 public abstract class kotlinx/coroutines/experimental/javafx/JavaFxDispatcher : kotlinx/coroutines/experimental/CoroutineDispatcher, kotlinx/coroutines/experimental/Delay {
-	public fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public fun delay (JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
 }
 
 public final class kotlinx/coroutines/experimental/javafx/JavaFxDispatcherKt {
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-jdk8.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-jdk8.txt
index 94fb357..6019c23 100644
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-jdk8.txt
+++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-jdk8.txt
@@ -16,18 +16,21 @@
 	public static final fun future (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/util/concurrent/CompletableFuture;
 	public static final synthetic fun future (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function2;)Ljava/util/concurrent/CompletableFuture;
 	public static final fun future (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/util/concurrent/CompletableFuture;
+	public static final fun future (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;)Ljava/util/concurrent/CompletableFuture;
 	public static synthetic fun future$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/concurrent/CompletableFuture;
 	public static synthetic fun future$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/util/concurrent/CompletableFuture;
 	public static synthetic fun future$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/util/concurrent/CompletableFuture;
 	public static synthetic fun future$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/util/concurrent/CompletableFuture;
 	public static synthetic fun future$default (Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlinx/coroutines/experimental/Job;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/util/concurrent/CompletableFuture;
 	public static synthetic fun future$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/util/concurrent/CompletableFuture;
+	public static synthetic fun future$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlinx/coroutines/experimental/CoroutineStart;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/util/concurrent/CompletableFuture;
 	public static final fun toCompletableFuture (Lkotlinx/coroutines/experimental/Deferred;)Ljava/util/concurrent/CompletableFuture;
 }
 
 public final class kotlinx/coroutines/experimental/time/TimeKt {
 	public static final fun delay (Ljava/time/Duration;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public static final fun onTimeout (Lkotlinx/coroutines/experimental/selects/SelectBuilder;Ljava/time/Duration;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public static final fun onTimeout (Lkotlinx/coroutines/experimental/selects/SelectBuilder;Ljava/time/Duration;Lkotlin/jvm/functions/Function1;)V
+	public static final synthetic fun onTimeout (Lkotlinx/coroutines/experimental/selects/SelectBuilder;Ljava/time/Duration;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static final synthetic fun withTimeout (Ljava/time/Duration;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static final fun withTimeout (Ljava/time/Duration;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public static final synthetic fun withTimeoutOrNull (Ljava/time/Duration;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-nio.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-nio.txt
deleted file mode 100644
index 1db7145..0000000
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-nio.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-public final class kotlinx/coroutines/experimental/nio/NioKt {
-	public static final fun aAccept (Ljava/nio/channels/AsynchronousServerSocketChannel;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public static final fun aConnect (Ljava/nio/channels/AsynchronousSocketChannel;Ljava/net/SocketAddress;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public static final fun aLock (Ljava/nio/channels/AsynchronousFileChannel;JJZLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public static final fun aLock (Ljava/nio/channels/AsynchronousFileChannel;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public static final fun aRead (Ljava/nio/channels/AsynchronousFileChannel;Ljava/nio/ByteBuffer;JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public static final fun aRead (Ljava/nio/channels/AsynchronousSocketChannel;Ljava/nio/ByteBuffer;JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public static synthetic fun aRead$default (Ljava/nio/channels/AsynchronousSocketChannel;Ljava/nio/ByteBuffer;JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-	public static final fun aWrite (Ljava/nio/channels/AsynchronousFileChannel;Ljava/nio/ByteBuffer;JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public static final fun aWrite (Ljava/nio/channels/AsynchronousSocketChannel;Ljava/nio/ByteBuffer;JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public static synthetic fun aWrite$default (Ljava/nio/channels/AsynchronousSocketChannel;Ljava/nio/ByteBuffer;JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
-}
-
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-play-services.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-play-services.txt
new file mode 100644
index 0000000..18f3c51
--- /dev/null
+++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-play-services.txt
@@ -0,0 +1,6 @@
+public final class kotlinx/coroutines/experimental/tasks/TasksKt {
+	public static final fun asDeferred (Lcom/google/android/gms/tasks/Task;)Lkotlinx/coroutines/experimental/Deferred;
+	public static final fun asTask (Lkotlinx/coroutines/experimental/Deferred;)Lcom/google/android/gms/tasks/Task;
+	public static final fun await (Lcom/google/android/gms/tasks/Task;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+}
+
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-quasar.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-quasar.txt
deleted file mode 100644
index b5fe0e3..0000000
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-quasar.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-public final class kotlinx/coroutines/experimental/quasar/KotlinSuspendableClassifier : co/paralleluniverse/fibers/instrument/SuspendableClassifier {
-	public fun <init> ()V
-	public fun isSuspendable (Lco/paralleluniverse/fibers/instrument/MethodDatabase;Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Lco/paralleluniverse/fibers/instrument/MethodDatabase$SuspendableType;
-}
-
-public final class kotlinx/coroutines/experimental/quasar/QuasarKt {
-	public static final fun runFiberBlocking (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
-	public static final fun runSuspendable (Lco/paralleluniverse/strands/SuspendableCallable;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-}
-
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactor.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactor.txt
index 1dbc637..83b8dc8 100644
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactor.txt
+++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-reactor.txt
@@ -1,10 +1,12 @@
 public final class kotlinx/coroutines/experimental/reactor/ConvertKt {
 	public static final fun asFlux (Lkotlinx/coroutines/experimental/channels/ReceiveChannel;Lkotlin/coroutines/experimental/CoroutineContext;)Lreactor/core/publisher/Flux;
 	public static synthetic fun asFlux$default (Lkotlinx/coroutines/experimental/channels/ReceiveChannel;Lkotlin/coroutines/experimental/CoroutineContext;ILjava/lang/Object;)Lreactor/core/publisher/Flux;
+	public static final fun asMono (Lkotlinx/coroutines/experimental/Deferred;)Lreactor/core/publisher/Mono;
 	public static final fun asMono (Lkotlinx/coroutines/experimental/Deferred;Lkotlin/coroutines/experimental/CoroutineContext;)Lreactor/core/publisher/Mono;
+	public static final fun asMono (Lkotlinx/coroutines/experimental/Job;)Lreactor/core/publisher/Mono;
 	public static final fun asMono (Lkotlinx/coroutines/experimental/Job;Lkotlin/coroutines/experimental/CoroutineContext;)Lreactor/core/publisher/Mono;
-	public static synthetic fun asMono$default (Lkotlinx/coroutines/experimental/Deferred;Lkotlin/coroutines/experimental/CoroutineContext;ILjava/lang/Object;)Lreactor/core/publisher/Mono;
-	public static synthetic fun asMono$default (Lkotlinx/coroutines/experimental/Job;Lkotlin/coroutines/experimental/CoroutineContext;ILjava/lang/Object;)Lreactor/core/publisher/Mono;
+	public static final synthetic fun asMono$default (Lkotlinx/coroutines/experimental/Deferred;Lkotlin/coroutines/experimental/CoroutineContext;ILjava/lang/Object;)Lreactor/core/publisher/Mono;
+	public static final synthetic fun asMono$default (Lkotlinx/coroutines/experimental/Job;Lkotlin/coroutines/experimental/CoroutineContext;ILjava/lang/Object;)Lreactor/core/publisher/Mono;
 }
 
 public final class kotlinx/coroutines/experimental/reactor/FluxKt {
@@ -22,14 +24,18 @@
 	public static synthetic fun mono$default (Lkotlinx/coroutines/experimental/CoroutineScope;Lkotlin/coroutines/experimental/CoroutineContext;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lreactor/core/publisher/Mono;
 }
 
-public class kotlinx/coroutines/experimental/reactor/SchedulerCoroutineDispatcher : kotlinx/coroutines/experimental/CoroutineDispatcher, kotlinx/coroutines/experimental/Delay {
+public final class kotlinx/coroutines/experimental/reactor/SchedulerCoroutineDispatcher : kotlinx/coroutines/experimental/CoroutineDispatcher, kotlinx/coroutines/experimental/Delay {
 	public fun <init> (Lreactor/core/scheduler/Scheduler;)V
-	public fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public synthetic fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public fun delay (JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public fun dispatch (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Runnable;)V
 	public fun equals (Ljava/lang/Object;)Z
+	public final fun getScheduler ()Lreactor/core/scheduler/Scheduler;
 	public fun hashCode ()I
-	public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
-	public fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public fun scheduleResumeAfterDelay (JLkotlinx/coroutines/experimental/CancellableContinuation;)V
 	public fun toString ()Ljava/lang/String;
 }
 
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-rx2.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-rx2.txt
index c4dca9b..237212b 100644
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-rx2.txt
+++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-rx2.txt
@@ -69,12 +69,16 @@
 
 public final class kotlinx/coroutines/experimental/rx2/SchedulerCoroutineDispatcher : kotlinx/coroutines/experimental/CoroutineDispatcher, kotlinx/coroutines/experimental/Delay {
 	public fun <init> (Lio/reactivex/Scheduler;)V
-	public fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public synthetic fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public fun delay (JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
 	public fun dispatch (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Runnable;)V
 	public fun equals (Ljava/lang/Object;)Z
+	public final fun getScheduler ()Lio/reactivex/Scheduler;
 	public fun hashCode ()I
-	public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
-	public fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public fun scheduleResumeAfterDelay (JLkotlinx/coroutines/experimental/CancellableContinuation;)V
 	public fun toString ()Ljava/lang/String;
 }
 
diff --git a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-swing.txt b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-swing.txt
index 1a7f44d..dcb7f3b 100644
--- a/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-swing.txt
+++ b/binary-compatibility-validator/reference-public-api/kotlinx-coroutines-swing.txt
@@ -1,14 +1,17 @@
-public final class kotlinx/coroutines/experimental/swing/Swing : kotlinx/coroutines/experimental/swing/SwingDispatcher, kotlinx/coroutines/experimental/Delay {
+public final class kotlinx/coroutines/experimental/swing/Swing : kotlinx/coroutines/experimental/swing/SwingDispatcher {
 	public static final field INSTANCE Lkotlinx/coroutines/experimental/swing/Swing;
 	public fun dispatch (Lkotlin/coroutines/experimental/CoroutineContext;Ljava/lang/Runnable;)V
-	public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
-	public fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
+	public fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public fun scheduleResumeAfterDelay (JLkotlinx/coroutines/experimental/CancellableContinuation;)V
 	public fun toString ()Ljava/lang/String;
 }
 
 public abstract class kotlinx/coroutines/experimental/swing/SwingDispatcher : kotlinx/coroutines/experimental/CoroutineDispatcher, kotlinx/coroutines/experimental/Delay {
-	public fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
-	public fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun delay (JLjava/util/concurrent/TimeUnit;Lkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public fun delay (JLkotlin/coroutines/experimental/Continuation;)Ljava/lang/Object;
+	public fun invokeOnTimeout (JLjava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun invokeOnTimeout (JLjava/util/concurrent/TimeUnit;Ljava/lang/Runnable;)Lkotlinx/coroutines/experimental/DisposableHandle;
+	public synthetic fun scheduleResumeAfterDelay (JLjava/util/concurrent/TimeUnit;Lkotlinx/coroutines/experimental/CancellableContinuation;)V
 }
 
 public final class kotlinx/coroutines/experimental/swing/SwingDispatcherKt {
diff --git a/common/kotlinx-coroutines-core-common/src/AbstractCoroutine.kt b/common/kotlinx-coroutines-core-common/src/AbstractCoroutine.kt
index 3f1f4b1..020af59 100644
--- a/common/kotlinx-coroutines-core-common/src/AbstractCoroutine.kt
+++ b/common/kotlinx-coroutines-core-common/src/AbstractCoroutine.kt
@@ -28,8 +28,11 @@
  * @param parentContext context of the parent coroutine.
  * @param active when `true` (by default) coroutine is created in _active_ state, when `false` in _new_ state.
  *               See [Job] for details.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
 @Suppress("EXPOSED_SUPER_CLASS")
+@InternalCoroutinesApi
 public abstract class AbstractCoroutine<in T>(
     /**
      * Context of the parent coroutine.
diff --git a/common/kotlinx-coroutines-core-common/src/Annotations.kt b/common/kotlinx-coroutines-core-common/src/Annotations.kt
new file mode 100644
index 0000000..7aae365
--- /dev/null
+++ b/common/kotlinx-coroutines-core-common/src/Annotations.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.coroutines.experimental
+
+/**
+ * Marks declarations that are still **experimental** in coroutines API, which means that the design of the
+ * corresponding declarations has open issues which may (or may not) lead to their changes in the future.
+ * Roughly speaking, there is a chance that those declarations will be deprecated in the near future or
+ * the semantics of their behavior may change in some way that may break some code.
+ */
+@MustBeDocumented
+@Retention(value = AnnotationRetention.SOURCE)
+// todo: Experimental WARNING
+public annotation class ExperimentalCoroutinesApi
+
+/**
+ * Marks declarations that are **obsolete** in coroutines API, which means that the design of the corresponding
+ * declarations has serious known flaws and they will be redesigned in the future.
+ * Roughly speaking, these declarations will be deprecated in the future but there is no replacement for them yet,
+ * so they cannot be deprecated right away.
+ */
+@MustBeDocumented
+@Retention(value = AnnotationRetention.SOURCE)
+// todo: Experimental WARNING
+public annotation class ObsoleteCoroutinesApi
+
+/**
+ * Marks declarations that are **internal** in coroutines API, which means that should not be used outside of
+ * `kotlinx.coroutines`, because their signatures and semantics will be changing between release without any
+ * warnings and without providing any migration aids.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
+ */
+@Retention(value = AnnotationRetention.SOURCE)
+// todo: Experimental ERROR
+public annotation class InternalCoroutinesApi
diff --git a/common/kotlinx-coroutines-core-common/src/Builders.common.kt b/common/kotlinx-coroutines-core-common/src/Builders.common.kt
index d2e761e..3a0e981 100644
--- a/common/kotlinx-coroutines-core-common/src/Builders.common.kt
+++ b/common/kotlinx-coroutines-core-common/src/Builders.common.kt
@@ -9,10 +9,11 @@
 
 import kotlinx.coroutines.experimental.internal.*
 import kotlinx.coroutines.experimental.intrinsics.*
+import kotlinx.coroutines.experimental.selects.*
 import kotlin.coroutines.experimental.*
 import kotlin.coroutines.experimental.intrinsics.*
 
-// --------------- basic coroutine builders ---------------
+// --------------- launch ---------------
 
 /**
  * Launches new coroutine without blocking current thread and returns a reference to the coroutine as a [Job].
@@ -37,25 +38,34 @@
  *
  * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
- * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code which will be invoked in the context of the provided scope.
  **/
 public fun CoroutineScope.launch(
     context: CoroutineContext = EmptyCoroutineContext,
     start: CoroutineStart = CoroutineStart.DEFAULT,
-    onCompletion: CompletionHandler? = null,
     block: suspend CoroutineScope.() -> Unit
 ): Job {
     val newContext = newCoroutineContext(context)
     val coroutine = if (start.isLazy)
         LazyStandaloneCoroutine(newContext, block) else
         StandaloneCoroutine(newContext, active = true)
-    if (onCompletion != null) coroutine.invokeOnCompletion(handler = onCompletion)
     coroutine.start(start, coroutine, block)
     return coroutine
 }
 
 /**
+ * @suppress **Deprecated**: onCompletion parameter is deprecated.
+ */
+@Deprecated("onCompletion parameter is deprecated")
+public fun CoroutineScope.launch(
+    context: CoroutineContext = EmptyCoroutineContext,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
+    onCompletion: CompletionHandler? = null,
+    block: suspend CoroutineScope.() -> Unit
+): Job =
+    launch(context, start, block).also { if (onCompletion != null) it.invokeOnCompletion(onCompletion) }
+
+/**
  * Launches new coroutine without blocking current thread and returns a reference to the coroutine as a [Job].
  * @suppress **Deprecated** Use [CoroutineScope.launch] instead.
  */
@@ -107,6 +117,63 @@
 ): Job =
     GlobalScope.launch(context, start, block = block)
 
+// --------------- async ---------------
+
+/**
+ * Creates new coroutine and returns its future result as an implementation of [Deferred].
+ * The running coroutine is cancelled when the resulting deferred is [cancelled][Job.cancel].
+ *
+ * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [context] argument.
+ * If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used.
+ * The parent job is inherited from a [CoroutineScope] as well, but it can also be overridden
+ * with corresponding [coroutineContext] element.
+ *
+ * By default, the coroutine is immediately scheduled for execution.
+ * Other options can be specified via `start` parameter. See [CoroutineStart] for details.
+ * An optional [start] parameter can be set to [CoroutineStart.LAZY] to start coroutine _lazily_. In this case,,
+ * the resulting [Deferred] is created in _new_ state. It can be explicitly started with [start][Job.start]
+ * function and will be started implicitly on the first invocation of [join][Job.join], [await][Deferred.await] or [awaitAll].
+ *
+ * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
+ * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
+ * @param block the coroutine code.
+ */
+public fun <T> CoroutineScope.async(
+    context: CoroutineContext = EmptyCoroutineContext,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
+    block: suspend CoroutineScope.() -> T
+): Deferred<T> {
+    val newContext = newCoroutineContext(context)
+    val coroutine = if (start.isLazy)
+        LazyDeferredCoroutine(newContext, block) else
+        DeferredCoroutine<T>(newContext, active = true)
+    coroutine.start(start, coroutine, block)
+    return coroutine
+}
+
+@Suppress("UNCHECKED_CAST")
+private open class DeferredCoroutine<T>(
+    parentContext: CoroutineContext,
+    active: Boolean
+) : AbstractCoroutine<T>(parentContext, active), Deferred<T>, SelectClause1<T> {
+    override fun getCompleted(): T = getCompletedInternal() as T
+    override suspend fun await(): T = awaitInternal() as T
+    override val onAwait: SelectClause1<T> get() = this
+    override fun <R> registerSelectClause1(select: SelectInstance<R>, block: suspend (T) -> R) =
+        registerSelectClause1Internal(select, block)
+}
+
+private class LazyDeferredCoroutine<T>(
+    parentContext: CoroutineContext,
+    private val block: suspend CoroutineScope.() -> T
+) : DeferredCoroutine<T>(parentContext, active = false) {
+    override fun onStart() {
+        block.startCoroutineCancellable(this, this)
+    }
+}
+
+// --------------- withContext ---------------
+
 /**
  * @suppress **Deprecated**: Use `start = CoroutineStart.XXX` parameter
  */
@@ -122,17 +189,24 @@
  * This function immediately applies dispatcher from the new context, shifting execution of the block into the
  * different thread inside the block, and back when it completes.
  * The specified [context] is added onto the current coroutine context for the execution of the block.
- *
- * An optional `start` parameter is used only if the specified `context` uses a different [CoroutineDispatcher] than
- * a current one, otherwise it is ignored.
- * By default, the coroutine is immediately scheduled for execution and can be cancelled
- * while it is waiting to be executed and it can be cancelled while the result is scheduled
- * to be processed by the invoker context.
- * Other options can be specified via `start` parameter. See [CoroutineStart] for details.
- * A value of [CoroutineStart.LAZY] is not supported and produces [IllegalArgumentException].
  */
 public suspend fun <T> withContext(
     context: CoroutineContext,
+    block: suspend CoroutineScope.() -> T
+): T =
+    // todo: optimize fast-path to work without allocation (when there is a already a coroutine implementing scope)
+    withContextImpl(context, start = CoroutineStart.DEFAULT) {
+        currentScope {
+            block()
+        }
+    }
+
+/**
+ * @suppress **Deprecated**: start parameter is deprecated, no replacement.
+ */
+@Deprecated("start parameter is deprecated, no replacement")
+public suspend fun <T> withContext(
+    context: CoroutineContext,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend CoroutineScope.() -> T
 ): T =
diff --git a/common/kotlinx-coroutines-core-common/src/CancellableContinuation.kt b/common/kotlinx-coroutines-core-common/src/CancellableContinuation.kt
index 9ee6ca1..deef82c 100644
--- a/common/kotlinx-coroutines-core-common/src/CancellableContinuation.kt
+++ b/common/kotlinx-coroutines-core-common/src/CancellableContinuation.kt
@@ -73,6 +73,7 @@
      *
      * @suppress **This is unstable API and it is subject to change.**
      */
+    @InternalCoroutinesApi
     public fun tryResume(value: T, idempotent: Any? = null): Any?
 
     /**
@@ -82,6 +83,7 @@
      *
      * @suppress **This is unstable API and it is subject to change.**
      */
+    @InternalCoroutinesApi
     public fun tryResumeWithException(exception: Throwable): Any?
 
     /**
@@ -89,12 +91,14 @@
      *
      * @suppress **This is unstable API and it is subject to change.**
      */
+    @InternalCoroutinesApi
     public fun completeResume(token: Any)
 
     /**
      * Makes this continuation cancellable. Use it with `holdCancellability` optional parameter to
      * [suspendCancellableCoroutine] function. It throws [IllegalStateException] if invoked more than once.
      */
+    @InternalCoroutinesApi
     public fun initCancellability()
 
     /**
@@ -146,7 +150,10 @@
      * [dispatch][CoroutineDispatcher.dispatch] function of the [CoroutineDispatcher] in the [context].
      * This function is designed to be used only by the [CoroutineDispatcher] implementations themselves.
      * **It should not be used in general code**.
+     *
+     * **Note: This function is experimental.** Its signature general code may be changed in the future.
      */
+    @ExperimentalCoroutinesApi
     public fun CoroutineDispatcher.resumeUndispatched(value: T)
 
     /**
@@ -154,30 +161,37 @@
      * [dispatch][CoroutineDispatcher.dispatch] function of the [CoroutineDispatcher] in the [context].
      * This function is designed to be used only by the [CoroutineDispatcher] implementations themselves.
      * **It should not be used in general code**.
+     *
+     * **Note: This function is experimental.** Its signature general code may be changed in the future.
      */
+    @ExperimentalCoroutinesApi
     public fun CoroutineDispatcher.resumeUndispatchedWithException(exception: Throwable)
 }
 
 /**
  * Suspends coroutine similar to [suspendCoroutine], but provide an implementation of [CancellableContinuation] to
  * the [block]. This function throws [CancellationException] if the coroutine is cancelled or completed while suspended.
- *
- * If [holdCancellability] optional parameter is `true`, then the coroutine is suspended, but it is not
- * cancellable until [CancellableContinuation.initCancellability] is invoked.
- *
- * See [suspendAtomicCancellableCoroutine] for suspending functions that need *atomic cancellation*.
  */
 public suspend inline fun <T> suspendCancellableCoroutine(
-    holdCancellability: Boolean = false,
     crossinline block: (CancellableContinuation<T>) -> Unit
 ): T =
     suspendCoroutineUninterceptedOrReturn { uCont ->
         val cancellable = CancellableContinuationImpl(uCont.intercepted(), resumeMode = MODE_CANCELLABLE)
-        if (!holdCancellability) cancellable.initCancellability()
+        cancellable.initCancellability()
         block(cancellable)
         cancellable.getResult()
     }
 
+@Suppress("DeprecatedCallableAddReplaceWith")
+@Deprecated(
+    level = DeprecationLevel.ERROR,
+    message = "holdCancellability is no longer supported, no replacement"
+)
+public suspend inline fun <T> suspendCancellableCoroutine(
+    holdCancellability: Boolean = false,
+    crossinline block: (CancellableContinuation<T>) -> Unit
+): T = error("holdCancellability is no longer supported, no replacement")
+
 /**
  * Suspends coroutine similar to [suspendCancellableCoroutine], but with *atomic cancellation*.
  *
@@ -185,7 +199,10 @@
  * As a side-effect of atomic cancellation, a thread-bound coroutine (to some UI thread, for example) may
  * continue to execute even after it was cancelled from the same thread in the case when the continuation
  * was already resumed and was posted for execution to the thread's queue.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public suspend inline fun <T> suspendAtomicCancellableCoroutine(
     holdCancellability: Boolean = false,
     crossinline block: (CancellableContinuation<T>) -> Unit
@@ -241,7 +258,10 @@
  * ```
  * invokeOnCancellation { handle.dispose() }
  * ```
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun CancellableContinuation<*>.disposeOnCancellation(handle: DisposableHandle) =
     invokeOnCancellation(handler = DisposeOnCancel(handle).asHandler)
 
diff --git a/common/kotlinx-coroutines-core-common/src/CompletedExceptionally.kt b/common/kotlinx-coroutines-core-common/src/CompletedExceptionally.kt
index 80e3afe..da3825c 100644
--- a/common/kotlinx-coroutines-core-common/src/CompletedExceptionally.kt
+++ b/common/kotlinx-coroutines-core-common/src/CompletedExceptionally.kt
@@ -13,6 +13,8 @@
  * **Note: This class cannot be used outside of internal coroutines framework**.
  * **Note: cannot be internal and renamed until we get rid of MutableDelegateContinuation in IO**
  *
+ * @param cause the exceptional completion cause. It's either original exceptional cause
+ *        or artificial [CancellationException] if no cause was provided
  * @suppress **This is unstable API and it is subject to change.**
  */
 // todo: rename to Cancelled
@@ -28,8 +30,8 @@
  * **Note: This class cannot be used outside of internal coroutines framework**.
  *
  * @param continuation the continuation that was cancelled.
- * @param cause the exceptional completion cause. If `cause` is null, then a [JobCancellationException]
- *        if created on first get from [exception] property.
+ * @param cause the exceptional completion cause. If `cause` is null, then a [CancellationException]
+ *        if created on first access to [exception] property.
  * @suppress **This is unstable API and it is subject to change.**
  */
 public class CancelledContinuation(
diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineContext.common.kt b/common/kotlinx-coroutines-core-common/src/CoroutineContext.common.kt
index 5eed6c1..5545599 100644
--- a/common/kotlinx-coroutines-core-common/src/CoroutineContext.common.kt
+++ b/common/kotlinx-coroutines-core-common/src/CoroutineContext.common.kt
@@ -8,6 +8,10 @@
 
 public expect fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext
 
+/**
+ * The default [CoroutineDispatcher] that is used by all standard builders.
+ * @suppress **Deprecated**: Use [Dispatchers.Default].
+ */
 @Suppress("PropertyName")
 @Deprecated(
     message = "Use Dispatchers.Default",
diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineDispatcher.kt b/common/kotlinx-coroutines-core-common/src/CoroutineDispatcher.kt
index 296f8f8..2940f8d 100644
--- a/common/kotlinx-coroutines-core-common/src/CoroutineDispatcher.kt
+++ b/common/kotlinx-coroutines-core-common/src/CoroutineDispatcher.kt
@@ -59,7 +59,10 @@
      * However, coroutine builders like [launch][CoroutineScope.launch] and [async][CoroutineScope.async] accept an optional [CoroutineStart]
      * parameter that allows one to optionally choose C#-style [CoroutineStart.UNDISPATCHED] behaviour
      * whenever it is needed for efficiency.
+     *
+     * **Note: This is an experimental api.** Execution semantics of coroutines may change in the future when this function returns `false`.
      */
+    @ExperimentalCoroutinesApi
     public open fun isDispatchNeeded(context: CoroutineContext): Boolean = true
 
     /**
@@ -74,13 +77,16 @@
      *
      * **Implementation note** though yield marker may be passed as a part of [context], this
      * is a separate method for performance reasons
+     *
+     * @suppress **This an internal API and should not be used from general code.**
      */
+    @InternalCoroutinesApi
     public open fun dispatchYield(context: CoroutineContext, block: Runnable) = dispatch(context, block)
 
     /**
      * Returns continuation that wraps the original [continuation], thus intercepting all resumptions.
      */
-    public override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
+    public final override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> =
         DispatchedContinuation(this, continuation)
 
     /**
diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineExceptionHandler.kt b/common/kotlinx-coroutines-core-common/src/CoroutineExceptionHandler.kt
index 2a8cc53..2450039 100644
--- a/common/kotlinx-coroutines-core-common/src/CoroutineExceptionHandler.kt
+++ b/common/kotlinx-coroutines-core-common/src/CoroutineExceptionHandler.kt
@@ -23,6 +23,7 @@
  * todo: Deprecate/hide this function.
  */
 @JvmOverloads // binary compatibility
+@InternalCoroutinesApi
 public fun handleCoroutineException(context: CoroutineContext, exception: Throwable, caller: Job? = null) {
     // Ignore CancellationException (they are normal ways to terminate a coroutine)
     if (exception is CancellationException) return // nothing to do
@@ -75,11 +76,9 @@
  *   (because that is the supposed mechanism to cancel the running coroutine)
  * * Otherwise:
  *     * if there is a [Job] in the context, then [Job.cancel] is invoked;
- *     * all instances of [CoroutineExceptionHandler] found via [ServiceLoader] are invoked;
- *     * and current thread's [Thread.uncaughtExceptionHandler] is invoked.
- *
- * See [handleCoroutineException].
- */
+ *     * Otherwise, all instances of [CoroutineExceptionHandler] found via [ServiceLoader]
+ *     * and current thread's [Thread.uncaughtExceptionHandler] are invoked.
+ **/
 public interface CoroutineExceptionHandler : CoroutineContext.Element {
     /**
      * Key for [CoroutineExceptionHandler] instance in the coroutine context.
@@ -88,7 +87,7 @@
 
     /**
      * Handles uncaught [exception] in the given [context]. It is invoked
-     * if coroutine has an uncaught exception. See [handleCoroutineException].
+     * if coroutine has an uncaught exception.
      */
     public fun handleException(context: CoroutineContext, exception: Throwable)
 }
diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineScope.kt b/common/kotlinx-coroutines-core-common/src/CoroutineScope.kt
index ea1ccac..3935296 100644
--- a/common/kotlinx-coroutines-core-common/src/CoroutineScope.kt
+++ b/common/kotlinx-coroutines-core-common/src/CoroutineScope.kt
@@ -169,7 +169,7 @@
  * 2) If `doSomeWork` throws an exception, then `async` task is cancelled and `loadDataForUI` rethrows that exception.
  * 3) If outer scope of `loadDataForUI` is cancelled, both started `async` and `withContext` are cancelled.
  *
- * Method may throw [JobCancellationException] if the current job was cancelled externally
+ * Method may throw [CancellationException] if the current job was cancelled externally
  * or may throw the corresponding unhandled [Throwable] if there is any unhandled exception in this scope
  * (for example, from a crashed coroutine that was started with [launch][CoroutineScope.launch] in this scope).
  */
@@ -193,6 +193,7 @@
  * Provides [CoroutineScope] that is already present in the current [coroutineContext] to the given [block].
  * Note, this method doesn't wait for all launched children to complete (as opposed to [coroutineScope]).
  */
+@Deprecated("No replacement, usages are discouraged. Find another solution.")
 public suspend inline fun <R> currentScope(block: CoroutineScope.() -> R): R =
     CoroutineScope(coroutineContext).block()
 
diff --git a/common/kotlinx-coroutines-core-common/src/CoroutineStart.kt b/common/kotlinx-coroutines-core-common/src/CoroutineStart.kt
index e91aea3..4ce9df4 100644
--- a/common/kotlinx-coroutines-core-common/src/CoroutineStart.kt
+++ b/common/kotlinx-coroutines-core-common/src/CoroutineStart.kt
@@ -54,7 +54,10 @@
      *
      * Cancellability of coroutine at suspension points depends on the particular implementation details of
      * suspending functions as in [DEFAULT].
+     *
+     * @suppress **This an internal API and should not be used from general code.**
      */
+    @InternalCoroutinesApi
     ATOMIC,
 
     /**
@@ -67,7 +70,10 @@
      *
      * Cancellability of coroutine at suspension points depends on the particular implementation details of
      * suspending functions as in [DEFAULT].
+     *
+     * **Note: This is an experimental api.** Execution semantics of coroutines may change in the future when this mode is used.
      */
+    @ExperimentalCoroutinesApi
     UNDISPATCHED;
 
     /**
@@ -77,7 +83,10 @@
      * * [ATOMIC] uses [startCoroutine].
      * * [UNDISPATCHED] uses [startCoroutineUndispatched].
      * * [LAZY] does nothing.
+     *
+     * @suppress **This an internal API and should not be used from general code.**
      */
+    @InternalCoroutinesApi
     public operator fun <T> invoke(block: suspend () -> T, completion: Continuation<T>) =
         when (this) {
             CoroutineStart.DEFAULT -> block.startCoroutineCancellable(completion)
@@ -93,7 +102,10 @@
      * * [ATOMIC] uses [startCoroutine].
      * * [UNDISPATCHED] uses [startCoroutineUndispatched].
      * * [LAZY] does nothing.
+     *
+     * @suppress **This an internal API and should not be used from general code.**
      */
+    @InternalCoroutinesApi
     public operator fun <R, T> invoke(block: suspend R.() -> T, receiver: R, completion: Continuation<T>) =
         when (this) {
             CoroutineStart.DEFAULT -> block.startCoroutineCancellable(receiver, completion)
@@ -104,6 +116,9 @@
 
     /**
      * Returns `true` when [LAZY].
+     *
+     * @suppress **This an internal API and should not be used from general code.**
      */
+    @InternalCoroutinesApi
     public val isLazy: Boolean get() = this === LAZY
 }
diff --git a/common/kotlinx-coroutines-core-common/src/Deferred.kt b/common/kotlinx-coroutines-core-common/src/Deferred.kt
index e2c90f1..b4681a5 100644
--- a/common/kotlinx-coroutines-core-common/src/Deferred.kt
+++ b/common/kotlinx-coroutines-core-common/src/Deferred.kt
@@ -70,7 +70,10 @@
      *
      * This function is designed to be used from [invokeOnCompletion] handlers, when there is an absolute certainty that
      * the value is already complete. See also [getCompletionExceptionOrNull].
+     *
+     * **Note: This is an experimental api.** This function may be removed or renamed in the future.
      */
+    @ExperimentalCoroutinesApi
     public fun getCompleted(): T
 
     /**
@@ -80,7 +83,10 @@
      *
      * This function is designed to be used from [invokeOnCompletion] handlers, when there is an absolute certainty that
      * the value is already complete. See also [getCompleted].
+     *
+     * **Note: This is an experimental api.** This function may be removed or renamed in the future.
      */
+    @ExperimentalCoroutinesApi
     public fun getCompletionExceptionOrNull(): Throwable?
 
     /**
@@ -91,39 +97,16 @@
 }
 
 /**
- * Creates new coroutine and returns its future result as an implementation of [Deferred].
- * The running coroutine is cancelled when the resulting deferred is [cancelled][Job.cancel].
- *
- * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [context] argument.
- * If the context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used.
- * The parent job is inherited from a [CoroutineScope] as well, but it can also be overridden
- * with corresponding [coroutineContext] element.
- *
- * By default, the coroutine is immediately scheduled for execution.
- * Other options can be specified via `start` parameter. See [CoroutineStart] for details.
- * An optional [start] parameter can be set to [CoroutineStart.LAZY] to start coroutine _lazily_. In this case,,
- * the resulting [Deferred] is created in _new_ state. It can be explicitly started with [start][Job.start]
- * function and will be started implicitly on the first invocation of [join][Job.join], [await][Deferred.await] or [awaitAll].
- *
- * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
- * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
- * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
- * @param block the coroutine code.
+ * @suppress **Deprecated**: onCompletion parameter is deprecated.
  */
+@Deprecated("onCompletion parameter is deprecated")
 public fun <T> CoroutineScope.async(
     context: CoroutineContext = EmptyCoroutineContext,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     onCompletion: CompletionHandler? = null,
     block: suspend CoroutineScope.() -> T
-): Deferred<T> {
-    val newContext = newCoroutineContext(context)
-    val coroutine = if (start.isLazy)
-        LazyDeferredCoroutine(newContext, block) else
-        DeferredCoroutine<T>(newContext, active = true)
-    if (onCompletion != null) coroutine.invokeOnCompletion(handler = onCompletion)
-    coroutine.start(start, coroutine, block)
-    return coroutine
-}
+): Deferred<T> =
+    async(context, start, block).also { if (onCompletion != null) it.invokeOnCompletion(onCompletion) }
 
 /**
  * Creates new coroutine and returns its future result as an implementation of [Deferred].
@@ -193,23 +176,3 @@
 public fun <T> defer(context: CoroutineContext, block: suspend CoroutineScope.() -> T): Deferred<T> =
     GlobalScope.async(context, block = block)
 
-@Suppress("UNCHECKED_CAST")
-private open class DeferredCoroutine<T>(
-    parentContext: CoroutineContext,
-    active: Boolean
-) : AbstractCoroutine<T>(parentContext, active), Deferred<T>, SelectClause1<T> {
-    override fun getCompleted(): T = getCompletedInternal() as T
-    override suspend fun await(): T = awaitInternal() as T
-    override val onAwait: SelectClause1<T> get() = this
-    override fun <R> registerSelectClause1(select: SelectInstance<R>, block: suspend (T) -> R) =
-        registerSelectClause1Internal(select, block)
-}
-
-private class LazyDeferredCoroutine<T>(
-    parentContext: CoroutineContext,
-    private val block: suspend CoroutineScope.() -> T
-) : DeferredCoroutine<T>(parentContext, active = false) {
-    override fun onStart() {
-        block.startCoroutineCancellable(this, this)
-    }
-}
diff --git a/common/kotlinx-coroutines-core-common/src/Delay.kt b/common/kotlinx-coroutines-core-common/src/Delay.kt
index c33e6d0..9f2db58 100644
--- a/common/kotlinx-coroutines-core-common/src/Delay.kt
+++ b/common/kotlinx-coroutines-core-common/src/Delay.kt
@@ -14,21 +14,31 @@
  *
  * Implementation of this interface affects operation of
  * [delay][kotlinx.coroutines.experimental.delay] and [withTimeout] functions.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi // todo: Remove references from other docs
 public interface Delay {
+    @Deprecated(level = DeprecationLevel.HIDDEN, message = "binary compatibility")
+    suspend fun delay(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) = delay(time.convertToMillis(unit))
+
     /**
      * Delays coroutine for a given time without blocking a thread and resumes it after a specified time.
      * This suspending function is cancellable.
      * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
      * immediately resumes with [CancellationException].
      */
-    suspend fun delay(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) {
+    suspend fun delay(time: Long) {
         if (time <= 0) return // don't delay
-        return suspendCancellableCoroutine { scheduleResumeAfterDelay(time, unit, it) }
+        return suspendCancellableCoroutine { scheduleResumeAfterDelay(time, it) }
     }
 
+    @Deprecated(level = DeprecationLevel.HIDDEN, message = "binary compatibility")
+    fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) =
+        scheduleResumeAfterDelay(time.convertToMillis(unit), continuation)
+
     /**
-     * Schedules resume of a specified [continuation] after a specified delay [time].
+     * Schedules resume of a specified [continuation] after a specified delay [timeMillis].
      *
      * Continuation **must be scheduled** to resume even if it is already cancelled, because a cancellation is just
      * an exception that the coroutine that used `delay` might wanted to catch and process. It might
@@ -42,19 +52,27 @@
      * with(continuation) { resumeUndispatched(Unit) }
      * ```
      */
-    fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>)
+    fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>)
+
+    @Deprecated(level = DeprecationLevel.HIDDEN, message = "binary compatibility")
+    fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle =
+        DefaultDelay.invokeOnTimeout(time.convertToMillis(unit), block)
 
     /**
-     * Schedules invocation of a specified [block] after a specified delay [time].
+     * Schedules invocation of a specified [block] after a specified delay [timeMillis].
      * The resulting [DisposableHandle] can be used to [dispose][DisposableHandle.dispose] of this invocation
      * request if it is not needed anymore.
      *
      * This implementation uses a built-in single-threaded scheduled executor service.
      */
-    fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle =
-        DefaultDelay.invokeOnTimeout(time, unit, block)
+    fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle =
+        DefaultDelay.invokeOnTimeout(timeMillis, block)
 }
 
+@Deprecated(level = DeprecationLevel.HIDDEN, message = "binary compatibility")
+public suspend fun delay(timeMillis: Int) =
+    delay(timeMillis.toLong(), TimeUnit.MILLISECONDS)
+
 /**
  * Delays coroutine for a given time without blocking a thread and resumes it after a specified time.
  * This suspending function is cancellable.
@@ -66,10 +84,14 @@
  * This function delegates to [Delay.scheduleResumeAfterDelay] if the context [CoroutineDispatcher]
  * implements [Delay] interface, otherwise it resumes using a built-in single-threaded scheduled executor service.
  *
- * @param time time in milliseconds.
+ * @param timeMillis time in milliseconds.
  */
-public suspend fun delay(time: Int) =
-    delay(time.toLong(), TimeUnit.MILLISECONDS)
+public suspend fun delay(timeMillis: Long) {
+    if (timeMillis <= 0) return // don't delay
+    return suspendCancellableCoroutine sc@ { cont: CancellableContinuation<Unit> ->
+        cont.context.delay.scheduleResumeAfterDelay(timeMillis, cont)
+    }
+}
 
 /**
  * Delays coroutine for a given time without blocking a thread and resumes it after a specified time.
@@ -84,11 +106,22 @@
  *
  * @param time time in the specified [unit].
  * @param unit time unit.
+ *
+ * @suppress **Deprecated**: Replace with `delay(unit.toMillis(time))`
  */
-public suspend fun delay(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) {
-    if (time <= 0) return // don't delay
-    return suspendCancellableCoroutine sc@ { cont: CancellableContinuation<Unit> ->
-        cont.context.delay.scheduleResumeAfterDelay(time, unit, cont)
+@Deprecated(
+    message = "Replace with delay(unit.toMillis(time))",
+    replaceWith = ReplaceWith("delay(unit.toMillis(time))")
+)
+public suspend fun delay(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS) =
+    delay(time.convertToMillis(unit))
+
+internal fun Long.convertToMillis(unit: TimeUnit): Long {
+    val result = unit.toMillis(this)
+    return when {
+        result != 0L -> result
+        this > 0 -> 1L
+        else -> 0L
     }
 }
 
diff --git a/common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt b/common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt
index c9aea8d..5426891 100644
--- a/common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt
+++ b/common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt
@@ -37,8 +37,12 @@
      * an optional [CoroutineStart] parameter in coroutine builders like
      * [launch][CoroutineScope.launch] and [async][CoroutineScope.async] setting it to the
      * the value of [CoroutineStart.UNDISPATCHED].
+     *
+     * **Note: This is an experimental api.**
+     * Semantics, order of execution, and particular implementation details of this dispatcher may change in the future.
      */
     @JvmField
+    @ExperimentalCoroutinesApi
     public val Unconfined: CoroutineDispatcher =
         kotlinx.coroutines.experimental.Unconfined
 }
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/Exceptions.common.kt b/common/kotlinx-coroutines-core-common/src/Exceptions.common.kt
index 2ea6103..7658fb2 100644
--- a/common/kotlinx-coroutines-core-common/src/Exceptions.common.kt
+++ b/common/kotlinx-coroutines-core-common/src/Exceptions.common.kt
@@ -4,10 +4,16 @@
 
 package kotlinx.coroutines.experimental
 
+@InternalCoroutinesApi
 public expect class CompletionHandlerException(message: String, cause: Throwable) : RuntimeException
 
 public expect open class CancellationException(message: String?) : IllegalStateException
 
+/**
+ * @suppress **Deprecated**: Replace with [CancellationException].
+ */
+@InternalCoroutinesApi
+@Deprecated(message = "Replace with CancellationException", replaceWith = ReplaceWith("CancellationException"))
 public expect class JobCancellationException(
     message: String,
     cause: Throwable?,
diff --git a/common/kotlinx-coroutines-core-common/src/Job.kt b/common/kotlinx-coroutines-core-common/src/Job.kt
index 3fe4464..3713c07 100644
--- a/common/kotlinx-coroutines-core-common/src/Job.kt
+++ b/common/kotlinx-coroutines-core-common/src/Job.kt
@@ -123,14 +123,15 @@
      *
      * This function returns the original [cancel] cause of this job if that `cause` was an instance of
      * [CancellationException]. Otherwise (if this job was cancelled with a cause of a different type, or
-     * was cancelled without a cause, or had completed normally), an instance of [JobCancellationException] is
-     * returned. The [JobCancellationException.cause] of the resulting [JobCancellationException] references
+     * was cancelled without a cause, or had completed normally), an instance of [CancellationException] is
+     * returned. The [CancellationException.cause] of the resulting [CancellationException] references
      * the original cancellation cause that was passed to [cancel] function.
      *
      * This function throws [IllegalStateException] when invoked on a job that is still active.
      *
-     * @suppress **This is unstable API and it is subject to change.**
+     * @suppress **This an internal API and should not be used from general code.**
      */
+    @InternalCoroutinesApi
     public fun getCancellationException(): CancellationException
 
     /**
@@ -150,6 +151,14 @@
     public fun start(): Boolean
 
     /**
+     * Cancels this job.
+     * The result is `true` if this job was either cancelled as a result of this invocation
+     * or was already being cancelled.
+     * If job is already completed, method returns `false`.
+     */
+    public fun cancel(): Boolean
+
+    /**
      * Cancels this job with an optional cancellation [cause].
      * The result is `true` if this job was either cancelled as a result of this invocation
      * or it's being cancelled and given [cause] was successfully received by the job and will be properly handled, `false` otherwise.
@@ -160,11 +169,14 @@
      * When cancellation has a clear reason in the code, an instance of [CancellationException] should be created
      * at the corresponding original cancellation site and passed into this method to aid in debugging by providing
      * both the context of cancellation and text description of the reason.
+     *
+     * **Note: This is an experimental api.** Cancellation of a job with exception may change its semantics in the future.
      */
+    @ExperimentalCoroutinesApi
     public fun cancel(cause: Throwable? = null): Boolean
 
     // ------------ parent-child ------------
-    
+
     /**
      * Returns a sequence of this job's children.
      *
@@ -202,10 +214,10 @@
      * lookup a [Job] instance in the parent context and use this function to attach themselves as a child.
      * They also store a reference to the resulting [ChildHandle] and dispose a handle when they complete.
      *
-     * @suppress **This is unstable API and it is subject to change.**
-     *           This is an internal API. This method is too error prone for public API.
+     * @suppress This is an internal API. This method is too error prone for public API.
      */
     // ChildJob and ChildHandle are made internal on purpose to further deter 3rd-party impl of Job
+    @InternalCoroutinesApi
     @Suppress("EXPOSED_FUNCTION_RETURN_TYPE", "EXPOSED_PARAMETER_TYPE")
     public fun attachChild(child: ChildJob): ChildHandle
 
@@ -319,12 +331,13 @@
      * @param onCancelling when `true`, then the [handler] is invoked as soon as this job transitions to _failing_ state;
      *        when `false` then the [handler] is invoked only when it transitions to _completed_ state.
      * @param invokeImmediately when `true` and this job is already in the desired state (depending on [onCancelling]),
-     *        then the [handler] is immediately and synchronously invoked and [NonDisposableHandle] is returned;
-     *        when `false` then [NonDisposableHandle] is returned, but the [handler] is not invoked.
+     *        then the [handler] is immediately and synchronously invoked and no-op [DisposableHandle] is returned;
+     *        when `false` then no-op [DisposableHandle] is returned, but the [handler] is not invoked.
      * @param handler the handler.
-     * 
-     * @suppress **This is unstable API and it is subject to change.**
+     *
+     * @suppress **This an internal API and should not be used from general code.**
      */
+    @InternalCoroutinesApi
     public fun invokeOnCompletion(
         onCancelling: Boolean = false,
         invokeImmediately: Boolean = true,
@@ -364,6 +377,20 @@
 }
 
 /**
+ * @suppress **This an internal API and should not be used from general code.**
+ */
+@Suppress("FunctionName")
+@InternalCoroutinesApi
+public inline fun DisposableHandle(crossinline block: () -> Unit) =
+    object : DisposableHandle {
+        override fun dispose() {
+            block()
+        }
+    }
+
+// -------------------- Parent-child communication --------------------
+
+/**
  * A reference that parent receives from its child so that it can report its failure.
  *
  * @suppress **This is unstable API and it is subject to change.**
@@ -381,7 +408,7 @@
 
 /**
  * A handle that child keep onto its parent so that it is able to report its failure.
- * 
+ *
  * @suppress **This is unstable API and it is subject to change.**
  */
 internal interface ChildHandle : DisposableHandle {
@@ -419,7 +446,10 @@
  * ```
  * invokeOnCompletion { handle.dispose() }
  * ```
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun Job.disposeOnCompletion(handle: DisposableHandle): DisposableHandle =
     invokeOnCompletion(handler = DisposeOnCompletion(this, handle).asHandler)
 
@@ -455,7 +485,10 @@
  * Suspends coroutine until all [children][Job.children] of this job are complete using
  * [Job.join] for all of them. Unlike [Job.join] on this job as a whole, it does not wait until
  * this job is complete.
+ *
+ * @suppress **Deprecated**: No replacement. Group child in a `coroutineScope { }` block to wait for them
  */
+@Deprecated("No replacement. Group child in a coroutineScope { } block to wait for them")
 public suspend fun Job.joinChildren() {
     children.forEach { it.join() }
 }
@@ -482,20 +515,42 @@
     get() = this[Job]?.isActive == true
 
 /**
+ * Cancels [Job] of this context. The result is `true` if the job was
+ * cancelled as a result of this invocation or was already being cancelled and
+ * `false` if there is no job in the context or if it was already completed. See [Job.cancel] for details.
+ */
+public fun CoroutineContext.cancel(): Boolean =
+    this[Job]?.cancel() ?: false
+
+/**
  * Cancels [Job] of this context with an optional cancellation [cause]. The result is `true` if the job was
  * cancelled as a result of this invocation and `false` if there is no job in the context or if it was already
  * cancelled or completed. See [Job.cancel] for details.
+ *
+ * **Note: This is an experimental api.** Cancellation of a job with exception may change its semantics in the future.
  */
+@ExperimentalCoroutinesApi
 public fun CoroutineContext.cancel(cause: Throwable? = null): Boolean =
     this[Job]?.cancel(cause) ?: false
 
 /**
- * Cancels all children of the [Job] in this context with an optional cancellation [cause].
+ * Cancels all children of the [Job] in this context, without touching the the state of this job itself.
  * It does not do anything if there is no job in the context or it has no children.
- * See [Job.cancelChildren] for details.
  */
+public fun CoroutineContext.cancelChildren() {
+    this[Job]?.children?.forEach { it.cancel() }
+}
+
+/**
+ * Cancels all children of the [Job] in this context with an optional cancellation [cause],
+ * without touching the the state of this job itself.
+ * It does not do anything if there is no job in the context or it has no children.
+ *
+ * **Note: This is an experimental api.** Cancellation of a job with exception may change its semantics in the future.
+ */
+@ExperimentalCoroutinesApi
 public fun CoroutineContext.cancelChildren(cause: Throwable? = null) {
-    this[Job]?.cancelChildren(cause)
+    this[Job]?.children?.forEach { it.cancel(cause) }
 }
 
 /**
@@ -507,7 +562,9 @@
 
 /**
  * No-op implementation of [DisposableHandle].
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public object NonDisposableHandle : DisposableHandle, ChildHandle {
     /**
      * Does not do anything.
diff --git a/common/kotlinx-coroutines-core-common/src/JobSupport.kt b/common/kotlinx-coroutines-core-common/src/JobSupport.kt
index 8628991..66924ed 100644
--- a/common/kotlinx-coroutines-core-common/src/JobSupport.kt
+++ b/common/kotlinx-coroutines-core-common/src/JobSupport.kt
@@ -408,7 +408,7 @@
 
     /**
      * Returns the cause that signals the completion of this job -- it returns the original
-     * [cancel] cause, [JobCancellationException] or **`null` if this job had completed normally**.
+     * [cancel] cause, [CancellationException] or **`null` if this job had completed normally**.
      * This function throws [IllegalStateException] when invoked for an job that has not [completed][isCompleted] nor
      * failing yet.
      *
@@ -599,6 +599,10 @@
      */
     internal open val onCancelComplete: Boolean get() = false
 
+    // external cancel without cause, never invoked implicitly from internal machinery
+    public override fun cancel(): Boolean =
+        cancel(null) // must delegate here, because some classes override cancel(x)
+
     // external cancel with (optional) cause, never invoked implicitly from internal machinery
     public override fun cancel(cause: Throwable?): Boolean =
         cancelImpl(cause) && handlesException
@@ -693,7 +697,7 @@
 
     // Performs promotion of incomplete coroutine state to NodeList for the purpose of
     // converting coroutine state to Failing, returns null when need to retry
-    private fun getOrPromoteFailingList(state: Incomplete): NodeList? = state.list ?: 
+    private fun getOrPromoteFailingList(state: Incomplete): NodeList? = state.list ?:
         when (state) {
             is Empty -> NodeList() // we can allocate new empty list that'll get integrated into Failing state
             is JobNode<*> -> {
diff --git a/common/kotlinx-coroutines-core-common/src/NonCancellable.kt b/common/kotlinx-coroutines-core-common/src/NonCancellable.kt
index 9e1ae41..1d60aa4 100644
--- a/common/kotlinx-coroutines-core-common/src/NonCancellable.kt
+++ b/common/kotlinx-coroutines-core-common/src/NonCancellable.kt
@@ -20,64 +20,125 @@
  * ```
  */
 public object NonCancellable : AbstractCoroutineContextElement(Job), Job {
-    /** Always returns `true`. */
+    /**
+     * Always returns `true`.
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
     override val isActive: Boolean  get() = true
 
-    /** Always returns `false`. */
+    /**
+     * Always returns `false`.
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
     override val isCompleted: Boolean get() = false
 
-    /** Always returns `false`. */
+    /**
+     * Always returns `false`.
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
     override val isCancelled: Boolean get() = false
 
-    /** Always returns `false`. */
+    /**
+     * Always returns `false`.
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
     override fun start(): Boolean = false
 
-    /** Always throws [UnsupportedOperationException]. */
+    /**
+     * Always throws [UnsupportedOperationException].
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
     override suspend fun join() {
         throw UnsupportedOperationException("This job is always active")
     }
 
+    /**
+     * Always throws [UnsupportedOperationException].
+     * @suppress **This an internal API and should not be used from general code.**
+     */
     override val onJoin: SelectClause0
         get() = throw UnsupportedOperationException("This job is always active")
 
-    /** Always throws [IllegalStateException]. */
+    /**
+     * Always throws [IllegalStateException].
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
     override fun getCancellationException(): CancellationException = throw IllegalStateException("This job is always active")
 
-    /** Always returns [NonDisposableHandle]. */
+    /**
+     * @suppress **This an internal API and should not be used from general code.**
+     */
     @Suppress("OverridingDeprecatedMember")
+    @InternalCoroutinesApi
     override fun invokeOnCompletion(handler: CompletionHandler): DisposableHandle =
         NonDisposableHandle
 
-    /** Always returns [NonDisposableHandle]. */
+    /**
+     * @suppress **This an internal API and should not be used from general code.**
+     */
     @Suppress("OverridingDeprecatedMember")
+    @InternalCoroutinesApi
     override fun invokeOnCompletion(handler: CompletionHandler, onCancelling: Boolean): DisposableHandle =
         NonDisposableHandle
 
-    /** Always returns [NonDisposableHandle]. */
+    /**
+     * Always returns no-op handle.
+     * @suppress **This an internal API and should not be used from general code.**
+     */
     @Suppress("OverridingDeprecatedMember")
+    @InternalCoroutinesApi
     override fun invokeOnCompletion(onCancelling_: Boolean, handler: CompletionHandler): DisposableHandle =
         NonDisposableHandle
 
-    /** Always returns [NonDisposableHandle]. */
+    /**
+     * Always returns no-op handle.
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
     override fun invokeOnCompletion(onCancelling: Boolean, invokeImmediately: Boolean, handler: CompletionHandler): DisposableHandle =
         NonDisposableHandle
 
-    /** Always returns `false`. */
+    /**
+     * Always returns `false`.
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
+    override fun cancel(): Boolean = false
+
+    /**
+     * Always returns `false`.
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
     override fun cancel(cause: Throwable?): Boolean = false // never handles exceptions
 
-    /** Always returns [emptySequence]. */
+    /**
+     * Always returns [emptySequence].
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
     override val children: Sequence<Job>
         get() = emptySequence()
 
     /**
      * Always returns [NonDisposableHandle] and does not do anything.
-     * @suppress **This is unstable API and it is subject to change.**
-     *           This is an internal API. This method is too error prone for public API.
+     * @suppress **This an internal API and should not be used from general code.**
      */
     @Suppress("EXPOSED_FUNCTION_RETURN_TYPE", "EXPOSED_PARAMETER_TYPE")
+    @InternalCoroutinesApi
     override fun attachChild(child: ChildJob): ChildHandle = NonDisposableHandle
 
-    /** Does not do anything. */
+    /**
+     * Does not do anything.
+     * @suppress **This an internal API and should not be used from general code.**
+     */
     @Suppress("OverridingDeprecatedMember")
+    @InternalCoroutinesApi
     override fun cancelChildren(cause: Throwable?) {}
 }
diff --git a/common/kotlinx-coroutines-core-common/src/Scheduled.kt b/common/kotlinx-coroutines-core-common/src/Scheduled.kt
index a99bb9b..1545843 100644
--- a/common/kotlinx-coroutines-core-common/src/Scheduled.kt
+++ b/common/kotlinx-coroutines-core-common/src/Scheduled.kt
@@ -4,32 +4,12 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlinx.coroutines.experimental.internal.*
-import kotlinx.coroutines.experimental.intrinsics.*
 import kotlinx.coroutines.experimental.selects.*
 import kotlinx.coroutines.experimental.timeunit.*
-import kotlin.coroutines.experimental.*
-import kotlin.coroutines.experimental.intrinsics.*
 
-/**
- * Runs a given suspending [block] of code inside a coroutine with a specified timeout and throws
- * [TimeoutCancellationException] if timeout was exceeded.
- *
- * The code that is executing inside the [block] is cancelled on timeout and the active or next invocation of
- * cancellable suspending function inside the block throws [TimeoutCancellationException].
- * Even if the code in the block suppresses [TimeoutCancellationException], it
- * is still thrown by `withTimeout` invocation.
- *
- * The sibling function that does not throw exception on timeout is [withTimeoutOrNull].
- * Note, that timeout action can be specified for [select] invocation with [onTimeout][SelectBuilder.onTimeout] clause.
- *
- * This function delegates to [Delay.invokeOnTimeout] if the context [CoroutineDispatcher]
- * implements [Delay] interface, otherwise it tracks time using a built-in single-threaded scheduled executor service.
- *
- * @param time timeout time in milliseconds.
- */
+@Deprecated(level = DeprecationLevel.HIDDEN, message = "binary compatibility")
 public suspend fun <T> withTimeout(time: Int, block: suspend CoroutineScope.() -> T): T =
-    withTimeout(time.toLong(), TimeUnit.MILLISECONDS, block)
+    withTimeout(time.toLong(), block)
 
 /**
  * Runs a given suspending [block] of code inside a coroutine with a specified timeout and throws
@@ -48,50 +28,15 @@
  *
  * @param time timeout time
  * @param unit timeout unit (milliseconds by default)
+ *
+ * @suppress **Deprecated**: Replace with `withTimeout(unit.toMillis(time), block)`
  */
-public suspend fun <T> withTimeout(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS, block: suspend CoroutineScope.() -> T): T {
-    if (time <= 0L) throw CancellationException("Timed out immediately")
-    return suspendCoroutineUninterceptedOrReturn { uCont ->
-        setupTimeout(TimeoutCoroutine(time, unit, uCont), block)
-    }
-}
-
-private fun <U, T: U> setupTimeout(
-    coroutine: TimeoutCoroutine<U, T>,
-    block: suspend CoroutineScope.() -> T
-): Any? {
-    // schedule cancellation of this coroutine on time
-    val cont = coroutine.uCont
-    val context = cont.context
-    coroutine.disposeOnCompletion(context.delay.invokeOnTimeout(coroutine.time, coroutine.unit, coroutine))
-    // restart block using new coroutine with new job,
-    // however start it as undispatched coroutine, because we are already in the proper context
-    return coroutine.startUndispatchedOrReturn(coroutine, block)
-}
-
-private open class TimeoutCoroutine<U, in T: U>(
-    @JvmField val time: Long,
-    @JvmField val unit: TimeUnit,
-    @JvmField val uCont: Continuation<U> // unintercepted continuation
-) : AbstractCoroutine<T>(uCont.context, active = true), Runnable, Continuation<T> {
-    override val defaultResumeMode: Int get() = MODE_DIRECT
-
-    @Suppress("LeakingThis")
-    override fun run() {
-        cancel(TimeoutCancellationException(time, unit, this))
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    internal override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) {
-        if (state is CompletedExceptionally)
-            uCont.resumeUninterceptedWithExceptionMode(state.cause, mode)
-        else
-            uCont.resumeUninterceptedMode(state as T, mode)
-    }
-
-    override fun nameString(): String =
-        "${super.nameString()}($time $unit)"
-}
+@Deprecated(
+    message = "Replace with withTimeout(unit.toMillis(time), block)",
+    replaceWith = ReplaceWith("withTimeout(unit.toMillis(time), block)")
+)
+public suspend fun <T> withTimeout(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS, block: suspend CoroutineScope.() -> T): T =
+    withTimeout(unit.toMillis(time), block)
 
 /**
  * Runs a given suspending block of code inside a coroutine with a specified timeout and returns
@@ -110,6 +55,7 @@
  *
  * @param time timeout time in milliseconds.
  */
+@Deprecated(level = DeprecationLevel.HIDDEN, message = "binary compatibility")
 public suspend fun <T> withTimeoutOrNull(time: Int, block: suspend CoroutineScope.() -> T): T? =
     withTimeoutOrNull(time.toLong(), TimeUnit.MILLISECONDS, block)
 
@@ -130,43 +76,12 @@
  *
  * @param time timeout time
  * @param unit timeout unit (milliseconds by default)
+ * @suppress **Deprecated**: Replace with `withTimeoutOrNull(unit.toMillis(time), block)`
  */
-public suspend fun <T> withTimeoutOrNull(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS, block: suspend CoroutineScope.() -> T): T? {
-    if (time <= 0L) return null
+@Deprecated(
+    message = "Replace with withTimeoutOrNull(unit.toMillis(time), block)",
+    replaceWith = ReplaceWith("withTimeoutOrNull(unit.toMillis(time), block)")
+)
+public suspend fun <T> withTimeoutOrNull(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS, block: suspend CoroutineScope.() -> T): T? =
+    withTimeoutOrNull(time.convertToMillis(unit), block)
 
-    // Workaround for K/N bug
-    val array = arrayOfNulls<TimeoutCoroutine<T?, T?>>(1)
-    try {
-        return suspendCoroutineUninterceptedOrReturn { uCont ->
-            val timeoutCoroutine = TimeoutCoroutine(time, unit, uCont)
-            array[0] = timeoutCoroutine
-            setupTimeout<T?, T?>(timeoutCoroutine, block)
-        }
-    } catch (e: TimeoutCancellationException) {
-        // Return null iff it's our exception, otherwise propagate it upstream (e.g. in case of nested withTimeouts)
-        if (e.coroutine === array[0]) {
-            return null
-        }
-        throw e
-    }
-}
-
-/**
- * This exception is thrown by [withTimeout] to indicate timeout.
- */
-public class TimeoutCancellationException internal constructor(
-    message: String,
-    @JvmField internal val coroutine: Job?
-) : CancellationException(message) {
-    /**
-     * Creates timeout exception with a given message.
-     */
-    public constructor(message: String) : this(message, null)
-}
-
-@Suppress("FunctionName")
-internal fun TimeoutCancellationException(
-    time: Long,
-    unit: TimeUnit,
-    coroutine: Job
-) : TimeoutCancellationException = TimeoutCancellationException("Timed out waiting for $time $unit", coroutine)
diff --git a/common/kotlinx-coroutines-core-common/src/Timeout.kt b/common/kotlinx-coroutines-core-common/src/Timeout.kt
new file mode 100644
index 0000000..5c9ea07
--- /dev/null
+++ b/common/kotlinx-coroutines-core-common/src/Timeout.kt
@@ -0,0 +1,133 @@
+/*
+ * 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 kotlinx.coroutines.experimental.internal.*
+import kotlinx.coroutines.experimental.intrinsics.*
+import kotlinx.coroutines.experimental.selects.*
+import kotlin.coroutines.experimental.*
+import kotlin.coroutines.experimental.intrinsics.*
+
+/**
+ * Runs a given suspending [block] of code inside a coroutine with a specified timeout and throws
+ * [TimeoutCancellationException] if timeout was exceeded.
+ *
+ * The code that is executing inside the [block] is cancelled on timeout and the active or next invocation of
+ * cancellable suspending function inside the block throws [TimeoutCancellationException].
+ * Even if the code in the block suppresses [TimeoutCancellationException], it
+ * is still thrown by `withTimeout` invocation.
+ *
+ * The sibling function that does not throw exception on timeout is [withTimeoutOrNull].
+ * Note, that timeout action can be specified for [select] invocation with [onTimeout][SelectBuilder.onTimeout] clause.
+ *
+ * This function delegates to [Delay.invokeOnTimeout] if the context [CoroutineDispatcher]
+ * implements [Delay] interface, otherwise it tracks time using a built-in single-threaded scheduled executor service.
+ *
+ * @param timeMillis timeout time in milliseconds.
+ */
+public suspend fun <T> withTimeout(timeMillis: Long, block: suspend CoroutineScope.() -> T): T {
+    if (timeMillis <= 0L) throw CancellationException("Timed out immediately")
+    return suspendCoroutineUninterceptedOrReturn { uCont ->
+        setupTimeout(TimeoutCoroutine(timeMillis, uCont), block)
+    }
+}
+
+/**
+ * Runs a given suspending block of code inside a coroutine with a specified timeout and returns
+ * `null` if this timeout was exceeded.
+ *
+ * The code that is executing inside the [block] is cancelled on timeout and the active or next invocation of
+ * cancellable suspending function inside the block throws [TimeoutCancellationException].
+ * **NB**: this method is exception-unsafe. Even if the code in the block suppresses [TimeoutCancellationException], this
+ * invocation of `withTimeoutOrNull` still returns `null` and thrown exception will be ignored.
+ *
+ * The sibling function that throws exception on timeout is [withTimeout].
+ * Note, that timeout action can be specified for [select] invocation with [onTimeout][SelectBuilder.onTimeout] clause.
+ *
+ * This function delegates to [Delay.invokeOnTimeout] if the context [CoroutineDispatcher]
+ * implements [Delay] interface, otherwise it tracks time using a built-in single-threaded scheduled executor service.
+ *
+ * @param timeMillis timeout time in milliseconds.
+ */
+public suspend fun <T> withTimeoutOrNull(timeMillis: Long, block: suspend CoroutineScope.() -> T): T? {
+    if (timeMillis <= 0L) return null
+
+    // Workaround for K/N bug
+    val array = arrayOfNulls<TimeoutCoroutine<T?, T?>>(1)
+    try {
+        return suspendCoroutineUninterceptedOrReturn { uCont ->
+            val timeoutCoroutine = TimeoutCoroutine(timeMillis, uCont)
+            array[0] = timeoutCoroutine
+            setupTimeout<T?, T?>(timeoutCoroutine, block)
+        }
+    } catch (e: TimeoutCancellationException) {
+        // Return null iff it's our exception, otherwise propagate it upstream (e.g. in case of nested withTimeouts)
+        if (e.coroutine === array[0]) {
+            return null
+        }
+        throw e
+    }
+}
+
+private fun <U, T: U> setupTimeout(
+    coroutine: TimeoutCoroutine<U, T>,
+    block: suspend CoroutineScope.() -> T
+): Any? {
+    // schedule cancellation of this coroutine on time
+    val cont = coroutine.uCont
+    val context = cont.context
+    coroutine.disposeOnCompletion(context.delay.invokeOnTimeout(coroutine.time, coroutine))
+    // restart block using new coroutine with new job,
+    // however start it as undispatched coroutine, because we are already in the proper context
+    return coroutine.startUndispatchedOrReturn(coroutine, block)
+}
+
+private open class TimeoutCoroutine<U, in T: U>(
+    @JvmField val time: Long,
+    @JvmField val uCont: Continuation<U> // unintercepted continuation
+) : AbstractCoroutine<T>(uCont.context, active = true), Runnable, Continuation<T> {
+    override val defaultResumeMode: Int get() = MODE_DIRECT
+
+    @Suppress("LeakingThis")
+    override fun run() {
+        cancel(TimeoutCancellationException(time, this))
+    }
+
+    @Suppress("UNCHECKED_CAST")
+    internal override fun onCompletionInternal(state: Any?, mode: Int, suppressed: Boolean) {
+        if (state is CompletedExceptionally)
+            uCont.resumeUninterceptedWithExceptionMode(state.cause, mode)
+        else
+            uCont.resumeUninterceptedMode(state as T, mode)
+    }
+
+    override fun nameString(): String =
+        "${super.nameString()}(timeMillis=$time)"
+}
+
+/**
+ * This exception is thrown by [withTimeout] to indicate timeout.
+ */
+public class TimeoutCancellationException internal constructor(
+    message: String,
+    @JvmField internal val coroutine: Job?
+) : CancellationException(message) {
+    /**
+     * Creates timeout exception with a given message.
+     * This constructor is needed for exception stack-traces recovery.
+     *
+     * @suppress **This an internal API and should not be used from general code.**
+     */
+    @InternalCoroutinesApi
+    public constructor(message: String) : this(message, null)
+}
+
+@Suppress("FunctionName")
+internal fun TimeoutCancellationException(
+    time: Long,
+    coroutine: Job
+) : TimeoutCancellationException = TimeoutCancellationException("Timed out waiting for $time ms", coroutine)
+
+
diff --git a/common/kotlinx-coroutines-core-common/src/channels/AbstractChannel.kt b/common/kotlinx-coroutines-core-common/src/channels/AbstractChannel.kt
index 2a1aa61..201449b 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/AbstractChannel.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/AbstractChannel.kt
@@ -13,7 +13,10 @@
 
 /**
  * Abstract send channel. It is a base class for all send channel implementations.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public abstract class AbstractSendChannel<E> : SendChannel<E> {
     /** @suppress **This is unstable API and it is subject to change.** */
     protected val queue = LockFreeLinkedListHead()
@@ -499,7 +502,10 @@
 
 /**
  * Abstract send/receive channel. It is a base class for all channel implementations.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public abstract class AbstractChannel<E> : AbstractSendChannel<E>(), Channel<E> {
     // ------ extension points for buffered channels ------
 
@@ -654,6 +660,8 @@
         return if (result === POLL_FAILED) null else receiveOrNullResult(result)
     }
 
+    override fun cancel(): Boolean = cancel(null)
+
     override fun cancel(cause: Throwable?): Boolean =
         close(cause).also {
             cleanupSendQueueOnCancel()
@@ -1024,6 +1032,7 @@
  * Represents sending waiter in the queue.
  * @suppress **This is unstable API and it is subject to change.**
  */
+@InternalCoroutinesApi
 public interface Send {
     val pollResult: Any? // E | Closed
     fun tryResumeSend(idempotent: Any?): Any?
@@ -1035,6 +1044,7 @@
  * Represents receiver waiter in the queue or closed token.
  * @suppress **This is unstable API and it is subject to change.**
  */
+@InternalCoroutinesApi
 public interface ReceiveOrClosed<in E> {
     val offerResult: Any // OFFER_SUCCESS | Closed
     fun tryResumeReceive(value: E, idempotent: Any?): Any?
@@ -1046,6 +1056,7 @@
  * @suppress **This is unstable API and it is subject to change.**
  */
 @Suppress("UNCHECKED_CAST")
+@InternalCoroutinesApi
 public class SendElement(
     override val pollResult: Any?,
     @JvmField val cont: CancellableContinuation<Unit>
@@ -1060,6 +1071,7 @@
  * Represents closed channel.
  * @suppress **This is unstable API and it is subject to change.**
  */
+@InternalCoroutinesApi
 public class Closed<in E>(
     @JvmField val closeCause: Throwable?
 ) : LockFreeLinkedListNode(), Send, ReceiveOrClosed<E> {
diff --git a/common/kotlinx-coroutines-core-common/src/channels/ArrayBroadcastChannel.kt b/common/kotlinx-coroutines-core-common/src/channels/ArrayBroadcastChannel.kt
index 145bd81..2c795bc 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/ArrayBroadcastChannel.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/ArrayBroadcastChannel.kt
@@ -4,6 +4,7 @@
 
 package kotlinx.coroutines.experimental.channels
 
+import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.internal.*
 import kotlinx.coroutines.experimental.selects.*
 
@@ -20,8 +21,16 @@
  * This implementation uses lock to protect the buffer, which is held only during very short buffer-update operations.
  * The lock at each subscription is also used to manage concurrent attempts to receive from the same subscriber.
  * The lists of suspended senders or receivers are lock-free.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
-class ArrayBroadcastChannel<E>(
+@InternalCoroutinesApi
+public class ArrayBroadcastChannel<E>
+@Deprecated(
+    "Replace with BroadcastChannel factory function",
+    replaceWith = ReplaceWith("BroadcastChannel(capacity)")
+)
+constructor(
     /**
      * Buffer capacity.
      */
diff --git a/common/kotlinx-coroutines-core-common/src/channels/ArrayChannel.kt b/common/kotlinx-coroutines-core-common/src/channels/ArrayChannel.kt
index 04a55be..a69a684 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/ArrayChannel.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/ArrayChannel.kt
@@ -4,6 +4,7 @@
 
 package kotlinx.coroutines.experimental.channels
 
+import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.internal.*
 import kotlinx.coroutines.experimental.selects.*
 
@@ -15,8 +16,16 @@
  *
  * This implementation uses lock to protect the buffer, which is held only during very short buffer-update operations.
  * The lists of suspended senders or receivers are lock-free.
+ * 
+ * @suppress **This an internal API and should not be used from general code.**
  */
-public open class ArrayChannel<E>(
+@InternalCoroutinesApi
+public open class ArrayChannel<E>
+@Deprecated(
+    "Replace with Channel factory function",
+    replaceWith = ReplaceWith("Channel(capacity)")
+)
+constructor(
     /**
      * Buffer capacity.
      */
diff --git a/common/kotlinx-coroutines-core-common/src/channels/Broadcast.kt b/common/kotlinx-coroutines-core-common/src/channels/Broadcast.kt
index d75f408..3da7fd6 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/Broadcast.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/Broadcast.kt
@@ -66,7 +66,7 @@
  * the resulting channel becomes _failed_, so that any attempt to receive from such a channel throws exception.
  *
  * The kind of the resulting channel depends on the specified [capacity] parameter:
- * * when `capacity` positive (1 by default), but less than [UNLIMITED] -- uses [ArrayBroadcastChannel]
+ * * when `capacity` positive (1 by default), but less than [UNLIMITED] -- uses `ArrayBroadcastChannel` with a buffer of given capacity,
  * * when `capacity` is [CONFLATED] -- uses [ConflatedBroadcastChannel] that conflates back-to-back sends;
  * * otherwise -- throws [IllegalArgumentException].
  *
diff --git a/common/kotlinx-coroutines-core-common/src/channels/BroadcastChannel.kt b/common/kotlinx-coroutines-core-common/src/channels/BroadcastChannel.kt
index 40f489f..59d70e7 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/BroadcastChannel.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/BroadcastChannel.kt
@@ -16,12 +16,16 @@
  *
  * See `BroadcastChannel()` factory function for the description of available
  * broadcast channel implementations.
+ *
+ * **Note: This is an experimental api.** It may be changed in the future updates.
  */
+@ExperimentalCoroutinesApi
 public interface BroadcastChannel<E> : SendChannel<E> {
     /**
      * Factory for broadcast channels.
      * @suppress **Deprecated**
      */
+    @Deprecated(message = "No replacement")
     public companion object Factory {
         /**
          * Creates a broadcast channel with the specified buffer capacity.
@@ -69,11 +73,14 @@
  * Creates a broadcast channel with the specified buffer capacity.
  *
  * The resulting channel type depends on the specified [capacity] parameter:
- * * when `capacity` positive, but less than [UNLIMITED] -- creates [ArrayBroadcastChannel]
+ * * when `capacity` positive, but less than [UNLIMITED] -- creates `ArrayBroadcastChannel` with a buffer of given capacity.
  *   **Note:** this channel looses all items that are send to it until the first subscriber appears;
  * * when `capacity` is [CONFLATED] -- creates [ConflatedBroadcastChannel] that conflates back-to-back sends;
  * * otherwise -- throws [IllegalArgumentException].
+ *
+ * **Note: This is an experimental api.** It may be changed in the future updates.
  */
+@ExperimentalCoroutinesApi
 public fun <E> BroadcastChannel(capacity: Int): BroadcastChannel<E> =
     when (capacity) {
         0 -> throw IllegalArgumentException("Unsupported 0 capacity for BroadcastChannel")
diff --git a/common/kotlinx-coroutines-core-common/src/channels/Channel.kt b/common/kotlinx-coroutines-core-common/src/channels/Channel.kt
index 797a1c0..6c48c64 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/Channel.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/Channel.kt
@@ -2,10 +2,13 @@
  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
 
+@file:Suppress("FunctionName")
+
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.Channel.Factory.CONFLATED
+import kotlinx.coroutines.experimental.channels.Channel.Factory.RENDEZVOUS
 import kotlinx.coroutines.experimental.channels.Channel.Factory.UNLIMITED
 import kotlinx.coroutines.experimental.selects.*
 
@@ -16,13 +19,19 @@
     /**
      * Returns `true` if this channel was closed by invocation of [close] and thus
      * the [send] and [offer] attempts throws exception.
+     *
+     * **Note: This is an experimental api.** This property may change its semantics and/or name in the future.
      */
+    @ExperimentalCoroutinesApi
     public val isClosedForSend: Boolean
 
     /**
      * Returns `true` if the channel is full (out of capacity) and the [send] attempt will suspend.
      * This function returns `false` for [isClosedForSend] channel.
+     *
+     * **Note: This is an experimental api.** This property may change its semantics and/or name in the future.
      */
+    @ExperimentalCoroutinesApi
     public val isFull: Boolean
 
     /**
@@ -68,7 +77,7 @@
     public fun offer(element: E): Boolean
 
     /**
-     * Closes this channel with an optional exceptional [cause].
+     * Closes this channel.
      * This is an idempotent operation -- repeated invocations of this function have no effect and return `false`.
      * Conceptually, its sends a special "close token" over this channel.
      *
@@ -110,11 +119,14 @@
      *
      * ```
      *
+     * **Note: This is an experimental api.** This function may change its semantics, parameters or return type in the future.
+     *
      * @throws UnsupportedOperationException if underlying channel doesn't support [invokeOnClose].
      * Implementation note: currently, [invokeOnClose] is unsupported only by Rx-like integrations
      *
      * @throws IllegalStateException if another handler was already registered
      */
+    @ExperimentalCoroutinesApi
     public fun invokeOnClose(handler: (cause: Throwable?) -> Unit)
 }
 
@@ -128,13 +140,19 @@
      * throws [ClosedReceiveChannelException]. If the channel was closed because of the exception, it
      * is considered closed, too, but it is called a _failed_ channel. All suspending attempts to receive
      * an element from a failed channel throw the original [close][SendChannel.close] cause exception.
+     *
+     * **Note: This is an experimental api.** This property may change its semantics and/or name in the future.
      */
+    @ExperimentalCoroutinesApi
     public val isClosedForReceive: Boolean
 
     /**
      * Returns `true` if the channel is empty (contains no elements) and the [receive] attempt will suspend.
      * This function returns `false` for [isClosedForReceive] channel.
+     *
+     * **Note: This is an experimental api.** This property may change its semantics and/or name in the future.
      */
+    @ExperimentalCoroutinesApi
     public val isEmpty: Boolean
 
     /**
@@ -187,7 +205,10 @@
      *
      * This function can be used in [select] invocation with [onReceiveOrNull] clause.
      * Use [poll] to try receiving from this channel without waiting.
+     *
+     * **Note: This is an experimental api.** This function may be replaced with a better on in the future.
      */
+    @ExperimentalCoroutinesApi
     public suspend fun receiveOrNull(): E?
 
     /**
@@ -195,7 +216,10 @@
      * is received from the channel or selects with `null` if if the channel
      * [isClosedForReceive] without cause. The [select] invocation fails with
      * the original [close][SendChannel.close] cause exception if the channel has _failed_.
+     *
+     * **Note: This is an experimental api.** This function may be replaced with a better on in the future.
      */
+    @ExperimentalCoroutinesApi
     public val onReceiveOrNull: SelectClause1<E?>
 
     /**
@@ -213,6 +237,19 @@
     public operator fun iterator(): ChannelIterator<E>
 
     /**
+     * Cancels reception of remaining elements from this channel. This function closes the channel
+     * and removes all buffered sent elements from it.
+     * This function returns `true` if the channel was not closed previously, or `false` otherwise.
+     *
+     * Immediately after invocation of this function [isClosedForReceive] and
+     * [isClosedForSend][SendChannel.isClosedForSend]
+     * on the side of [SendChannel] start returning `true`, so all attempts to send to this channel
+     * afterwards will throw [ClosedSendChannelException], while attempts to receive will throw
+     * [ClosedReceiveChannelException].
+     */
+    public fun cancel(): Boolean
+
+    /**
      * Cancels reception of remaining elements from this channel. This function closes the channel with
      * the specified cause (unless it was already closed) and removes all buffered sent elements from it.
      * This function returns `true` if the channel was not closed previously, or `false` otherwise.
@@ -224,7 +261,11 @@
      * [ClosedReceiveChannelException] if it was cancelled without a cause.
      * A channel that was cancelled with non-null [cause] is called a _failed_ channel. Attempts to send or
      * receive on a failed channel throw the specified [cause] exception.
+     *
+     * **Note: This is an experimental api.** Semantics of _cancelling_ a channel with exception may
+     *         change in the future or this feature may be completely removed.
      */
+    @ExperimentalCoroutinesApi
     public fun cancel(cause: Throwable? = null): Boolean
 }
 
@@ -282,7 +323,28 @@
  * Conceptually, a channel is similar to [BlockingQueue][java.util.concurrent.BlockingQueue],
  * but it has suspending operations instead of blocking ones and it can be closed.
  *
- * See `Channel(capacity)` factory function for the description of available channel implementations.
+ * `Channel(capacity)` factory function is used to create channels of different kind depending on
+ * the value of `capacity` integer:
+ *
+ * * When `capacity` is 0 -- it creates `RendezvousChannel`.
+ *   This channel does not have any buffer at all. An element is transferred from sender
+ *   to receiver only when [send] and [receive] invocations meet in time (rendezvous), so [send] suspends
+ *   until another coroutine invokes [receive] and [receive] suspends until another coroutine invokes [send].
+ *
+ * * When `capacity` is [Channel.UNLIMITED] -- it creates `LinkedListChannel`.
+ *   This is a channel with linked-list buffer of a unlimited capacity (limited only by available memory).
+ *   Sender to this channel never suspends and [offer] always returns `true`.
+ *
+ * * When `capacity` is [Channel.CONFLATED] -- it creates `ConflatedChannel`.
+ *   This channel buffers at most one element and conflates all subsequent `send` and `offer` invocations,
+ *   so that the receiver always gets the most recently sent element.
+ *   Back-to-send sent elements are _conflated_ -- only the the most recently sent element is received,
+ *   while previously sent elements **are lost**.
+ *   Sender to this channel never suspends and [offer] always returns `true`.
+ *
+ * * When `capacity` is positive, but less than [UNLIMITED] -- it creates [ArrayChannel].
+ *   This channel has an array buffer of a fixed `capacity`.
+ *   Sender suspends only when buffer is fully and receiver suspends only when buffer is empty.
  */
 public interface Channel<E> : SendChannel<E>, ReceiveChannel<E> {
     /**
@@ -290,14 +352,17 @@
      */
     public companion object Factory {
         /**
-         * Requests channel with unlimited capacity buffer in `Channel(...)` factory function --
-         * the [LinkedListChannel] gets created.
+         * Requests channel with unlimited capacity buffer in `Channel(...)` factory function
          */
         public const val UNLIMITED = Int.MAX_VALUE
 
         /**
-         * Requests conflated channel in `Channel(...)` factory function --
-         * the [ConflatedChannel] gets created.
+         * Requests rendezvous channel in `Channel(...)` factory function -- the `RendezvousChannel` gets created.
+         */
+        public const val RENDEZVOUS = 0
+
+        /**
+         * Requests conflated channel in `Channel(...)` factory function -- the `ConflatedChannel` gets created.
          */
         public const val CONFLATED = -1
 
@@ -313,21 +378,18 @@
 /**
  * Creates a channel without a buffer -- [RendezvousChannel].
  */
+@Deprecated(level = DeprecationLevel.HIDDEN, message = "binary compatibility")
 public fun <E> Channel(): Channel<E> = RendezvousChannel<E>()
 
 /**
  * Creates a channel with the specified buffer capacity (or without a buffer by default).
- *
- * The resulting channel type depends on the specified [capacity] parameter:
- * * when `capacity` is 0 -- creates [RendezvousChannel] without a buffer;
- * * when `capacity` is [Channel.UNLIMITED] -- creates [LinkedListChannel] with buffer of unlimited size;
- * * when `capacity` is [Channel.CONFLATED] -- creates [ConflatedChannel] that conflates back-to-back sends;
- * * when `capacity` is positive, but less than [UNLIMITED] -- creates [ArrayChannel] with a buffer of the specified `capacity`;
- * * otherwise -- throws [IllegalArgumentException].
+ * See [Channel] interface documentation for details.
+ * 
+ * @throws IllegalArgumentException when [capacity] < -1
  */
-public fun <E> Channel(capacity: Int): Channel<E> =
+public fun <E> Channel(capacity: Int = 0): Channel<E> =
     when (capacity) {
-        0 -> RendezvousChannel()
+        RENDEZVOUS -> RendezvousChannel()
         UNLIMITED -> LinkedListChannel()
         CONFLATED -> ConflatedChannel()
         else -> ArrayChannel(capacity)
@@ -345,4 +407,5 @@
  * channel that was closed without a cause. A _failed_ channel rethrows the original [close][SendChannel.close] cause
  * exception on receive attempts.
  */
+// todo: explain when this exception is thrown
 public class ClosedReceiveChannelException(message: String?) : NoSuchElementException(message)
diff --git a/common/kotlinx-coroutines-core-common/src/channels/ChannelCoroutine.kt b/common/kotlinx-coroutines-core-common/src/channels/ChannelCoroutine.kt
index d2752d4..dfb5112 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/ChannelCoroutine.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/ChannelCoroutine.kt
@@ -14,6 +14,8 @@
 ) : AbstractCoroutine<Unit>(parentContext, active), Channel<E> by _channel {
     val channel: Channel<E> get() = this
 
+    override fun cancel() = cancel(null)
+
     override fun cancel(cause: Throwable?): Boolean {
         val wasCancelled = _channel.cancel(cause)
         if (wasCancelled) super.cancel(cause) // cancel the job
diff --git a/common/kotlinx-coroutines-core-common/src/channels/Channels.common.kt b/common/kotlinx-coroutines-core-common/src/channels/Channels.common.kt
index 8ad0db7..f52a3ea 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/Channels.common.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/Channels.common.kt
@@ -18,6 +18,7 @@
 /**
  * Returns a channel to read all element of the [Iterable].
  */
+@Deprecated("No replacement")
 public fun <E> Iterable<E>.asReceiveChannel(context: CoroutineContext = Dispatchers.Unconfined): ReceiveChannel<E> =
     GlobalScope.produce(context) {
         for (element in this@asReceiveChannel)
@@ -27,6 +28,7 @@
 /**
  * Returns a channel to read all element of the [Sequence].
  */
+@Deprecated("No replacement")
 public fun <E> Sequence<E>.asReceiveChannel(context: CoroutineContext = Dispatchers.Unconfined): ReceiveChannel<E> =
     GlobalScope.produce(context) {
         for (element in this@asReceiveChannel)
@@ -38,7 +40,11 @@
 /**
  * Opens subscription to this [BroadcastChannel] and makes sure that the given [block] consumes all elements
  * from it by always invoking [cancel][ReceiveChannel.cancel] after the execution of the block.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public inline fun <E, R> BroadcastChannel<E>.consume(block: ReceiveChannel<E>.() -> R): R {
     val channel = openSubscription()
     try {
@@ -50,7 +56,11 @@
 
 /**
  * Subscribes to this [BroadcastChannel] and performs the specified action for each received element.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> BroadcastChannel<E>.consumeEach(action: (E) -> Unit) =
     consume {
         for (element in this) action(element)
@@ -74,7 +84,11 @@
  * immediately throws an [IllegalStateException].
  * See [this issue](https://github.com/Kotlin/kotlinx.coroutines/issues/167)
  * for details.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public fun ReceiveChannel<*>.consumes(): CompletionHandler =
     { cause: Throwable? -> cancel(cause) }
 
@@ -82,7 +96,11 @@
  * Returns a [CompletionHandler] that invokes [cancel][ReceiveChannel.cancel] on all the
  * specified [ReceiveChannel] instances with the corresponding cause.
  * See also [ReceiveChannel.consumes()] for a version on one channel.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public fun consumesAll(vararg channels: ReceiveChannel<*>): CompletionHandler =
     { cause: Throwable? ->
         var exception: Throwable? = null
@@ -110,7 +128,11 @@
  * for details.
  *
  * The operation is _terminal_.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public inline fun <E, R> ReceiveChannel<E>.consume(block: ReceiveChannel<E>.() -> R): R {
     var cause: Throwable? = null
     try {
@@ -134,7 +156,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.consumeEach(action: (E) -> Unit) =
     consume {
         for (e in this) action(e)
@@ -152,7 +178,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.consumeEachIndexed(action: (IndexedValue<E>) -> Unit) {
     var index = 0
     consumeEach {
@@ -165,7 +195,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.elementAt(index: Int): E =
     elementAtOrElse(index) { throw IndexOutOfBoundsException("ReceiveChannel doesn't contain element at index $index.") }
 
@@ -174,7 +208,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.elementAtOrElse(index: Int, defaultValue: (Int) -> E): E =
     consume {
         if (index < 0)
@@ -192,7 +230,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.elementAtOrNull(index: Int): E? =
     consume {
         if (index < 0)
@@ -210,7 +252,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.find(predicate: (E) -> Boolean): E? =
     firstOrNull(predicate)
 
@@ -219,7 +265,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.findLast(predicate: (E) -> Boolean): E? =
     lastOrNull(predicate)
 
@@ -229,7 +279,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.first(): E =
     consume {
         val iterator = iterator()
@@ -244,7 +298,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.first(predicate: (E) -> Boolean): E {
     consumeEach {
         if (predicate(it)) return it
@@ -257,7 +315,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.firstOrNull(): E? =
     consume {
         val iterator = iterator()
@@ -271,7 +333,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public inline suspend fun <E> ReceiveChannel<E>.firstOrNull(predicate: (E) -> Boolean): E? {
     consumeEach {
         if (predicate(it)) return it
@@ -284,7 +350,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.indexOf(element: E): Int {
     var index = 0
     consumeEach {
@@ -300,7 +370,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.indexOfFirst(predicate: (E) -> Boolean): Int {
     var index = 0
     consumeEach {
@@ -316,7 +390,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public inline suspend fun <E> ReceiveChannel<E>.indexOfLast(predicate: (E) -> Boolean): Int {
     var lastIndex = -1
     var index = 0
@@ -334,7 +412,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.last(): E =
     consume {
         val iterator = iterator()
@@ -352,7 +434,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.last(predicate: (E) -> Boolean): E {
     var last: E? = null
     var found = false
@@ -372,7 +458,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.lastIndexOf(element: E): Int {
     var lastIndex = -1
     var index = 0
@@ -389,7 +479,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.lastOrNull(): E? =
     consume {
         val iterator = iterator()
@@ -406,7 +500,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.lastOrNull(predicate: (E) -> Boolean): E? {
     var last: E? = null
     consumeEach {
@@ -422,7 +520,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.single(): E =
     consume {
         val iterator = iterator()
@@ -439,7 +541,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.single(predicate: (E) -> Boolean): E {
     var single: E? = null
     var found = false
@@ -460,7 +566,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.singleOrNull(): E? =
     consume {
         val iterator = iterator()
@@ -477,7 +587,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.singleOrNull(predicate: (E) -> Boolean): E? {
     var single: E? = null
     var found = false
@@ -497,7 +611,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public fun <E> ReceiveChannel<E>.drop(n: Int, context: CoroutineContext = Dispatchers.Unconfined): ReceiveChannel<E> =
     GlobalScope.produce(context, onCompletion = consumes()) {
         require(n >= 0) { "Requested element count $n is less than zero." }
@@ -518,7 +636,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.dropWhile(context: CoroutineContext = Dispatchers.Unconfined, predicate: suspend (E) -> Boolean): ReceiveChannel<E> =
     GlobalScope.produce(context, onCompletion = consumes()) {
@@ -538,7 +660,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.filter(context: CoroutineContext = Dispatchers.Unconfined, predicate: suspend (E) -> Boolean): ReceiveChannel<E> =
     GlobalScope.produce(context, onCompletion = consumes()) {
@@ -554,7 +680,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.filterIndexed(context: CoroutineContext = Dispatchers.Unconfined, predicate: suspend (index: Int, E) -> Boolean): ReceiveChannel<E> =
     GlobalScope.produce(context, onCompletion = consumes()) {
@@ -571,7 +701,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.filterIndexedTo(destination: C, predicate: (index: Int, E) -> Boolean): C {
     consumeEachIndexed { (index, element) ->
         if (predicate(index, element)) destination.add(element)
@@ -586,7 +720,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, C : SendChannel<E>> ReceiveChannel<E>.filterIndexedTo(destination: C, predicate: (index: Int, E) -> Boolean): C {
     consumeEachIndexed { (index, element) ->
         if (predicate(index, element)) destination.send(element)
@@ -599,7 +737,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.filterNot(context: CoroutineContext = Dispatchers.Unconfined, predicate: suspend (E) -> Boolean): ReceiveChannel<E> =
     filter(context) { !predicate(it) }
@@ -615,7 +757,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 @Suppress("UNCHECKED_CAST")
 public fun <E : Any> ReceiveChannel<E?>.filterNotNull(): ReceiveChannel<E> =
     filter { it != null } as ReceiveChannel<E>
@@ -625,7 +771,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E : Any, C : MutableCollection<in E>> ReceiveChannel<E?>.filterNotNullTo(destination: C): C {
     consumeEach {
         if (it != null) destination.add(it)
@@ -638,7 +788,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E : Any, C : SendChannel<E>> ReceiveChannel<E?>.filterNotNullTo(destination: C): C {
     consumeEach {
         if (it != null) destination.send(it)
@@ -651,7 +805,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.filterNotTo(destination: C, predicate: (E) -> Boolean): C {
     consumeEach {
         if (!predicate(it)) destination.add(it)
@@ -664,7 +822,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, C : SendChannel<E>> ReceiveChannel<E>.filterNotTo(destination: C, predicate: (E) -> Boolean): C {
     consumeEach {
         if (!predicate(it)) destination.send(it)
@@ -677,7 +839,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.filterTo(destination: C, predicate: (E) -> Boolean): C {
     consumeEach {
         if (predicate(it)) destination.add(it)
@@ -690,7 +856,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, C : SendChannel<E>> ReceiveChannel<E>.filterTo(destination: C, predicate: (E) -> Boolean): C {
     consumeEach {
         if (predicate(it)) destination.send(it)
@@ -703,7 +873,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public fun <E> ReceiveChannel<E>.take(n: Int, context: CoroutineContext = Dispatchers.Unconfined): ReceiveChannel<E> =
     GlobalScope.produce(context, onCompletion = consumes()) {
         if (n == 0) return@produce
@@ -722,7 +896,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E> ReceiveChannel<E>.takeWhile(context: CoroutineContext = Dispatchers.Unconfined, predicate: suspend (E) -> Boolean): ReceiveChannel<E> =
     GlobalScope.produce(context, onCompletion = consumes()) {
@@ -742,7 +920,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K, V> ReceiveChannel<E>.associate(transform: (E) -> Pair<K, V>): Map<K, V> =
     associateTo(LinkedHashMap(), transform)
 
@@ -756,7 +938,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K> ReceiveChannel<E>.associateBy(keySelector: (E) -> K): Map<K, E> =
     associateByTo(LinkedHashMap(), keySelector)
 
@@ -769,7 +955,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K, V> ReceiveChannel<E>.associateBy(keySelector: (E) -> K, valueTransform: (E) -> V): Map<K, V> =
     associateByTo(LinkedHashMap(), keySelector, valueTransform)
 
@@ -782,7 +972,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K, M : MutableMap<in K, in E>> ReceiveChannel<E>.associateByTo(destination: M, keySelector: (E) -> K): M {
     consumeEach {
         destination.put(keySelector(it), it)
@@ -799,7 +993,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K, V, M : MutableMap<in K, in V>> ReceiveChannel<E>.associateByTo(destination: M, keySelector: (E) -> K, valueTransform: (E) -> V): M {
     consumeEach {
         destination.put(keySelector(it), valueTransform(it))
@@ -815,7 +1013,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K, V, M : MutableMap<in K, in V>> ReceiveChannel<E>.associateTo(destination: M, transform: (E) -> Pair<K, V>): M {
     consumeEach {
         destination += transform(it)
@@ -829,7 +1031,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E, C : SendChannel<E>> ReceiveChannel<E>.toChannel(destination: C): C {
     consumeEach {
         destination.send(it)
@@ -842,7 +1048,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E, C : MutableCollection<in E>> ReceiveChannel<E>.toCollection(destination: C): C {
     consumeEach {
         destination.add(it)
@@ -864,7 +1074,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <K, V> ReceiveChannel<Pair<K, V>>.toMap(): Map<K, V> =
     toMap(LinkedHashMap())
 
@@ -873,7 +1087,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <K, V, M : MutableMap<in K, in V>> ReceiveChannel<Pair<K, V>>.toMap(destination: M): M {
     consumeEach {
         destination += it
@@ -886,7 +1104,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.toMutableList(): MutableList<E> =
     toCollection(ArrayList())
 
@@ -897,7 +1119,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.toSet(): Set<E> =
     this.toMutableSet()
 
@@ -906,7 +1132,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R> ReceiveChannel<E>.flatMap(context: CoroutineContext = Dispatchers.Unconfined, transform: suspend (E) -> ReceiveChannel<R>): ReceiveChannel<R> =
     GlobalScope.produce(context, onCompletion = consumes()) {
@@ -923,7 +1153,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K> ReceiveChannel<E>.groupBy(keySelector: (E) -> K): Map<K, List<E>> =
     groupByTo(LinkedHashMap(), keySelector)
 
@@ -936,7 +1170,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K, V> ReceiveChannel<E>.groupBy(keySelector: (E) -> K, valueTransform: (E) -> V): Map<K, List<V>> =
     groupByTo(LinkedHashMap(), keySelector, valueTransform)
 
@@ -948,7 +1186,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K, M : MutableMap<in K, MutableList<E>>> ReceiveChannel<E>.groupByTo(destination: M, keySelector: (E) -> K): M {
     consumeEach {
         val key = keySelector(it)
@@ -967,7 +1209,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, K, V, M : MutableMap<in K, MutableList<V>>> ReceiveChannel<E>.groupByTo(destination: M, keySelector: (E) -> K, valueTransform: (E) -> V): M {
     consumeEach {
         val key = keySelector(it)
@@ -1000,7 +1246,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R> ReceiveChannel<E>.mapIndexed(context: CoroutineContext = Dispatchers.Unconfined, transform: suspend (index: Int, E) -> R): ReceiveChannel<R> =
     GlobalScope.produce(context, onCompletion = consumes()) {
@@ -1018,7 +1268,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R : Any> ReceiveChannel<E>.mapIndexedNotNull(context: CoroutineContext = Dispatchers.Unconfined, transform: suspend (index: Int, E) -> R?): ReceiveChannel<R> =
     mapIndexed(context, transform).filterNotNull()
@@ -1031,7 +1285,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R : Any, C : MutableCollection<in R>> ReceiveChannel<E>.mapIndexedNotNullTo(destination: C, transform: (index: Int, E) -> R?): C {
     consumeEachIndexed { (index, element) ->
         transform(index, element)?.let { destination.add(it) }
@@ -1047,7 +1305,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R : Any, C : SendChannel<R>> ReceiveChannel<E>.mapIndexedNotNullTo(destination: C, transform: (index: Int, E) -> R?): C {
     consumeEachIndexed { (index, element) ->
         transform(index, element)?.let { destination.send(it) }
@@ -1063,7 +1325,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R, C : MutableCollection<in R>> ReceiveChannel<E>.mapIndexedTo(destination: C, transform: (index: Int, E) -> R): C {
     var index = 0
     consumeEach {
@@ -1080,7 +1346,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R, C : SendChannel<R>> ReceiveChannel<E>.mapIndexedTo(destination: C, transform: (index: Int, E) -> R): C {
     var index = 0
     consumeEach {
@@ -1095,7 +1365,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R : Any> ReceiveChannel<E>.mapNotNull(context: CoroutineContext = Dispatchers.Unconfined, transform: suspend (E) -> R?): ReceiveChannel<R> =
     map(context, transform).filterNotNull()
@@ -1106,7 +1380,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R : Any, C : MutableCollection<in R>> ReceiveChannel<E>.mapNotNullTo(destination: C, transform: (E) -> R?): C {
     consumeEach {
         transform(it)?.let { destination.add(it) }
@@ -1120,7 +1398,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R : Any, C : SendChannel<R>> ReceiveChannel<E>.mapNotNullTo(destination: C, transform: (E) -> R?): C {
     consumeEach {
         transform(it)?.let { destination.send(it) }
@@ -1134,7 +1416,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R, C : MutableCollection<in R>> ReceiveChannel<E>.mapTo(destination: C, transform: (E) -> R): C {
     consumeEach {
         destination.add(transform(it))
@@ -1148,7 +1434,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R, C : SendChannel<R>> ReceiveChannel<E>.mapTo(destination: C, transform: (E) -> R): C {
     consumeEach {
         destination.send(transform(it))
@@ -1161,7 +1451,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public fun <E> ReceiveChannel<E>.withIndex(context: CoroutineContext = Dispatchers.Unconfined): ReceiveChannel<IndexedValue<E>> =
     GlobalScope.produce(context, onCompletion = consumes()) {
         var index = 0
@@ -1177,7 +1471,11 @@
  *
  * The operation is _intermediate_ and _stateful_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public fun <E> ReceiveChannel<E>.distinct(): ReceiveChannel<E> =
     this.distinctBy { it }
 
@@ -1189,7 +1487,11 @@
  *
  * The operation is _intermediate_ and _stateful_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark predicate with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, K> ReceiveChannel<E>.distinctBy(context: CoroutineContext = Dispatchers.Unconfined, selector: suspend (E) -> K): ReceiveChannel<E> =
     GlobalScope.produce(context, onCompletion = consumes()) {
@@ -1210,7 +1512,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.toMutableSet(): MutableSet<E> =
     toCollection(LinkedHashSet())
 
@@ -1219,7 +1525,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.all(predicate: (E) -> Boolean): Boolean {
     consumeEach {
         if (!predicate(it)) return false
@@ -1232,7 +1542,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.any(): Boolean =
     consume {
         return iterator().hasNext()
@@ -1243,7 +1557,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.any(predicate: (E) -> Boolean): Boolean {
     consumeEach {
         if (predicate(it)) return true
@@ -1256,7 +1574,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.count(): Int {
     var count = 0
     consumeEach { count++ }
@@ -1268,7 +1590,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.count(predicate: (E) -> Boolean): Int {
     var count = 0
     consumeEach {
@@ -1282,7 +1608,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R> ReceiveChannel<E>.fold(initial: R, operation: (acc: R, E) -> R): R {
     var accumulator = initial
     consumeEach {
@@ -1299,7 +1629,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R> ReceiveChannel<E>.foldIndexed(initial: R, operation: (index: Int, acc: R, E) -> R): R {
     var index = 0
     var accumulator = initial
@@ -1314,7 +1648,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R : Comparable<R>> ReceiveChannel<E>.maxBy(selector: (E) -> R): E? =
     consume {
         val iterator = iterator()
@@ -1337,7 +1675,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.maxWith(comparator: Comparator<in E>): E? =
     consume {
         val iterator = iterator()
@@ -1355,7 +1697,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E, R : Comparable<R>> ReceiveChannel<E>.minBy(selector: (E) -> R): E? =
     consume {
         val iterator = iterator()
@@ -1378,7 +1724,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.minWith(comparator: Comparator<in E>): E? =
     consume {
         val iterator = iterator()
@@ -1396,7 +1746,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend fun <E> ReceiveChannel<E>.none(): Boolean =
     consume {
         return !iterator().hasNext()
@@ -1407,7 +1761,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.none(predicate: (E) -> Boolean): Boolean {
     consumeEach {
         if (predicate(it)) return false
@@ -1420,7 +1778,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <S, E : S> ReceiveChannel<E>.reduce(operation: (acc: S, E) -> S): S =
     consume {
         val iterator = this.iterator()
@@ -1440,7 +1802,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark operation with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public suspend inline fun <S, E : S> ReceiveChannel<E>.reduceIndexed(operation: (index: Int, acc: S, E) -> S): S =
     consume {
@@ -1459,7 +1825,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.sumBy(selector: (E) -> Int): Int {
     var sum = 0
     consumeEach {
@@ -1473,7 +1843,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.sumByDouble(selector: (E) -> Double): Double {
     var sum = 0.0
     consumeEach {
@@ -1487,7 +1861,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public fun <E : Any> ReceiveChannel<E?>.requireNoNulls(): ReceiveChannel<E> =
     map { it ?: throw IllegalArgumentException("null element found in $this.") }
 
@@ -1498,7 +1876,11 @@
  *
  * The operation is _terminal_.
  * This function [consumes][ReceiveChannel.consume] all elements of the original [ReceiveChannel].
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public suspend inline fun <E> ReceiveChannel<E>.partition(predicate: (E) -> Boolean): Pair<List<E>, List<E>> {
     val first = ArrayList<E>()
     val second = ArrayList<E>()
@@ -1518,7 +1900,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][ReceiveChannel.consume] all elements of both the original [ReceiveChannel] and the `other` one.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 public infix fun <E, R> ReceiveChannel<E>.zip(other: ReceiveChannel<R>): ReceiveChannel<Pair<E, R>> =
     zip(other) { t1, t2 -> t1 to t2 }
 
@@ -1527,7 +1913,11 @@
  *
  * The operation is _intermediate_ and _stateless_.
  * This function [consumes][consume] all elements of both the original [ReceiveChannel] and the `other` one.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 // todo: mark transform with crossinline modifier when it is supported: https://youtrack.jetbrains.com/issue/KT-19159
 public fun <E, R, V> ReceiveChannel<E>.zip(other: ReceiveChannel<R>, context: CoroutineContext = Dispatchers.Unconfined, transform: (a: E, b: R) -> V): ReceiveChannel<V> =
     GlobalScope.produce(context, onCompletion = consumesAll(this, other)) {
diff --git a/common/kotlinx-coroutines-core-common/src/channels/ConflatedBroadcastChannel.kt b/common/kotlinx-coroutines-core-common/src/channels/ConflatedBroadcastChannel.kt
index 3bdd4c4..a91129d 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/ConflatedBroadcastChannel.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/ConflatedBroadcastChannel.kt
@@ -5,6 +5,7 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.atomicfu.*
+import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.internal.*
 import kotlinx.coroutines.experimental.intrinsics.*
 import kotlinx.coroutines.experimental.selects.*
@@ -23,7 +24,10 @@
  * This implementation is fully lock-free. In this implementation
  * [opening][openSubscription] and [closing][ReceiveChannel.cancel] subscription takes O(N) time, where N is the
  * number of subscribers.
+ *
+ * **Note: This API is experimental.** It may be changed in the future updates.
  */
+@ExperimentalCoroutinesApi
 public class ConflatedBroadcastChannel<E>() : BroadcastChannel<E> {
     /**
      * Creates an instance of this class that already holds a value.
diff --git a/common/kotlinx-coroutines-core-common/src/channels/ConflatedChannel.kt b/common/kotlinx-coroutines-core-common/src/channels/ConflatedChannel.kt
index 5208378..0e322cf 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/ConflatedChannel.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/ConflatedChannel.kt
@@ -4,6 +4,7 @@
 
 package kotlinx.coroutines.experimental.channels
 
+import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.selects.*
 
 /**
@@ -16,8 +17,16 @@
  * This channel is created by `Channel(Channel.CONFLATED)` factory function invocation.
  *
  * This implementation is fully lock-free.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
-public open class ConflatedChannel<E> : AbstractChannel<E>() {
+@InternalCoroutinesApi
+public open class ConflatedChannel<E>
+@Deprecated(
+    "Replace with Channel factory function",
+    replaceWith = ReplaceWith("Channel(Channel.CONFLATED)")
+)
+constructor(): AbstractChannel<E>() {
     protected final override val isBufferAlwaysEmpty: Boolean get() = true
     protected final override val isBufferEmpty: Boolean get() = true
     protected final override val isBufferAlwaysFull: Boolean get() = false
diff --git a/common/kotlinx-coroutines-core-common/src/channels/LinkedListChannel.kt b/common/kotlinx-coroutines-core-common/src/channels/LinkedListChannel.kt
index 885ba7a..5b017ca 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/LinkedListChannel.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/LinkedListChannel.kt
@@ -4,6 +4,7 @@
 
 package kotlinx.coroutines.experimental.channels
 
+import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.selects.*
 
 /**
@@ -13,8 +14,16 @@
  * This channel is created by `Channel(Channel.UNLIMITED)` factory function invocation.
  *
  * This implementation is fully lock-free.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
-public open class LinkedListChannel<E> : AbstractChannel<E>() {
+@InternalCoroutinesApi
+public open class LinkedListChannel<E>
+@Deprecated(
+    "Replace with Channel factory function",
+    replaceWith = ReplaceWith("Channel(Channel.UNLIMITED)")
+)
+constructor() : AbstractChannel<E>() {
     protected final override val isBufferAlwaysEmpty: Boolean get() = true
     protected final override val isBufferEmpty: Boolean get() = true
     protected final override val isBufferAlwaysFull: Boolean get() = false
diff --git a/common/kotlinx-coroutines-core-common/src/channels/Produce.kt b/common/kotlinx-coroutines-core-common/src/channels/Produce.kt
index 7e13768..b7e75de 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/Produce.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/Produce.kt
@@ -10,7 +10,11 @@
 
 /**
  * Scope for [produce][CoroutineScope.produce] coroutine builder.
+ *
+ * **Note: This is an experimental api.** Behaviour of producers that work as children in a parent scope with respect
+ *        to cancellation and error handling may change in the future.
  */
+@ExperimentalCoroutinesApi
 public interface ProducerScope<in E> : CoroutineScope, SendChannel<E> {
     /**
      * A reference to the channel that this coroutine [sends][send] elements to.
@@ -51,20 +55,36 @@
  * Uncaught exceptions in this coroutine close the channel with this exception as a cause and
  * the resulting channel becomes _failed_, so that any attempt to receive from such a channel throws exception.
  *
- * The kind of the resulting channel depends on the specified [capacity] parameter:
- * * when `capacity` is 0 (default) -- uses [RendezvousChannel] without a buffer;
- * * when `capacity` is [Channel.UNLIMITED] -- uses [LinkedListChannel] with buffer of unlimited size;
- * * when `capacity` is [Channel.CONFLATED] -- uses [ConflatedChannel] that conflates back-to-back sends;
- * * when `capacity` is positive, but less than [UNLIMITED] -- uses [ArrayChannel] with a buffer of the specified `capacity`;
- * * otherwise -- throws [IllegalArgumentException].
+ * The kind of the resulting channel depends on the specified [capacity] parameter.
+ * See [Channel] interface documentation for details.
  *
  * See [newCoroutineContext] for a description of debugging facilities that are available for newly created coroutine.
  *
+ * **Note: This is an experimental api.** Behaviour of producers that work as children in a parent scope with respect
+ *        to cancellation and error handling may change in the future.
+ *
  * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
  * @param capacity capacity of the channel's buffer (no buffer by default).
- * @param onCompletion optional completion handler for the producer coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
+@ExperimentalCoroutinesApi
+public fun <E> CoroutineScope.produce(
+    context: CoroutineContext = EmptyCoroutineContext,
+    capacity: Int = 0,
+    block: suspend ProducerScope<E>.() -> Unit
+): ReceiveChannel<E> {
+    val channel = Channel<E>(capacity)
+    val newContext = newCoroutineContext(context)
+    val coroutine = ProducerCoroutine(newContext, channel)
+    coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
+    return coroutine
+}
+
+/**
+ * @suppress **This an internal API and should not be used from general code.**
+ *           onCompletion parameter will be redesigned.
+ */
+@InternalCoroutinesApi
 public fun <E> CoroutineScope.produce(
     context: CoroutineContext = EmptyCoroutineContext,
     capacity: Int = 0,
diff --git a/common/kotlinx-coroutines-core-common/src/channels/RendezvousChannel.kt b/common/kotlinx-coroutines-core-common/src/channels/RendezvousChannel.kt
index cac7d5b..0c7f2d0 100644
--- a/common/kotlinx-coroutines-core-common/src/channels/RendezvousChannel.kt
+++ b/common/kotlinx-coroutines-core-common/src/channels/RendezvousChannel.kt
@@ -4,6 +4,8 @@
 
 package kotlinx.coroutines.experimental.channels
 
+import kotlinx.coroutines.experimental.*
+
 /**
  * Rendezvous channel. This channel does not have any buffer at all. An element is transferred from sender
  * to receiver only when [send] and [receive] invocations meet in time (rendezvous), so [send] suspends
@@ -12,8 +14,16 @@
  * Use `Channel()` factory function to conveniently create an instance of rendezvous channel.
  *
  * This implementation is fully lock-free.
+ * 
+ * @suppress **This an internal API and should not be used from general code.**
  */
-public open class RendezvousChannel<E> : AbstractChannel<E>() {
+@InternalCoroutinesApi
+public open class RendezvousChannel<E>
+@Deprecated(
+    "Replace with Channel factory function",
+    replaceWith = ReplaceWith("Channel(Channel.RENDEZVOUS)")
+)
+constructor() : AbstractChannel<E>() {
     protected final override val isBufferAlwaysEmpty: Boolean get() = true
     protected final override val isBufferEmpty: Boolean get() = true
     protected final override val isBufferAlwaysFull: Boolean get() = true
diff --git a/common/kotlinx-coroutines-core-common/src/internal/Concurrent.common.kt b/common/kotlinx-coroutines-core-common/src/internal/Concurrent.common.kt
index ac3c9c0..be4b57c 100644
--- a/common/kotlinx-coroutines-core-common/src/internal/Concurrent.common.kt
+++ b/common/kotlinx-coroutines-core-common/src/internal/Concurrent.common.kt
@@ -5,7 +5,7 @@
 package kotlinx.coroutines.experimental.internal
 
 /**
- * Special kind of list intended to be used as collection of subscribers in [ArrayBroadcastChannel]
+ * Special kind of list intended to be used as collection of subscribers in `ArrayBroadcastChannel`
  * On JVM it's CopyOnWriteList and on JS it's MutableList.
  *
  * Note that this alias is intentionally not named as CopyOnWriteList to avoid accidental misusage outside of ArrayBroadcastChannel
diff --git a/common/kotlinx-coroutines-core-common/src/intrinsics/Cancellable.kt b/common/kotlinx-coroutines-core-common/src/intrinsics/Cancellable.kt
index 4564c2c..5d263f1 100644
--- a/common/kotlinx-coroutines-core-common/src/intrinsics/Cancellable.kt
+++ b/common/kotlinx-coroutines-core-common/src/intrinsics/Cancellable.kt
@@ -11,13 +11,19 @@
 /**
  * Use this function to start coroutine in a cancellable way, so that it can be cancelled
  * while waiting to be dispatched.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun <T> (suspend () -> T).startCoroutineCancellable(completion: Continuation<T>) =
     createCoroutineUnchecked(completion).resumeCancellable(Unit)
 
 /**
  * Use this function to start coroutine in a cancellable way, so that it can be cancelled
  * while waiting to be dispatched.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun <R, T> (suspend (R) -> T).startCoroutineCancellable(receiver: R, completion: Continuation<T>) =
     createCoroutineUnchecked(receiver, completion).resumeCancellable(Unit)
diff --git a/common/kotlinx-coroutines-core-common/src/intrinsics/Undispatched.kt b/common/kotlinx-coroutines-core-common/src/intrinsics/Undispatched.kt
index 80048a8..8daf5da 100644
--- a/common/kotlinx-coroutines-core-common/src/intrinsics/Undispatched.kt
+++ b/common/kotlinx-coroutines-core-common/src/intrinsics/Undispatched.kt
@@ -12,7 +12,10 @@
  * Use this function to restart coroutine directly from inside of [suspendCoroutine],
  * when the code is already in the context of this coroutine.
  * It does not use [ContinuationInterceptor] and does not update context of the current thread.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun <T> (suspend () -> T).startCoroutineUnintercepted(completion: Continuation<T>) {
     startDirect(completion) {
         startCoroutineUninterceptedOrReturn(completion)
@@ -23,7 +26,10 @@
  * Use this function to restart coroutine directly from inside of [suspendCoroutine],
  * when the code is already in the context of this coroutine.
  * It does not use [ContinuationInterceptor] and does not update context of the current thread.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun <R, T> (suspend (R) -> T).startCoroutineUnintercepted(receiver: R, completion: Continuation<T>) {
     startDirect(completion) {
         startCoroutineUninterceptedOrReturn(receiver, completion)
@@ -34,7 +40,10 @@
  * Use this function to start new coroutine in [CoroutineStart.UNDISPATCHED] mode &mdash;
  * immediately execute coroutine in the current thread until next suspension.
  * It does not use [ContinuationInterceptor], but updates the context of the current thread for the new coroutine.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun <T> (suspend () -> T).startCoroutineUndispatched(completion: Continuation<T>) {
     startDirect(completion) {
         withCoroutineContext(completion.context) {
@@ -47,7 +56,10 @@
  * Use this function to start new coroutine in [CoroutineStart.UNDISPATCHED] mode &mdash;
  * immediately execute coroutine in the current thread until next suspension.
  * It does not use [ContinuationInterceptor], but updates the context of the current thread for the new coroutine.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun <R, T> (suspend (R) -> T).startCoroutineUndispatched(receiver: R, completion: Continuation<T>) {
     startDirect(completion) {
         withCoroutineContext(completion.context) {
@@ -76,7 +88,10 @@
  *
  * First, this function initializes parent job from the `parentContext` of this coroutine that was passed to it
  * during construction. Second, it starts the coroutine using [startCoroutineUninterceptedOrReturn].
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun <T> AbstractCoroutine<T>.startUndispatchedOrReturn(block: suspend () -> T): Any? {
     initParentJob()
     return undispatchedResult { block.startCoroutineUninterceptedOrReturn(this) }
@@ -89,7 +104,10 @@
  *
  * First, this function initializes parent job from the `parentContext` of this coroutine that was passed to it
  * during construction. Second, it starts the coroutine using [startCoroutineUninterceptedOrReturn].
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun <T, R> AbstractCoroutine<T>.startUndispatchedOrReturn(receiver: R, block: suspend R.() -> T): Any? {
     initParentJob()
     return undispatchedResult { block.startCoroutineUninterceptedOrReturn(receiver, this) }
diff --git a/common/kotlinx-coroutines-core-common/src/selects/Select.kt b/common/kotlinx-coroutines-core-common/src/selects/Select.kt
index e8f49dc..bbec635 100644
--- a/common/kotlinx-coroutines-core-common/src/selects/Select.kt
+++ b/common/kotlinx-coroutines-core-common/src/selects/Select.kt
@@ -42,10 +42,22 @@
      * Clause that selects the given [block] after a specified timeout passes.
      * If timeout is negative or zero, [block] is selected immediately.
      *
-     * @param time timeout time
-     * @param unit timeout unit (milliseconds by default)
+     * **Note: This is an experimental api.** It may be replaced with light-weight timer/timeout channels in the future.
+     *
+     * @param timeMillis timeout time in milliseconds.
      */
-    public fun onTimeout(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS, block: suspend () -> R)
+    @ExperimentalCoroutinesApi
+    public fun onTimeout(timeMillis: Long, block: suspend () -> R)
+
+    /**
+     * @suppress **Deprecated**: onTimeout(unit.toMillis(time), block)`
+     */
+    @Deprecated(
+        message = "Replace with onTimeout(unit.toMillis(time), block)",
+        replaceWith = ReplaceWith("onTimeout(unit.toMillis(time), block)")
+    )
+    public fun onTimeout(time: Long, unit: TimeUnit = TimeUnit.MILLISECONDS, block: suspend () -> R) =
+        onTimeout(time.convertToMillis(unit), block)
 }
 
 /**
@@ -56,6 +68,7 @@
      * Registers this clause with the specified [select] instance and [block] of code.
      * @suppress **This is unstable API and it is subject to change.**
      */
+    @InternalCoroutinesApi
     public fun <R> registerSelectClause0(select: SelectInstance<R>, block: suspend () -> R)
 }
 
@@ -67,6 +80,7 @@
      * Registers this clause with the specified [select] instance and [block] of code.
      * @suppress **This is unstable API and it is subject to change.**
      */
+    @InternalCoroutinesApi
     public fun <R> registerSelectClause1(select: SelectInstance<R>, block: suspend (Q) -> R)
 }
 
@@ -78,6 +92,7 @@
      * Registers this clause with the specified [select] instance and [block] of code.
      * @suppress **This is unstable API and it is subject to change.**
      */
+    @InternalCoroutinesApi
     public fun <R> registerSelectClause2(select: SelectInstance<R>, param: P, block: suspend (Q) -> R)
 }
 
@@ -87,6 +102,7 @@
  *
  * @suppress **This is unstable API and it is subject to change.**
  */
+@InternalCoroutinesApi
 public interface SelectInstance<in R> {
     /**
      * Returns `true` when this [select] statement had already picked a clause to execute.
@@ -404,8 +420,8 @@
         registerSelectClause2(this@SelectBuilderImpl, param, block)
     }
 
-    override fun onTimeout(time: Long, unit: TimeUnit, block: suspend () -> R) {
-        if (time <= 0L) {
+    override fun onTimeout(timeMillis: Long, block: suspend () -> R) {
+        if (timeMillis <= 0L) {
             if (trySelect(null))
                 block.startCoroutineUnintercepted(completion)
             return
@@ -416,7 +432,7 @@
             if (trySelect(null))
                 block.startCoroutineCancellable(completion) // shall be cancellable while waits for dispatch
         }
-        disposeOnSelect(context.delay.invokeOnTimeout(time, unit, action))
+        disposeOnSelect(context.delay.invokeOnTimeout(timeMillis, action))
     }
 
     private class DisposeNode(
diff --git a/common/kotlinx-coroutines-core-common/src/selects/SelectUnbiased.kt b/common/kotlinx-coroutines-core-common/src/selects/SelectUnbiased.kt
index 05e1bc2..2c84d47 100644
--- a/common/kotlinx-coroutines-core-common/src/selects/SelectUnbiased.kt
+++ b/common/kotlinx-coroutines-core-common/src/selects/SelectUnbiased.kt
@@ -4,7 +4,6 @@
 
 package kotlinx.coroutines.experimental.selects
 
-import kotlinx.coroutines.experimental.timeunit.*
 import kotlin.coroutines.experimental.*
 import kotlin.coroutines.experimental.intrinsics.*
 
@@ -64,7 +63,7 @@
         clauses += { registerSelectClause2(instance, param, block) }
     }
 
-    override fun onTimeout(time: Long, unit: TimeUnit, block: suspend () -> R) {
-        clauses += { instance.onTimeout(time, unit, block) }
+    override fun onTimeout(timeMillis: Long, block: suspend () -> R) {
+        clauses += { instance.onTimeout(timeMillis, block) }
     }
 }
\ No newline at end of file
diff --git a/common/kotlinx-coroutines-core-common/src/selects/WhileSelect.kt b/common/kotlinx-coroutines-core-common/src/selects/WhileSelect.kt
index 8358c19..f9260b9 100644
--- a/common/kotlinx-coroutines-core-common/src/selects/WhileSelect.kt
+++ b/common/kotlinx-coroutines-core-common/src/selects/WhileSelect.kt
@@ -4,6 +4,8 @@
 
 package kotlinx.coroutines.experimental.selects
 
+import kotlinx.coroutines.experimental.*
+
 /**
  * Loops while [select] expression returns `true`.
  *
@@ -21,7 +23,10 @@
  * while(select<Boolean> {
  *    /*body*/
  * }) {}
+ *
+ * **Note: This is an experimental api.** It may be replaced with a higher-performance DSL for selection from loops.
  */
-suspend fun whileSelect(builder: SelectBuilder<Boolean>.() -> Unit) {
+@ExperimentalCoroutinesApi
+public suspend inline fun whileSelect(crossinline builder: SelectBuilder<Boolean>.() -> Unit) {
     while(select<Boolean>(builder)) {}
 }
diff --git a/common/kotlinx-coroutines-core-common/src/sync/Mutex.kt b/common/kotlinx-coroutines-core-common/src/sync/Mutex.kt
index 997be13..896e682 100644
--- a/common/kotlinx-coroutines-core-common/src/sync/Mutex.kt
+++ b/common/kotlinx-coroutines-core-common/src/sync/Mutex.kt
@@ -76,8 +76,9 @@
      */
     public fun holdsLock(owner: Any): Boolean
 
-        /**
-     * Unlocks this mutex. Throws [IllegalStateException] if invoked on a mutex that is not locked.
+    /**
+     * Unlocks this mutex. Throws [IllegalStateException] if invoked on a mutex that is not locked or
+     * was locked with a different owner token (by identity).
      *
      * @param owner Optional owner token for debugging. When `owner` is specified (non-null value) and this mutex
      *        was locked with the different token (by identity), this function throws [IllegalStateException].
diff --git a/common/kotlinx-coroutines-core-common/src/timeunit/TimeUnit.common.kt b/common/kotlinx-coroutines-core-common/src/timeunit/TimeUnit.common.kt
index 3c868df..f10609e 100644
--- a/common/kotlinx-coroutines-core-common/src/timeunit/TimeUnit.common.kt
+++ b/common/kotlinx-coroutines-core-common/src/timeunit/TimeUnit.common.kt
@@ -4,6 +4,11 @@
 
 package kotlinx.coroutines.experimental.timeunit
 
+/*
+ * @suppress **Deprecated** No replacement
+ */
+@Suppress("ACTUAL_WITHOUT_EXPECT")
+@Deprecated(message = "No replacement")
 public expect enum class TimeUnit {
     MILLISECONDS,
     SECONDS;
diff --git a/common/kotlinx-coroutines-core-common/test/AsyncLazyTest.kt b/common/kotlinx-coroutines-core-common/test/AsyncLazyTest.kt
index 714abbf..83be9e6 100644
--- a/common/kotlinx-coroutines-core-common/test/AsyncLazyTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/AsyncLazyTest.kt
@@ -141,7 +141,7 @@
 
     @Test
     fun testCancelBeforeStart() = runTest(
-        expected = { it is JobCancellationException }
+        expected = { it is CancellationException }
     ) {
         expect(1)
         val d = async(start = CoroutineStart.LAZY) {
diff --git a/common/kotlinx-coroutines-core-common/test/AsyncTest.kt b/common/kotlinx-coroutines-core-common/test/AsyncTest.kt
index 09910e0..5ccb97f 100644
--- a/common/kotlinx-coroutines-core-common/test/AsyncTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/AsyncTest.kt
@@ -232,7 +232,7 @@
         try {
             expect(1)
             deferred.await()
-        } catch (e: JobCancellationException) {
+        } catch (e: CancellationException) {
             finish(3)
         }
     }
diff --git a/common/kotlinx-coroutines-core-common/test/CancellableContinuationTest.kt b/common/kotlinx-coroutines-core-common/test/CancellableContinuationTest.kt
index 6288607..c56cc17 100644
--- a/common/kotlinx-coroutines-core-common/test/CancellableContinuationTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/CancellableContinuationTest.kt
@@ -80,7 +80,7 @@
                 suspendCancellableCoroutine<Unit> { c ->
                     continuation = c
                 }
-            } catch (e: JobCancellationException) {
+            } catch (e: CancellationException) {
                 expect(3)
             }
         }
@@ -105,7 +105,7 @@
                 suspendCancellableCoroutine<Unit> { c ->
                     continuation = c
                 }
-            } catch (e: JobCancellationException) {
+            } catch (e: CancellationException) {
                 expect(3)
             }
         }
diff --git a/common/kotlinx-coroutines-core-common/test/CompletableDeferredTest.kt b/common/kotlinx-coroutines-core-common/test/CompletableDeferredTest.kt
index e75fa50..f9a71b8 100644
--- a/common/kotlinx-coroutines-core-common/test/CompletableDeferredTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/CompletableDeferredTest.kt
@@ -2,7 +2,7 @@
  * 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
+@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "DEPRECATION") // KT-21913
 
 package kotlinx.coroutines.experimental
 
diff --git a/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt b/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt
index ff1f987..875f49d 100644
--- a/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt
@@ -118,7 +118,7 @@
             try {
                 callJobScoped()
                 expectUnreached()
-            } catch (e: JobCancellationException) {
+            } catch (e: CancellationException) {
                 expect(5)
                 assertNull(e.cause)
             }
diff --git a/common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt b/common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt
index 99d4a92..db59aa5 100644
--- a/common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/CoroutinesTest.kt
@@ -238,11 +238,10 @@
         // now we have a failed job with TestException
         finish(3)
         try {
-            job.cancelAndJoin() // join should crash on child's exception but it will be wrapped into JobCancellationException
+            job.cancelAndJoin() // join should crash on child's exception but it will be wrapped into CancellationException
         } catch (e: Throwable) {
-            e as JobCancellationException // type assertion
+            e as CancellationException // type assertion
             assertTrue(e.cause is TestException)
-            assertTrue(e.job === coroutineContext[Job])
             throw e
         }
         expectUnreached()
@@ -280,7 +279,7 @@
         expect(3)
         parent.cancelChildren()
         expect(4)
-        parent.joinChildren() // will yield to child
+        parent.children.forEach { it.join() } // will yield to child
         assertTrue(parent.isActive) // make sure it did not cancel parent
         finish(6)
     }
diff --git a/common/kotlinx-coroutines-core-common/test/DelayTest.kt b/common/kotlinx-coroutines-core-common/test/DelayTest.kt
index b98f73f..69cb52e 100644
--- a/common/kotlinx-coroutines-core-common/test/DelayTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/DelayTest.kt
@@ -3,7 +3,7 @@
  * 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
+@file:Suppress("NAMED_ARGUMENTS_NOT_ALLOWED", "DEPRECATION") // KT-21913
 
 package kotlinx.coroutines.experimental
 
@@ -13,22 +13,22 @@
 class DelayTest : TestBase() {
 
     @Test
-    fun testCancellation() = runTest(expected = {it is JobCancellationException}) {
+    fun testCancellation() = runTest(expected = {it is CancellationException }) {
         runAndCancel(3600, TimeUnit.SECONDS)
     }
 
     @Test
-    fun testMaxLongValue()= runTest(expected = {it is JobCancellationException}) {
+    fun testMaxLongValue()= runTest(expected = {it is CancellationException }) {
         runAndCancel(Long.MAX_VALUE)
     }
 
     @Test
-    fun testMaxIntValue()= runTest(expected = {it is JobCancellationException}) {
+    fun testMaxIntValue()= runTest(expected = {it is CancellationException }) {
         runAndCancel(Int.MAX_VALUE.toLong())
     }
 
     @Test
-    fun testOverflowOnUnitConversion()= runTest(expected = {it is JobCancellationException}) {
+    fun testOverflowOnUnitConversion()= runTest(expected = {it is CancellationException }) {
         runAndCancel(Long.MAX_VALUE, TimeUnit.SECONDS)
     }
 
diff --git a/common/kotlinx-coroutines-core-common/test/NonCancellableTest.kt b/common/kotlinx-coroutines-core-common/test/NonCancellableTest.kt
index 7a1dbfe..94050ee 100644
--- a/common/kotlinx-coroutines-core-common/test/NonCancellableTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/NonCancellableTest.kt
@@ -30,7 +30,7 @@
         try {
             job.await()
             expectUnreached()
-        } catch (e: JobCancellationException) {
+        } catch (e: CancellationException) {
             assertNull(e.cause)
             finish(6)
         }
@@ -90,7 +90,7 @@
         try {
             job.await()
             expectUnreached()
-        } catch (e: JobCancellationException) {
+        } catch (e: CancellationException) {
             finish(6)
         }
     }
@@ -119,7 +119,7 @@
         try {
             job.await()
             expectUnreached()
-        } catch (e: JobCancellationException) {
+        } catch (e: CancellationException) {
             assertNull(e.cause)
             finish(7)
         }
diff --git a/common/kotlinx-coroutines-core-common/test/WithContextTest.kt b/common/kotlinx-coroutines-core-common/test/WithContextTest.kt
index 475c37e..d29e71c 100644
--- a/common/kotlinx-coroutines-core-common/test/WithContextTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/WithContextTest.kt
@@ -128,7 +128,7 @@
 
     @Test
     fun testRunCancellableDefault() = runTest(
-        expected = { it is JobCancellationException }
+        expected = { it is CancellationException }
     ) {
         val job = Job()
         job.cancel() // cancel before it has a chance to run
@@ -150,7 +150,7 @@
                 yield() // but will cancel here
                 expectUnreached()
             }
-        } catch (e: JobCancellationException) {
+        } catch (e: CancellationException) {
             // This block should be invoked *after* context body
             finish(3)
         }
@@ -158,7 +158,7 @@
 
     @Test
     fun testRunUndispatchedTryCancel() = runTest(
-        expected = { it is JobCancellationException }
+        expected = { it is CancellationException }
     ) {
         expect(1)
         val job = Job()
@@ -218,7 +218,7 @@
             } catch (e: Throwable) {
                 expect(7)
                 // make sure JCE is thrown
-                assertTrue(e is JobCancellationException, "Caught $e")
+                assertTrue(e is CancellationException, "Caught $e")
             }
         }
 
diff --git a/common/kotlinx-coroutines-core-common/test/WithTimeoutTest.kt b/common/kotlinx-coroutines-core-common/test/WithTimeoutTest.kt
index 40f0e71..2408f77 100644
--- a/common/kotlinx-coroutines-core-common/test/WithTimeoutTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/WithTimeoutTest.kt
@@ -124,7 +124,7 @@
                 "OK"
             }
         } catch (e: CancellationException) {
-            assertEquals("Timed out waiting for 100 MILLISECONDS", e.message)
+            assertEquals("Timed out waiting for 100 ms", e.message)
             finish(3)
         }
     }
diff --git a/common/kotlinx-coroutines-core-common/test/channels/ArrayBroadcastChannelTest.kt b/common/kotlinx-coroutines-core-common/test/channels/ArrayBroadcastChannelTest.kt
index 46db04e..eeed553 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/ArrayBroadcastChannelTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/ArrayBroadcastChannelTest.kt
@@ -11,7 +11,7 @@
 
     @Test
     fun testConcurrentModification() = runTest {
-        val channel = ArrayBroadcastChannel<Int>(1)
+        val channel = BroadcastChannel<Int>(1)
         val s1 = channel.openSubscription()
         val s2 = channel.openSubscription()
 
@@ -35,7 +35,7 @@
     @Test
     fun testBasic() = runTest {
         expect(1)
-        val broadcast = ArrayBroadcastChannel<Int>(1)
+        val broadcast = BroadcastChannel<Int>(1)
         assertFalse(broadcast.isClosedForSend)
         val first = broadcast.openSubscription()
         launch(start = CoroutineStart.UNDISPATCHED) {
@@ -81,7 +81,7 @@
     @Test
     fun testSendSuspend() = runTest {
         expect(1)
-        val broadcast = ArrayBroadcastChannel<Int>(1)
+        val broadcast = BroadcastChannel<Int>(1)
         val first = broadcast.openSubscription()
         launch {
             expect(4)
@@ -100,7 +100,7 @@
     @Test
     fun testConcurrentSendCompletion() = runTest {
         expect(1)
-        val broadcast = ArrayBroadcastChannel<Int>(1)
+        val broadcast = BroadcastChannel<Int>(1)
         val sub = broadcast.openSubscription()
         // launch 3 concurrent senders (one goes buffer, two other suspend)
         for (x in 1..3) {
@@ -126,7 +126,7 @@
     @Test
     fun testForgetUnsubscribed() = runTest {
         expect(1)
-        val broadcast = ArrayBroadcastChannel<Int>(1)
+        val broadcast = BroadcastChannel<Int>(1)
         broadcast.send(1)
         broadcast.send(2)
         broadcast.send(3)
diff --git a/common/kotlinx-coroutines-core-common/test/channels/ArrayChannelTest.kt b/common/kotlinx-coroutines-core-common/test/channels/ArrayChannelTest.kt
index b2e4f05..dc6b047 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/ArrayChannelTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/ArrayChannelTest.kt
@@ -10,7 +10,7 @@
 class ArrayChannelTest : TestBase() {
     @Test
     fun testSimple() = runTest {
-        val q = ArrayChannel<Int>(1)
+        val q = Channel<Int>(1)
         check(q.isEmpty && !q.isFull)
         expect(1)
         val sender = launch {
@@ -39,7 +39,7 @@
 
     @Test
     fun testClosedBufferedReceiveOrNull() = runTest {
-        val q = ArrayChannel<Int>(1)
+        val q = Channel<Int>(1)
         check(q.isEmpty && !q.isFull && !q.isClosedForSend && !q.isClosedForReceive)
         expect(1)
         launch {
@@ -64,7 +64,7 @@
 
     @Test
     fun testClosedExceptions() = runTest {
-        val q = ArrayChannel<Int>(1)
+        val q = Channel<Int>(1)
         expect(1)
         launch {
             expect(4)
@@ -87,7 +87,7 @@
 
     @Test
     fun testOfferAndPool() = runTest {
-        val q = ArrayChannel<Int>(1)
+        val q = Channel<Int>(1)
         assertTrue(q.offer(1))
         expect(1)
         launch {
@@ -117,7 +117,7 @@
 
     @Test
     fun testConsumeAll() = runTest {
-        val q = ArrayChannel<Int>(5)
+        val q = Channel<Int>(5)
         for (i in 1..10) {
             if (i <= 5) {
                 expect(i)
@@ -140,7 +140,7 @@
 
     @Test
     fun testCancelWithCause() = runTest({ it is TestException }) {
-        val channel = ArrayChannel<Int>(5)
+        val channel = Channel<Int>(5)
         channel.cancel(TestException())
         channel.receiveOrNull()
     }
diff --git a/common/kotlinx-coroutines-core-common/test/channels/ChannelsTest.kt b/common/kotlinx-coroutines-core-common/test/channels/ChannelsTest.kt
index b956f6c..bf15962 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/ChannelsTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/ChannelsTest.kt
@@ -170,7 +170,7 @@
         val channel = Channel<Nothing>()
         channel.close()
 
-        assertTrue(emptyList<Nothing>().asReceiveChannel().count() == 0)
+        assertEquals(emptyList<Nothing>().asReceiveChannel().count(), 0)
     }
 
     @Test
@@ -364,7 +364,8 @@
     @Test
     fun testFilterNotNull() = runTest {
         repeat(3) { mod ->
-            assertEquals(testList.map { it.takeIf { it % 2 == mod } }.filterNotNull(),
+            assertEquals(
+                testList.mapNotNull { it.takeIf { it % 2 == mod } },
                 testList.asReceiveChannel().map { it.takeIf { it % 2 == mod } }.filterNotNull().toList())
         }
     }
@@ -374,7 +375,7 @@
         repeat(3) { mod ->
             val c = mutableListOf<Int>()
             testList.asReceiveChannel().map { it.takeIf { it % 2 == mod } }.filterNotNullTo(c)
-            assertEquals(testList.map { it.takeIf { it % 2 == mod } }.filterNotNull(), c)
+            assertEquals(testList.mapNotNull { it.takeIf { it % 2 == mod } }, c)
         }
     }
 
@@ -384,7 +385,7 @@
             val c = produce<Int> {
                 testList.asReceiveChannel().map { it.takeIf { it % 2 == mod } }.filterNotNullTo(channel)
             }
-            assertEquals(testList.map { it.takeIf { it % 2 == mod } }.filterNotNull(), c.toList())
+            assertEquals(testList.mapNotNull { it.takeIf { it % 2 == mod } }, c.toList())
         }
     }
 
diff --git a/common/kotlinx-coroutines-core-common/test/channels/ConflatedChannelTest.kt b/common/kotlinx-coroutines-core-common/test/channels/ConflatedChannelTest.kt
index ab78d4c..c6968db 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/ConflatedChannelTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/ConflatedChannelTest.kt
@@ -10,7 +10,7 @@
 class ConflatedChannelTest : TestBase() {
     @Test
     fun testBasicConflationOfferPoll() {
-        val q = ConflatedChannel<Int>()
+        val q = Channel<Int>(Channel.CONFLATED)
         assertNull(q.poll())
         assertTrue(q.offer(1))
         assertTrue(q.offer(2))
@@ -29,7 +29,7 @@
 
     @Test
     fun testConflatedClose() = runTest {
-        val q = ConflatedChannel<Int>()
+        val q = Channel<Int>(Channel.CONFLATED)
         q.send(1)
         q.close() // shall conflate sent item and become closed
         assertNull(q.receiveOrNull())
@@ -37,7 +37,7 @@
 
     @Test
     fun testConflationSendReceive() = runTest {
-        val q = ConflatedChannel<Int>()
+        val q = Channel<Int>(Channel.CONFLATED)
         expect(1)
         launch { // receiver coroutine
             expect(4)
@@ -65,7 +65,7 @@
 
     @Test
     fun testConsumeAll() = runTest {
-        val q = ConflatedChannel<Int>()
+        val q = Channel<Int>(Channel.CONFLATED)
         expect(1)
         for (i in 1..10) {
             q.send(i) // stores as last
@@ -79,7 +79,7 @@
 
     @Test
     fun testCancelWithCause() = runTest({ it is TestException }) {
-        val channel = ConflatedChannel<Int>()
+        val channel = Channel<Int>(Channel.CONFLATED)
         channel.cancel(TestException())
         channel.receiveOrNull()
     }
diff --git a/common/kotlinx-coroutines-core-common/test/channels/LinkedListChannelTest.kt b/common/kotlinx-coroutines-core-common/test/channels/LinkedListChannelTest.kt
index 18a915a..4db28ab 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/LinkedListChannelTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/LinkedListChannelTest.kt
@@ -10,7 +10,7 @@
 class LinkedListChannelTest : TestBase() {
     @Test
     fun testBasic() = runTest {
-        val c = LinkedListChannel<Int>()
+        val c = Channel<Int>(Channel.UNLIMITED)
         c.send(1)
         check(c.offer(2))
         c.send(3)
@@ -24,7 +24,7 @@
 
     @Test
     fun testConsumeAll() = runTest {
-        val q = LinkedListChannel<Int>()
+        val q = Channel<Int>(Channel.UNLIMITED)
         for (i in 1..10) {
             q.send(i) // buffers
         }
@@ -36,7 +36,7 @@
 
     @Test
     fun testCancelWithCause() = runTest({ it is TestException }) {
-        val channel = LinkedListChannel<Int>()
+        val channel = Channel<Int>(Channel.UNLIMITED)
         channel.cancel(TestException())
         channel.receiveOrNull()
     }
diff --git a/common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt b/common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt
index cbbda94..9b7cc1d 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/ProduceTest.kt
@@ -105,7 +105,7 @@
         try {
             source.receive()
             // TODO shouldn't it be ClosedReceiveChannelException ?
-        } catch (e: JobCancellationException) {
+        } catch (e: CancellationException) {
             finish(4)
         }
     }
diff --git a/common/kotlinx-coroutines-core-common/test/channels/RendezvousChannelTest.kt b/common/kotlinx-coroutines-core-common/test/channels/RendezvousChannelTest.kt
index 95a4347..3f422c9 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/RendezvousChannelTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/RendezvousChannelTest.kt
@@ -10,7 +10,7 @@
 class RendezvousChannelTest : TestBase() {
     @Test
     fun testSimple() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         check(q.isEmpty && q.isFull)
         expect(1)
         val sender = launch {
@@ -37,7 +37,7 @@
 
     @Test
     fun testClosedReceiveOrNull() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         check(q.isEmpty && q.isFull && !q.isClosedForSend && !q.isClosedForReceive)
         expect(1)
         launch {
@@ -59,7 +59,7 @@
 
     @Test
     fun testClosedExceptions() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         expect(1)
         launch {
             expect(4)
@@ -81,7 +81,7 @@
 
     @Test
     fun testOfferAndPool() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         assertFalse(q.offer(1))
         expect(1)
         launch {
@@ -109,7 +109,7 @@
 
     @Test
     fun testIteratorClosed() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         expect(1)
         launch {
             expect(3)
@@ -125,7 +125,7 @@
 
     @Test
     fun testIteratorOne() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         expect(1)
         launch {
             expect(3)
@@ -144,7 +144,7 @@
 
     @Test
     fun testIteratorOneWithYield() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         expect(1)
         launch {
             expect(3)
@@ -165,7 +165,7 @@
 
     @Test
     fun testIteratorTwo() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         expect(1)
         launch {
             expect(3)
@@ -189,7 +189,7 @@
 
     @Test
     fun testIteratorTwoWithYield() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         expect(1)
         launch {
             expect(3)
@@ -215,7 +215,7 @@
 
     @Test
     fun testSuspendSendOnClosedChannel() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         expect(1)
         launch {
             expect(4)
@@ -260,7 +260,7 @@
 
     @Test
     fun testConsumeAll() = runTest {
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         for (i in 1..10) {
             launch(start = CoroutineStart.UNDISPATCHED) {
                 expect(i)
@@ -278,7 +278,7 @@
 
     @Test
     fun testCancelWithCause() = runTest({ it is TestException }) {
-        val channel = RendezvousChannel<Int>()
+        val channel = Channel<Int>(Channel.RENDEZVOUS)
         channel.cancel(TestException())
         channel.receiveOrNull()
     }
diff --git a/common/kotlinx-coroutines-core-common/test/channels/SendReceiveStressTest.kt b/common/kotlinx-coroutines-core-common/test/channels/SendReceiveStressTest.kt
index 9f08bb5..b48bf13 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/SendReceiveStressTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/SendReceiveStressTest.kt
@@ -5,7 +5,6 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.*
 import kotlin.test.*
 
 class SendReceiveStressTest : TestBase() {
@@ -14,17 +13,17 @@
 
     @Test
     fun testArrayChannel() = runTest {
-        testStress(ArrayChannel(2))
+        testStress(Channel(2))
     }
 
     @Test
     fun testLinkedListChannel() = runTest {
-        testStress(LinkedListChannel())
+        testStress(Channel(Channel.UNLIMITED))
     }
 
     @Test
     fun testRendezvousChannel() = runTest {
-        testStress(RendezvousChannel())
+        testStress(Channel(Channel.RENDEZVOUS))
     }
 
     private suspend fun testStress(channel: Channel<Int>) = coroutineScope {
diff --git a/common/kotlinx-coroutines-core-common/test/channels/TestBroadcastChannelKind.kt b/common/kotlinx-coroutines-core-common/test/channels/TestBroadcastChannelKind.kt
index 41ca453..5c41f6f 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/TestBroadcastChannelKind.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/TestBroadcastChannelKind.kt
@@ -6,11 +6,11 @@
 
 enum class TestBroadcastChannelKind {
     ARRAY_1 {
-        override fun <T> create(): BroadcastChannel<T> = ArrayBroadcastChannel(1)
+        override fun <T> create(): BroadcastChannel<T> = BroadcastChannel(1)
         override fun toString(): String = "ArrayBroadcastChannel(1)"
     },
     ARRAY_10 {
-        override fun <T> create(): BroadcastChannel<T> = ArrayBroadcastChannel(10)
+        override fun <T> create(): BroadcastChannel<T> = BroadcastChannel(10)
         override fun toString(): String = "ArrayBroadcastChannel(10)"
     },
     CONFLATED {
diff --git a/common/kotlinx-coroutines-core-common/test/channels/TestChannelKind.kt b/common/kotlinx-coroutines-core-common/test/channels/TestChannelKind.kt
index 7af18b8..e783120 100644
--- a/common/kotlinx-coroutines-core-common/test/channels/TestChannelKind.kt
+++ b/common/kotlinx-coroutines-core-common/test/channels/TestChannelKind.kt
@@ -8,32 +8,32 @@
 
 enum class TestChannelKind {
     RENDEZVOUS {
-        override fun create(): Channel<Int> = RendezvousChannel()
+        override fun create(): Channel<Int> = Channel(Channel.RENDEZVOUS)
         override fun toString(): String = "RendezvousChannel"
     },
     ARRAY_1 {
-        override fun create(): Channel<Int> = ArrayChannel(1)
+        override fun create(): Channel<Int> = Channel(1)
         override fun toString(): String = "ArrayChannel(1)"
     },
     ARRAY_10 {
-        override fun create(): Channel<Int> = ArrayChannel(10)
+        override fun create(): Channel<Int> = Channel(10)
         override fun toString(): String = "ArrayChannel(10)"
     },
     LINKED_LIST {
-        override fun create(): Channel<Int> = LinkedListChannel()
+        override fun create(): Channel<Int> = Channel(Channel.UNLIMITED)
         override fun toString(): String = "LinkedListChannel"
     },
     CONFLATED {
-        override fun create(): Channel<Int> = ConflatedChannel()
+        override fun create(): Channel<Int> = Channel(Channel.CONFLATED)
         override fun toString(): String = "ConflatedChannel"
         override val isConflated: Boolean get() = true
     },
     ARRAY_BROADCAST_1 {
-        override fun create(): Channel<Int> = ChannelViaBroadcast(ArrayBroadcastChannel<Int>(1))
+        override fun create(): Channel<Int> = ChannelViaBroadcast(BroadcastChannel(1))
         override fun toString(): String = "ArrayBroadcastChannel(1)"
     },
     ARRAY_BROADCAST_10 {
-        override fun create(): Channel<Int> = ChannelViaBroadcast(ArrayBroadcastChannel<Int>(10))
+        override fun create(): Channel<Int> = ChannelViaBroadcast(BroadcastChannel(10))
         override fun toString(): String = "ArrayBroadcastChannel(10)"
     },
     CONFLATED_BROADCAST {
@@ -59,6 +59,7 @@
     override suspend fun receiveOrNull(): E? = sub.receiveOrNull()
     override fun poll(): E? = sub.poll()
     override fun iterator(): ChannelIterator<E> = sub.iterator()
+    override fun cancel(): Boolean = sub.cancel()
     override fun cancel(cause: Throwable?): Boolean = sub.cancel(cause)
     override val onReceive: SelectClause1<E>
         get() = sub.onReceive
diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectArrayChannelTest.kt b/common/kotlinx-coroutines-core-common/test/selects/SelectArrayChannelTest.kt
index 0c8d85f..a20ce30 100644
--- a/common/kotlinx-coroutines-core-common/test/selects/SelectArrayChannelTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/selects/SelectArrayChannelTest.kt
@@ -14,7 +14,7 @@
     @Test
     fun testSelectSendSuccess() = runTest {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         launch {
             expect(2)
             assertEquals("OK", channel.receive())
@@ -33,7 +33,7 @@
     @Test
     fun testSelectSendSuccessWithDefault() = runTest {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         launch {
             expect(2)
             assertEquals("OK", channel.receive())
@@ -55,7 +55,7 @@
     @Test
     fun testSelectSendReceiveBuf() = runTest {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         select<Unit> {
             channel.onSend("OK") {
                 expect(2)
@@ -74,7 +74,7 @@
     @Test
     fun testSelectSendWait() = runTest {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         launch {
             expect(4)
             assertEquals("BUF", channel.receive())
@@ -96,7 +96,7 @@
     @Test
     fun testSelectReceiveSuccess() = runTest {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         channel.send("OK")
         expect(2)
         select<Unit> {
@@ -111,7 +111,7 @@
     @Test
     fun testSelectReceiveSuccessWithDefault() = runTest {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         channel.send("OK")
         expect(2)
         select<Unit> {
@@ -129,7 +129,7 @@
     @Test
     fun testSelectReceiveWaitWithDefault() = runTest {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         select<Unit> {
             channel.onReceive {
                 expectUnreached()
@@ -159,7 +159,7 @@
     @Test
     fun testSelectReceiveWait() = runTest {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         launch {
             expect(3)
             channel.send("OK")
@@ -178,7 +178,7 @@
     @Test
     fun testSelectReceiveClosed() = runTest({it is ClosedReceiveChannelException}) {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         channel.close()
         finish(2)
         select<Unit> {
@@ -192,7 +192,7 @@
     @Test
     fun testSelectReceiveWaitClosed() = runTest({it is ClosedReceiveChannelException}) {
         expect(1)
-        val channel = ArrayChannel<String>(1)
+        val channel = Channel<String>(1)
         launch {
             expect(3)
             channel.close()
@@ -209,7 +209,7 @@
 
     @Test
     fun testSelectSendResourceCleanup() = runTest {
-        val channel = ArrayChannel<Int>(1)
+        val channel = Channel<Int>(1)
         val n = 1000
         expect(1)
         channel.send(-1) // fill the buffer, so all subsequent sends cannot proceed
@@ -224,7 +224,7 @@
 
     @Test
     fun testSelectReceiveResourceCleanup() = runTest {
-        val channel = ArrayChannel<Int>(1)
+        val channel = Channel<Int>(1)
         val n = 1000
         expect(1)
         repeat(n) { i ->
@@ -238,7 +238,7 @@
 
     @Test
     fun testSelectReceiveDispatchNonSuspending() = runTest {
-        val channel = ArrayChannel<Int>(1)
+        val channel = Channel<Int>(1)
         expect(1)
         channel.send(42)
         expect(2)
@@ -260,7 +260,7 @@
 
     @Test
     fun testSelectReceiveDispatchNonSuspending2() = runTest {
-        val channel = ArrayChannel<Int>(1)
+        val channel = Channel<Int>(1)
         expect(1)
         channel.send(42)
         expect(2)
diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectDeferredTest.kt b/common/kotlinx-coroutines-core-common/test/selects/SelectDeferredTest.kt
index d0f4056..c2e202c 100644
--- a/common/kotlinx-coroutines-core-common/test/selects/SelectDeferredTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/selects/SelectDeferredTest.kt
@@ -119,7 +119,7 @@
 
     @Test
     fun testSelectCancel() = runTest(
-        expected = { it is JobCancellationException }
+        expected = { it is CancellationException }
     ) {
         expect(1)
         val d = CompletableDeferred<String>()
diff --git a/common/kotlinx-coroutines-core-common/test/selects/SelectRendezvousChannelTest.kt b/common/kotlinx-coroutines-core-common/test/selects/SelectRendezvousChannelTest.kt
index 7f3040e..5aa5a3f 100644
--- a/common/kotlinx-coroutines-core-common/test/selects/SelectRendezvousChannelTest.kt
+++ b/common/kotlinx-coroutines-core-common/test/selects/SelectRendezvousChannelTest.kt
@@ -15,7 +15,7 @@
     @Test
     fun testSelectSendSuccess() = runTest {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         launch {
             expect(2)
             assertEquals("OK", channel.receive())
@@ -34,7 +34,7 @@
     @Test
     fun testSelectSendSuccessWithDefault() = runTest {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         launch {
             expect(2)
             assertEquals("OK", channel.receive())
@@ -56,7 +56,7 @@
     @Test
     fun testSelectSendWaitWithDefault() = runTest {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         select<Unit> {
             channel.onSend("OK") {
                 expectUnreached()
@@ -82,7 +82,7 @@
     @Test
     fun testSelectSendWait() = runTest {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         launch {
             expect(3)
             assertEquals("OK", channel.receive())
@@ -100,7 +100,7 @@
     @Test
     fun testSelectReceiveSuccess() = runTest {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         launch {
             expect(2)
             channel.send("OK")
@@ -120,7 +120,7 @@
     @Test
     fun testSelectReceiveSuccessWithDefault() = runTest {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         launch {
             expect(2)
             channel.send("OK")
@@ -143,7 +143,7 @@
     @Test
     fun testSelectReceiveWaitWithDefault() = runTest {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         select<Unit> {
             channel.onReceive {
                 expectUnreached()
@@ -169,7 +169,7 @@
     @Test
     fun testSelectReceiveWait() = runTest {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         launch {
             expect(3)
             channel.send("OK")
@@ -188,7 +188,7 @@
     @Test
     fun testSelectReceiveClosed() = runTest(expected = { it is ClosedReceiveChannelException }) {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         channel.close()
         finish(2)
         select<Unit> {
@@ -202,7 +202,7 @@
     @Test
     fun testSelectReceiveWaitClosed() = runTest(expected = {it is ClosedReceiveChannelException}) {
         expect(1)
-        val channel = RendezvousChannel<String>()
+        val channel = Channel<String>(Channel.RENDEZVOUS)
         launch {
             expect(3)
             channel.close()
@@ -219,7 +219,7 @@
 
     @Test
     fun testSelectSendResourceCleanup() = runTest {
-        val channel = RendezvousChannel<Int>()
+        val channel = Channel<Int>(Channel.RENDEZVOUS)
         val n = 1_000
         expect(1)
         repeat(n) { i ->
@@ -233,7 +233,7 @@
 
     @Test
     fun testSelectReceiveResourceCleanup() = runTest {
-        val channel = RendezvousChannel<Int>()
+        val channel = Channel<Int>(Channel.RENDEZVOUS)
         val n = 1_000
         expect(1)
         repeat(n) { i ->
@@ -247,8 +247,8 @@
 
     @Test
     fun testSelectAtomicFailure() = runTest {
-        val c1 = RendezvousChannel<Int>()
-        val c2 = RendezvousChannel<Int>()
+        val c1 = Channel<Int>(Channel.RENDEZVOUS)
+        val c2 = Channel<Int>(Channel.RENDEZVOUS)
         expect(1)
         launch {
             expect(3)
@@ -278,7 +278,7 @@
 
     @Test
     fun testSelectWaitDispatch() = runTest {
-        val c = RendezvousChannel<Int>()
+        val c = Channel<Int>(Channel.RENDEZVOUS)
         expect(1)
         launch {
             expect(3)
diff --git a/core/kotlinx-coroutines-core/README.md b/core/kotlinx-coroutines-core/README.md
index f2b9977..5093fd1 100644
--- a/core/kotlinx-coroutines-core/README.md
+++ b/core/kotlinx-coroutines-core/README.md
@@ -114,7 +114,7 @@
 [newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
 [newFixedThreadPoolContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-fixed-thread-pool-context.html
 [java.util.concurrent.Executor.asCoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/java.util.concurrent.-executor/as-coroutine-dispatcher.html
-[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
+[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable.html
 [CoroutineExceptionHandler]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-exception-handler/index.html
 [delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
 [yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
diff --git a/core/kotlinx-coroutines-core/src/Builders.kt b/core/kotlinx-coroutines-core/src/Builders.kt
index e3c2708..8c93f4c 100644
--- a/core/kotlinx-coroutines-core/src/Builders.kt
+++ b/core/kotlinx-coroutines-core/src/Builders.kt
@@ -15,21 +15,20 @@
  * This function should not be used from coroutine. It is designed to bridge regular blocking code
  * to libraries that are written in suspending style, to be used in `main` functions and in tests.
  *
- * The default [CoroutineDispatcher] for this builder in an implementation of [EventLoop] that processes continuations
+ * The default [CoroutineDispatcher] for this builder in an internal implementation of event loop that processes continuations
  * in this blocked thread until the completion of this coroutine.
  * See [CoroutineDispatcher] for the other implementations that are provided by `kotlinx.coroutines`.
  *
  * When [CoroutineDispatcher] is explicitly specified in the [context], then the new coroutine runs in the context of
- * the specified dispatcher while the current thread is blocked. If the specified dispatcher implements [EventLoop]
- * interface and this `runBlocking` invocation is performed from inside of the this event loop's thread, then
- * this event loop is processed using its [processNextEvent][EventLoop.processNextEvent] method until coroutine completes.
+ * the specified dispatcher while the current thread is blocked. If the specified dispatcher is an event loop of another `runBlocking`,
+ * the this invocation uses an outer event loop.
  *
  * If this blocked thread is interrupted (see [Thread.interrupt]), then the coroutine job is cancelled and
  * this `runBlocking` invocation throws [InterruptedException].
  *
  * See [newCoroutineContext][CoroutineScope.newCoroutineContext] for a description of debugging facilities that are available for newly created coroutine.
  *
- * @param context context of the coroutine. The default value is an implementation of [EventLoop].
+ * @param context context of the coroutine. The default value is an event loop on current thread.
  * @param block the coroutine code.
  */
 @Throws(InterruptedException::class)
diff --git a/core/kotlinx-coroutines-core/src/CoroutineContext.kt b/core/kotlinx-coroutines-core/src/CoroutineContext.kt
index 402b504..c2af973 100644
--- a/core/kotlinx-coroutines-core/src/CoroutineContext.kt
+++ b/core/kotlinx-coroutines-core/src/CoroutineContext.kt
@@ -9,35 +9,6 @@
 import java.util.concurrent.atomic.*
 import kotlin.coroutines.experimental.*
 
-/**
- * Name of the property that controls coroutine debugging. See [newCoroutineContext][CoroutineScope.newCoroutineContext].
- */
-public const val DEBUG_PROPERTY_NAME = "kotlinx.coroutines.debug"
-
-/**
- * Automatic debug configuration value for [DEBUG_PROPERTY_NAME]. See [newCoroutineContext][CoroutineScope.newCoroutineContext].
- */
-public const val DEBUG_PROPERTY_VALUE_AUTO = "auto"
-
-/**
- * Debug turned on value for [DEBUG_PROPERTY_NAME]. See [newCoroutineContext][CoroutineScope.newCoroutineContext].
- */
-public const val DEBUG_PROPERTY_VALUE_ON = "on"
-
-/**
- * Debug turned on value for [DEBUG_PROPERTY_NAME]. See [newCoroutineContext][CoroutineScope.newCoroutineContext].
- */
-public const val DEBUG_PROPERTY_VALUE_OFF = "off"
-
-internal val DEBUG = systemProp(DEBUG_PROPERTY_NAME).let { value ->
-    when (value) {
-        DEBUG_PROPERTY_VALUE_AUTO, null -> CoroutineId::class.java.desiredAssertionStatus()
-        DEBUG_PROPERTY_VALUE_ON, "" -> true
-        DEBUG_PROPERTY_VALUE_OFF -> false
-        else -> error("System property '$DEBUG_PROPERTY_NAME' has unrecognized value '$value'")
-    }
-}
-
 private val COROUTINE_ID = AtomicLong()
 
 // for tests only
@@ -101,7 +72,11 @@
  *
  * Coroutine name can be explicitly assigned using [CoroutineName] context element.
  * The string "coroutine" is used as a default name.
+ *
+ * **Note: This is an experimental api.**
+ *   Behavior of this function may change in the future with respect to its support for debugging facilities.
  */
+@ExperimentalCoroutinesApi
 public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {
     val combined = coroutineContext + context
     val debug = if (DEBUG) combined + CoroutineId(COROUTINE_ID.incrementAndGet()) else combined
diff --git a/core/kotlinx-coroutines-core/src/Debug.kt b/core/kotlinx-coroutines-core/src/Debug.kt
index d2e0da0..6a31687 100644
--- a/core/kotlinx-coroutines-core/src/Debug.kt
+++ b/core/kotlinx-coroutines-core/src/Debug.kt
@@ -4,8 +4,38 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlinx.coroutines.experimental.internal.*
 import kotlin.coroutines.experimental.Continuation
 
+/**
+ * Name of the property that controls coroutine debugging. See [newCoroutineContext][CoroutineScope.newCoroutineContext].
+ */
+public const val DEBUG_PROPERTY_NAME = "kotlinx.coroutines.debug"
+
+/**
+ * Automatic debug configuration value for [DEBUG_PROPERTY_NAME]. See [newCoroutineContext][CoroutineScope.newCoroutineContext].
+ */
+public const val DEBUG_PROPERTY_VALUE_AUTO = "auto"
+
+/**
+ * Debug turned on value for [DEBUG_PROPERTY_NAME]. See [newCoroutineContext][CoroutineScope.newCoroutineContext].
+ */
+public const val DEBUG_PROPERTY_VALUE_ON = "on"
+
+/**
+ * Debug turned on value for [DEBUG_PROPERTY_NAME]. See [newCoroutineContext][CoroutineScope.newCoroutineContext].
+ */
+public const val DEBUG_PROPERTY_VALUE_OFF = "off"
+
+internal val DEBUG = systemProp(DEBUG_PROPERTY_NAME).let { value ->
+    when (value) {
+        DEBUG_PROPERTY_VALUE_AUTO, null -> CoroutineId::class.java.desiredAssertionStatus()
+        DEBUG_PROPERTY_VALUE_ON, "" -> true
+        DEBUG_PROPERTY_VALUE_OFF -> false
+        else -> error("System property '$DEBUG_PROPERTY_NAME' has unrecognized value '$value'")
+    }
+}
+
 // internal debugging tools
 
 internal actual val Any.hexAddress: String
diff --git a/core/kotlinx-coroutines-core/src/DefaultExecutor.kt b/core/kotlinx-coroutines-core/src/DefaultExecutor.kt
index 322914b..cdec915 100644
--- a/core/kotlinx-coroutines-core/src/DefaultExecutor.kt
+++ b/core/kotlinx-coroutines-core/src/DefaultExecutor.kt
@@ -4,7 +4,7 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlinx.coroutines.experimental.timeunit.*
+import java.util.concurrent.*
 
 internal actual val DefaultDelay: Delay = DefaultExecutor
 
@@ -22,6 +22,7 @@
             DEFAULT_KEEP_ALIVE
         })
 
+    @Suppress("ObjectPropertyName")
     @Volatile
     private var _thread: Thread? = null
 
@@ -47,8 +48,8 @@
      * Livelock is possible only if `runBlocking` is called on internal default executed (which is used by default [delay]),
      * but it's not exposed as public API.
      */
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle =
-        DelayedRunnableTask(time, unit, block).also { schedule(it) }
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle =
+        DelayedRunnableTask(timeMillis, block).also { schedule(it) }
 
     override fun run() {
         timeSource.registerTimeLoopThread()
diff --git a/core/kotlinx-coroutines-core/src/EventLoop.kt b/core/kotlinx-coroutines-core/src/EventLoop.kt
index 8aa533d..4e21abd 100644
--- a/core/kotlinx-coroutines-core/src/EventLoop.kt
+++ b/core/kotlinx-coroutines-core/src/EventLoop.kt
@@ -6,7 +6,6 @@
 
 import kotlinx.atomicfu.*
 import kotlinx.coroutines.experimental.internal.*
-import kotlinx.coroutines.experimental.timeunit.*
 import java.util.concurrent.locks.*
 import kotlin.coroutines.experimental.*
 
@@ -16,7 +15,10 @@
  *
  * It may optionally implement [Delay] interface and support time-scheduled tasks. It is used by [runBlocking] to
  * continue processing events when invoked from the event dispatch thread.
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi // todo: review KDoc references to this interface
 public interface EventLoop: ContinuationInterceptor {
     /**
      * Processes next event in this event loop.
@@ -52,8 +54,11 @@
  *     LockSupport.parkNanos(eventLoop.processNextEvent()) // event loop will unpark
  * }
  * ```
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
 @Suppress("FunctionName")
+@InternalCoroutinesApi
 public fun EventLoop(thread: Thread = Thread.currentThread(), parentJob: Job? = null): EventLoop =
     EventLoopImpl(thread).apply {
         if (parentJob != null) initParentJob(parentJob)
@@ -71,6 +76,18 @@
 private const val REMOVED = 1
 private const val RESCHEDULED = 2
 
+private const val MS_TO_NS = 1_000_000L
+private const val MAX_MS = Long.MAX_VALUE / MS_TO_NS
+
+internal fun delayToNanos(timeMillis: Long): Long = when {
+    timeMillis <= 0 -> 0L
+    timeMillis >= MAX_MS -> Long.MAX_VALUE
+    else -> timeMillis * MS_TO_NS
+}
+
+internal fun delayNanosToMillis(timeNanos: Long): Long =
+    timeNanos / MS_TO_NS
+
 @Suppress("PrivatePropertyName")
 private val CLOSED_EMPTY = Symbol("CLOSED_EMPTY")
 
@@ -121,8 +138,8 @@
     override fun dispatch(context: CoroutineContext, block: Runnable) =
         execute(block)
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) =
-        schedule(DelayedResumeTask(time, unit, continuation))
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) =
+        schedule(DelayedResumeTask(timeMillis, continuation))
 
     override fun processNextEvent(): Long {
         if (!isCorrectThread()) return Long.MAX_VALUE
@@ -260,11 +277,11 @@
     }
 
     internal abstract inner class DelayedTask(
-        time: Long, timeUnit: TimeUnit
+        timeMillis: Long
     ) : Runnable, Comparable<DelayedTask>, DisposableHandle, ThreadSafeHeapNode {
         override var index: Int = -1
-        var state = DELAYED // Guarded by by lock on this task for reschedule/dispose purposes
-        @JvmField val nanoTime: Long = timeSource.nanoTime() + timeUnit.toNanos(time)
+        @JvmField var state = DELAYED // Guarded by by lock on this task for reschedule/dispose purposes
+        @JvmField val nanoTime: Long = timeSource.nanoTime() + delayToNanos(timeMillis)
 
         override fun compareTo(other: DelayedTask): Int {
             val dTime = nanoTime - other.nanoTime
@@ -302,10 +319,9 @@
     }
 
     private inner class DelayedResumeTask(
-        time: Long, timeUnit: TimeUnit,
+        timeMillis: Long,
         private val cont: CancellableContinuation<Unit>
-    ) : DelayedTask(time, timeUnit) {
-
+    ) : DelayedTask(timeMillis) {
         init {
             // Note that this operation isn't lock-free, but very short
             cont.disposeOnCancellation(this)
@@ -318,9 +334,9 @@
 
     // Cannot be moved to DefaultExecutor due to BE bug
     internal inner class DelayedRunnableTask(
-        time: Long, timeUnit: TimeUnit,
+        time: Long,
         private val block: Runnable
-    ) : DelayedTask(time, timeUnit) {
+    ) : DelayedTask(time) {
         override fun run() { block.run() }
         override fun toString(): String = super.toString() + block.toString()
     }
diff --git a/core/kotlinx-coroutines-core/src/Exceptions.kt b/core/kotlinx-coroutines-core/src/Exceptions.kt
index 9a9ac06..2622855 100644
--- a/core/kotlinx-coroutines-core/src/Exceptions.kt
+++ b/core/kotlinx-coroutines-core/src/Exceptions.kt
@@ -6,7 +6,10 @@
 
 /**
  * This exception gets thrown if an exception is caught while processing [CompletionHandler] invocation for [Job].
+ *
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public actual class CompletionHandlerException actual constructor(
     message: String,
     cause: Throwable
@@ -16,7 +19,7 @@
  * Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled while it is suspending.
  * It indicates _normal_ cancellation of a coroutine.
  * **It is not printed to console/log by default uncaught exception handler**.
- * (see [handleCoroutineException]).
+ * See [CoroutineExceptionHandler]
 */
 public actual typealias CancellationException = java.util.concurrent.CancellationException
 
@@ -24,7 +27,11 @@
  * Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled or completed
  * without cause, or with a cause or exception that is not [CancellationException]
  * (see [Job.getCancellationException]).
+ * 
+ * @suppress **Deprecated**: Replace with [CancellationException].
  */
+@InternalCoroutinesApi
+@Deprecated(message = "Replace with CancellationException", replaceWith = ReplaceWith("CancellationException"))
 public actual class JobCancellationException public actual constructor(
     message: String,
     cause: Throwable?,
@@ -49,6 +56,8 @@
     }
 
     override fun toString(): String = "${super.toString()}; job=$job"
+
+    @Suppress("DEPRECATION")
     override fun equals(other: Any?): Boolean =
         other === this ||
             other is JobCancellationException && other.message == message && other.job == job && other.cause == cause
diff --git a/core/kotlinx-coroutines-core/src/Executors.kt b/core/kotlinx-coroutines-core/src/Executors.kt
index d393564..178ee39 100644
--- a/core/kotlinx-coroutines-core/src/Executors.kt
+++ b/core/kotlinx-coroutines-core/src/Executors.kt
@@ -4,7 +4,6 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlinx.coroutines.experimental.timeunit.TimeUnit
 import java.io.*
 import java.util.concurrent.*
 import kotlin.coroutines.experimental.*
@@ -17,6 +16,12 @@
  * asynchronous API which requires instance of the [Executor].
  */
 public abstract class ExecutorCoroutineDispatcher: CloseableCoroutineDispatcher(), Closeable {
+    /**
+     * Closes this coroutine dispatcher and shuts down its executor.
+     * 
+     * It may throw an exception if this dispatcher is global and cannot be closed.
+     */
+    public abstract override fun close()
 
     /**
      * Underlying executor of current [CoroutineDispatcher].
@@ -42,6 +47,7 @@
 /**
  * Converts an instance of [Executor] to an implementation of [CoroutineDispatcher].
  */
+@JvmName("from") // this is for a nice Java API, see issue #255
 public fun Executor.asCoroutineDispatcher(): CoroutineDispatcher =
     ExecutorCoroutineDispatcherImpl(this)
 
@@ -68,6 +74,7 @@
 /**
  * @suppress **This is unstable API and it is subject to change.**
  */
+@InternalCoroutinesApi
 public abstract class ExecutorCoroutineDispatcherBase : ExecutorCoroutineDispatcher(), Delay {
 
     override fun dispatch(context: CoroutineContext, block: Runnable) =
@@ -77,26 +84,26 @@
             DefaultExecutor.execute(block)
         }
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
         val timeout =
             try { (executor as? ScheduledExecutorService)
-                ?.schedule(ResumeUndispatchedRunnable(this, continuation), time, unit) }
+                ?.schedule(ResumeUndispatchedRunnable(this, continuation), timeMillis, TimeUnit.MILLISECONDS) }
             catch (e: RejectedExecutionException) { null }
         if (timeout != null)
             continuation.cancelFutureOnCancellation(timeout)
         else
-            DefaultExecutor.scheduleResumeAfterDelay(time, unit, continuation)
+            DefaultExecutor.scheduleResumeAfterDelay(timeMillis, continuation)
     }
 
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
         val timeout =
             try { (executor as? ScheduledExecutorService)
-                ?.schedule(block, time, unit) }
+                ?.schedule(block, timeMillis, TimeUnit.MILLISECONDS) }
             catch (e: RejectedExecutionException) { null }
         return if (timeout != null)
             DisposableFutureHandle(timeout)
         else
-            DefaultExecutor.invokeOnTimeout(time, unit, block)
+            DefaultExecutor.invokeOnTimeout(timeMillis, block)
     }
 
     override fun close() {
diff --git a/core/kotlinx-coroutines-core/src/Future.kt b/core/kotlinx-coroutines-core/src/Future.kt
index b198404..398885f 100644
--- a/core/kotlinx-coroutines-core/src/Future.kt
+++ b/core/kotlinx-coroutines-core/src/Future.kt
@@ -15,7 +15,10 @@
  * ```
  * invokeOnCompletion { future.cancel(false) }
  * ```
+ * 
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
 public fun Job.cancelFutureOnCompletion(future: Future<*>): DisposableHandle =
     invokeOnCompletion(handler = CancelFutureOnCompletion(this, future)) // TODO make it work only on cancellation as well?
 
diff --git a/core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt b/core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt
index b13a731..08e2d1e 100644
--- a/core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt
+++ b/core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt
@@ -9,16 +9,24 @@
 import kotlin.coroutines.experimental.*
 
 /**
- * Creates a new coroutine execution context using a single thread with built-in [yield] and [delay] support.
- * **NOTE: The resulting [ThreadPoolDispatcher] owns native resources (its thread).
- * Resources are reclaimed by [ThreadPoolDispatcher.close].**
+ * Creates a new coroutine execution context using a single thread with built-in [yield] support.
+ * **NOTE: The resulting [ExecutorCoroutineDispatcher] owns native resources (its thread).
+ * Resources are reclaimed by [ExecutorCoroutineDispatcher.close].**
  *
  * @param name the base name of the created thread.
  */
-fun newSingleThreadContext(name: String): ThreadPoolDispatcher =
+fun newSingleThreadContext(name: String): ExecutorCoroutineDispatcher =
     newFixedThreadPoolContext(1, name)
 
 /**
+ * @suppress binary compatibility
+ */
+@JvmName("newSingleThreadContext")
+@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only")
+fun newSingleThreadContext0(name: String): ThreadPoolDispatcher =
+    newSingleThreadContext(name) as ThreadPoolDispatcher
+
+/**
  * @suppress **Deprecated**: Parent job is no longer supported.
  */
 @Deprecated(message = "Parent job is no longer supported, `close` the resulting ThreadPoolDispatcher to release resources",
@@ -27,19 +35,27 @@
     newFixedThreadPoolContext(1, name)
 
 /**
- * Creates new coroutine execution context with the fixed-size thread-pool and built-in [yield] and [delay] support.
- * **NOTE: The resulting [ThreadPoolDispatcher] owns native resources (its threads).
- * Resources are reclaimed by [ThreadPoolDispatcher.close].**
+ * Creates new coroutine execution context with the fixed-size thread-pool and built-in [yield] support.
+ * **NOTE: The resulting [ExecutorCoroutineDispatcher] owns native resources (its threads).
+ * Resources are reclaimed by [ExecutorCoroutineDispatcher.close].**
  *
  * @param nThreads the number of threads.
  * @param name the base name of the created threads.
  */
-fun newFixedThreadPoolContext(nThreads: Int, name: String): ThreadPoolDispatcher {
+fun newFixedThreadPoolContext(nThreads: Int, name: String): ExecutorCoroutineDispatcher {
     require(nThreads >= 1) { "Expected at least one thread, but $nThreads specified" }
     return ThreadPoolDispatcher(nThreads, name)
 }
 
 /**
+ * @suppress binary compatibility
+ */
+@JvmName("newFixedThreadPoolContext")
+@Deprecated(level = DeprecationLevel.HIDDEN, message = "Binary compatibility only")
+fun newFixedThreadPoolContext0(nThreads: Int, name: String): ThreadPoolDispatcher =
+    newFixedThreadPoolContext(nThreads, name) as ThreadPoolDispatcher
+
+/**
  * @suppress **Deprecated**: Parent job is no longer supported.
  */
 @Deprecated(message = "Parent job is no longer supported, `close` the resulting ThreadPoolDispatcher to release resources",
@@ -57,7 +73,11 @@
 /**
  * Dispatches coroutine execution to a thread pool of a fixed size. Instances of this dispatcher are
  * created with [newSingleThreadContext] and [newFixedThreadPoolContext].
+ * 
+ * @suppress **This an internal API and should not be used from general code.**
  */
+@InternalCoroutinesApi
+@Deprecated("Replace with ExecutorCoroutineDispatcher", replaceWith = ReplaceWith("ExecutorCoroutineDispatcher"))
 public class ThreadPoolDispatcher internal constructor(
     private val nThreads: Int,
     private val name: String
diff --git a/core/kotlinx-coroutines-core/src/channels/Actor.kt b/core/kotlinx-coroutines-core/src/channels/Actor.kt
index 7590cbb..abdc340 100644
--- a/core/kotlinx-coroutines-core/src/channels/Actor.kt
+++ b/core/kotlinx-coroutines-core/src/channels/Actor.kt
@@ -12,7 +12,11 @@
 
 /**
  * Scope for [actor][GlobalScope.actor] coroutine builder.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of complex actors.**
+ *           See [issue #87](https://github.com/Kotlin/kotlinx.coroutines/issues/87).
  */
+@ObsoleteCoroutinesApi
 public interface ActorScope<E> : CoroutineScope, ReceiveChannel<E> {
     /**
      * A reference to the mailbox channel that this coroutine [receives][receive] messages from.
@@ -57,12 +61,8 @@
  * Uncaught exceptions in this coroutine close the channel with this exception as a cause and
  * the resulting channel becomes _failed_, so that any attempt to send to such a channel throws exception.
  *
- * The kind of the resulting channel depends on the specified [capacity] parameter:
- * * when `capacity` is 0 (default) -- uses [RendezvousChannel] without a buffer;
- * * when `capacity` is [Channel.UNLIMITED] -- uses [LinkedListChannel] with buffer of unlimited size;
- * * when `capacity` is [Channel.CONFLATED] -- uses [ConflatedChannel] that conflates back-to-back sends;
- * * when `capacity` is positive, but less than [UNLIMITED] -- uses [ArrayChannel] with a buffer of the specified `capacity`;
- * * otherwise -- throws [IllegalArgumentException].
+ * The kind of the resulting channel depends on the specified [capacity] parameter.
+ * See [Channel] interface documentation for details.
  *
  * See [newCoroutineContext][CoroutineScope.newCoroutineContext] for a description of debugging facilities that are available for newly created coroutine.
  *
@@ -105,12 +105,16 @@
  * "`for (msg in channel)`" and other cancellable suspending functions throw [CancellationException] and actor
  * completes without processing remaining messages.
  *
+ * **Note: This API will become obsolete in future updates with introduction of complex actors.**
+ *           See [issue #87](https://github.com/Kotlin/kotlinx.coroutines/issues/87).
+ *
  * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
  * @param capacity capacity of the channel's buffer (no buffer by default).
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
  * @param onCompletion optional completion handler for the actor coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
+@ObsoleteCoroutinesApi
 public fun <E> CoroutineScope.actor(
     context: CoroutineContext = EmptyCoroutineContext,
     capacity: Int = 0,
diff --git a/core/kotlinx-coroutines-core/src/channels/TickerChannels.kt b/core/kotlinx-coroutines-core/src/channels/TickerChannels.kt
index 155aa6f..6c2c4d5 100644
--- a/core/kotlinx-coroutines-core/src/channels/TickerChannels.kt
+++ b/core/kotlinx-coroutines-core/src/channels/TickerChannels.kt
@@ -10,7 +10,10 @@
 
 /**
  * Mode for [ticker] function.
+ *
+ * **Note: Ticker channels are not currently integrated with structured concurrency and their api will change in the future.**
  */
+@ObsoleteCoroutinesApi
 enum class TickerMode {
     /**
      * Adjust delay to maintain fixed period if consumer cannot keep up or is otherwise slow.
@@ -40,7 +43,7 @@
  * Creates a channel that produces the first item after the given initial delay and subsequent items with the
  * given delay between them.
  *
- * The resulting channel is a [rendezvous channel][RendezvousChannel]. When receiver from this channel does not keep
+ * The resulting channel is a _rendezvous channel_. When receiver from this channel does not keep
  * up with receiving the elements from this channel, they are not being sent due to backpressure. The actual
  * timing behavior of ticker in this case is controlled by [mode] parameter which
  * is set to [TickerMode.FIXED_PERIOD] by default. See [TickerMode] for other details.
@@ -49,38 +52,52 @@
  *
  * **Note** producer to this channel is dispatched via [Dispatchers.Unconfined] by default and started eagerly.
  *
- * @param delay delay between each element.
- * @param unit unit of time that applies to [initialDelay] and [delay] (in milliseconds by default).
- * @param initialDelay delay after which the first element will be produced (it is equal to [delay] by default).
+ * **Note: Ticker channels are not currently integrated with structured concurrency and their api will change in the future.**
+ *           
+ * @param delayMillis delay between each element in milliseconds.
+ * @param initialDelayMillis delay after which the first element will be produced (it is equal to [delayMillis] by default) in milliseconds.
  * @param context context of the producing coroutine.
  * @param mode specifies behavior when elements are not received ([FIXED_PERIOD][TickerMode.FIXED_PERIOD] by default).
  */
+@ObsoleteCoroutinesApi
 public fun ticker(
-    delay: Long,
-    unit: TimeUnit = TimeUnit.MILLISECONDS,
-    initialDelay: Long = delay,
+    delayMillis: Long,
+    initialDelayMillis: Long = delayMillis,
     context: CoroutineContext = EmptyCoroutineContext,
     mode: TickerMode = TickerMode.FIXED_PERIOD
 ): ReceiveChannel<Unit> {
-    require(delay >= 0) { "Expected non-negative delay, but has $delay" }
-    require(initialDelay >= 0) { "Expected non-negative initial delay, but has $initialDelay" }
+    require(delayMillis >= 0) { "Expected non-negative delay, but has $delayMillis ms" }
+    require(initialDelayMillis >= 0) { "Expected non-negative initial delay, but has $initialDelayMillis ms" }
     return GlobalScope.produce(Dispatchers.Unconfined + context, capacity = 0) {
         when (mode) {
-            TickerMode.FIXED_PERIOD -> fixedPeriodTicker(delay, unit, initialDelay, channel)
-            TickerMode.FIXED_DELAY -> fixedDelayTicker(delay, unit, initialDelay, channel)
+            TickerMode.FIXED_PERIOD -> fixedPeriodTicker(delayMillis, initialDelayMillis, channel)
+            TickerMode.FIXED_DELAY -> fixedDelayTicker(delayMillis, initialDelayMillis, channel)
         }
     }
 }
 
-private suspend fun fixedPeriodTicker(
+/** @suppress **Deprecated**: TimeUnit is not longer supported */
+@Deprecated(
+    message = "TimeUnit is no longer supported",
+    replaceWith = ReplaceWith("ticker(unit.toMillis(delay), unit.toMillis(initialDelay), context, mode)")
+)
+public fun ticker(
     delay: Long,
-    unit: TimeUnit,
-    initialDelay: Long,
+    unit: TimeUnit = TimeUnit.MILLISECONDS, // todo: remove
+    initialDelay: Long = delay,
+    context: CoroutineContext = EmptyCoroutineContext,
+    mode: TickerMode = TickerMode.FIXED_PERIOD
+): ReceiveChannel<Unit> =
+    ticker(unit.toMillis(delay), unit.toMillis(initialDelay), context, mode)
+
+private suspend fun fixedPeriodTicker(
+    delayMillis: Long,
+    initialDelayMillis: Long,
     channel: SendChannel<Unit>
 ) {
-    var deadline = timeSource.nanoTime() + unit.toNanos(initialDelay)
-    delay(initialDelay, unit)
-    val delayNs = unit.toNanos(delay)
+    var deadline = timeSource.nanoTime() + delayToNanos(initialDelayMillis)
+    delay(initialDelayMillis)
+    val delayNs = delayToNanos(delayMillis)
     while (true) {
         deadline += delayNs
         channel.send(Unit)
@@ -89,22 +106,21 @@
         if (nextDelay == 0L && delayNs != 0L) {
             val adjustedDelay = delayNs - (now - deadline) % delayNs
             deadline = now + adjustedDelay
-            delay(adjustedDelay, java.util.concurrent.TimeUnit.NANOSECONDS)
+            delay(delayNanosToMillis(adjustedDelay))
         } else {
-            delay(nextDelay, java.util.concurrent.TimeUnit.NANOSECONDS)
+            delay(delayNanosToMillis(nextDelay))
         }
     }
 }
 
 private suspend fun fixedDelayTicker(
-    delay: Long,
-    unit: TimeUnit,
-    initialDelay: Long,
+    delayMillis: Long,
+    initialDelayMillis: Long,
     channel: SendChannel<Unit>
 ) {
-    delay(initialDelay, unit)
+    delay(initialDelayMillis)
     while (true) {
         channel.send(Unit)
-        delay(delay, unit)
+        delay(delayMillis)
     }
 }
diff --git a/core/kotlinx-coroutines-core/src/scheduling/CoroutineScheduler.kt b/core/kotlinx-coroutines-core/src/scheduling/CoroutineScheduler.kt
index ea23ada..37e1932 100644
--- a/core/kotlinx-coroutines-core/src/scheduling/CoroutineScheduler.kt
+++ b/core/kotlinx-coroutines-core/src/scheduling/CoroutineScheduler.kt
@@ -300,6 +300,14 @@
     fun shutdown(timeout: Long) {
         // atomically set termination flag which is checked when workers are added or removed
         if (!isTerminated.compareAndSet(false, true)) return
+
+        /*
+         * Shutdown current thread. Note that shutdown is testing utility,
+         * so we don't do anything special to properly verify that no tasks are submitted after close()
+         */
+        val thread = Thread.currentThread()
+        (thread as? Worker)?.tryReleaseCpu(WorkerState.TERMINATED)
+
         // Capture # of created workers that cannot change anymore (mind the synchronized block!)
         val created = synchronized(workers) { createdWorkers }
         for (i in 1..created) {
@@ -653,7 +661,7 @@
          * Releases CPU token if worker has any and changes state to [newState]
          * @return whether worker had CPU token
          */
-        private fun tryReleaseCpu(newState: WorkerState): Boolean {
+        internal fun tryReleaseCpu(newState: WorkerState): Boolean {
             val previousState = state
             val hadCpu = previousState == WorkerState.CPU_ACQUIRED
             if (hadCpu) cpuPermits.release()
diff --git a/core/kotlinx-coroutines-core/src/scheduling/ExperimentalCoroutineDispatcher.kt b/core/kotlinx-coroutines-core/src/scheduling/ExperimentalCoroutineDispatcher.kt
index 7abbf90..776b7af 100644
--- a/core/kotlinx-coroutines-core/src/scheduling/ExperimentalCoroutineDispatcher.kt
+++ b/core/kotlinx-coroutines-core/src/scheduling/ExperimentalCoroutineDispatcher.kt
@@ -25,7 +25,7 @@
     private val corePoolSize: Int,
     private val maxPoolSize: Int,
     private val idleWorkerKeepAliveNs: Long
-) : ExecutorCoroutineDispatcher(), Delay {
+) : ExecutorCoroutineDispatcher() {
     constructor(
         corePoolSize: Int = CORE_POOL_SIZE,
         maxPoolSize: Int = MAX_POOL_SIZE
@@ -47,9 +47,6 @@
     override fun dispatchYield(context: CoroutineContext, block: Runnable): Unit =
         coroutineScheduler.dispatch(block, fair = true)
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>): Unit =
-            DefaultExecutor.scheduleResumeAfterDelay(time, unit, continuation)
-
     // TODO throw error when this API becomes public and close it in tests via another method
     override fun close() = coroutineScheduler.close()
 
@@ -101,7 +98,7 @@
     val dispatcher: ExperimentalCoroutineDispatcher,
     val parallelism: Int,
     override val taskMode: TaskMode
-) : ExecutorCoroutineDispatcher(), Delay, TaskContext, Executor {
+) : ExecutorCoroutineDispatcher(), TaskContext, Executor {
 
     private val queue = ConcurrentLinkedQueue<Runnable>()
     private val inFlightTasks = atomic(0)
@@ -193,7 +190,4 @@
         next = queue.poll() ?: return
         dispatch(next, true)
     }
-
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) =
-        dispatcher.scheduleResumeAfterDelay(time, unit, continuation)
 }
diff --git a/core/kotlinx-coroutines-core/src/test_/TestCoroutineContext.kt b/core/kotlinx-coroutines-core/src/test_/TestCoroutineContext.kt
index 8251d80..deb3e1a 100644
--- a/core/kotlinx-coroutines-core/src/test_/TestCoroutineContext.kt
+++ b/core/kotlinx-coroutines-core/src/test_/TestCoroutineContext.kt
@@ -25,8 +25,12 @@
  * This dispatcher's virtual time will be automatically advanced based based on the delayed actions
  * within the Coroutine(s).
  *
+ * **Note: This API will become obsolete in future updates due to integration with structured concurrency.**
+ *           See [issue #541](https://github.com/Kotlin/kotlinx.coroutines/issues/541).
+ *
  * @param name A user-readable name for debugging purposes.
  */
+@ObsoleteCoroutinesApi
 class TestCoroutineContext(private val name: String? = null) : CoroutineContext {
     private val uncaughtExceptions = mutableListOf<Throwable>()
 
@@ -209,14 +213,14 @@
     private inner class Dispatcher : CoroutineDispatcher(), Delay, EventLoop {
         override fun dispatch(context: CoroutineContext, block: Runnable) = post(block)
 
-        override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
+        override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
             postDelayed(Runnable {
                 with(continuation) { resumeUndispatched(Unit) }
-            }, unit.toMillis(time))
+            }, timeMillis)
         }
 
-        override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
-            val node = postDelayed(block, unit.toMillis(time))
+        override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
+            val node = postDelayed(block, timeMillis)
             return object : DisposableHandle {
                 override fun dispose() {
                     queue.remove(node)
@@ -260,10 +264,14 @@
  * [TestCoroutineContext.assertExceptions], the list of unhandled exceptions will have been cleared and this method will
  * not throw an [AssertionError].
  *
+ * **Note: This API will become obsolete in future updates due to integration with structured concurrency.**
+ *           See [issue #541](https://github.com/Kotlin/kotlinx.coroutines/issues/541).
+ *
  * @param testContext The provided [TestCoroutineContext]. If not specified, a default [TestCoroutineContext] will be
  * provided instead.
  * @param testBody The code of the unit-test.
  */
+@ObsoleteCoroutinesApi
 public fun withTestContext(testContext: TestCoroutineContext = TestCoroutineContext(), testBody: TestCoroutineContext.() -> Unit) {
     with (testContext) {
         testBody()
diff --git a/core/kotlinx-coroutines-core/src/timeunit/TimeUnit.kt b/core/kotlinx-coroutines-core/src/timeunit/TimeUnit.kt
index fc32f90..e8bf546 100644
--- a/core/kotlinx-coroutines-core/src/timeunit/TimeUnit.kt
+++ b/core/kotlinx-coroutines-core/src/timeunit/TimeUnit.kt
@@ -6,6 +6,9 @@
 
 /**
  * Time unit type alias for writing multiplatform code.
+ *
+ * @suppress **Deprecated** No replacement
  */
 @Suppress("ACTUAL_WITHOUT_EXPECT")
+@Deprecated(message = "No replacement")
 public actual typealias TimeUnit = java.util.concurrent.TimeUnit
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/test/AtomicCancellationTest.kt b/core/kotlinx-coroutines-core/test/AtomicCancellationTest.kt
index 3de6015..c2292f7 100644
--- a/core/kotlinx-coroutines-core/test/AtomicCancellationTest.kt
+++ b/core/kotlinx-coroutines-core/test/AtomicCancellationTest.kt
@@ -9,6 +9,7 @@
 import kotlin.test.*
 
 class AtomicCancellationTest : TestBase() {
+
     @Test
     fun testSendAtomicCancel() = runBlocking {
         expect(1)
diff --git a/core/kotlinx-coroutines-core/test/AwaitStressTest.kt b/core/kotlinx-coroutines-core/test/AwaitStressTest.kt
index 86569fb..b2683fe 100644
--- a/core/kotlinx-coroutines-core/test/AwaitStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/AwaitStressTest.kt
@@ -97,7 +97,7 @@
             barrier.await()
             try {
                 awaitAll(d1, d2)
-            } catch (e: JobCancellationException) {
+            } catch (e: CancellationException) {
                 cancelledOnce = true
             }
         }
diff --git a/core/kotlinx-coroutines-core/test/CommonPoolTest.kt b/core/kotlinx-coroutines-core/test/CommonPoolTest.kt
index a9985f5..99d5bab 100644
--- a/core/kotlinx-coroutines-core/test/CommonPoolTest.kt
+++ b/core/kotlinx-coroutines-core/test/CommonPoolTest.kt
@@ -9,6 +9,7 @@
 import java.lang.reflect.*
 import java.util.concurrent.*
 
+@Suppress("DEPRECATION")
 class CommonPoolTest {
     private inline fun <T> Try(block: () -> T) = try { block() } catch (e: Throwable) { null }
 
@@ -40,7 +41,7 @@
         println("CommonPool.isGoodCommonPool test passed")
     }
 
-    fun createFJP(
+    private fun createFJP(
         parallelism: Int,
         fjpCtor: Constructor<out Any>,
         dwtfCtor: Constructor<out Any>
diff --git a/core/kotlinx-coroutines-core/test/DefaultExecutorStressTest.kt b/core/kotlinx-coroutines-core/test/DefaultExecutorStressTest.kt
index ba2b804..05efec2 100644
--- a/core/kotlinx-coroutines-core/test/DefaultExecutorStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/DefaultExecutorStressTest.kt
@@ -5,7 +5,6 @@
 package kotlinx.coroutines.experimental
 
 import org.junit.*
-import java.util.concurrent.*
 
 class DefaultExecutorStressTest : TestBase() {
     @Test
@@ -19,7 +18,7 @@
                 val deferred = async {
                     expect(++expected)
                     val largeArray = IntArray(10_000) { it }
-                    delay(Long.MAX_VALUE, TimeUnit.NANOSECONDS)
+                    delay(Long.MAX_VALUE)
                     println(largeArray) // consume to avoid DCE, actually unreachable
                 }
 
@@ -28,7 +27,7 @@
                 deferred.cancel()
                 try {
                     deferred.await()
-                } catch (e: JobCancellationException) {
+                } catch (e: CancellationException) {
                     expect(++expected)
                 }
             }
diff --git a/core/kotlinx-coroutines-core/test/DelayJvmTest.kt b/core/kotlinx-coroutines-core/test/DelayJvmTest.kt
index f171281..a8d2515 100644
--- a/core/kotlinx-coroutines-core/test/DelayJvmTest.kt
+++ b/core/kotlinx-coroutines-core/test/DelayJvmTest.kt
@@ -61,7 +61,7 @@
             Wrapper(pool, continuation)
     }
 
-    class Wrapper<T>(val pool: Executor, val cont: Continuation<T>) : Continuation<T> {
+    class Wrapper<T>(val pool: Executor, private val cont: Continuation<T>) : Continuation<T> {
         override val context: CoroutineContext
             get() = cont.context
 
diff --git a/core/kotlinx-coroutines-core/test/ExecutorsTest.kt b/core/kotlinx-coroutines-core/test/ExecutorsTest.kt
index 4d938f2..6d98bd6 100644
--- a/core/kotlinx-coroutines-core/test/ExecutorsTest.kt
+++ b/core/kotlinx-coroutines-core/test/ExecutorsTest.kt
@@ -8,7 +8,7 @@
 import java.util.concurrent.Executors
 
 class ExecutorsTest : TestBase() {
-    fun checkThreadName(prefix: String) {
+    private fun checkThreadName(prefix: String) {
         val name = Thread.currentThread().name
         check(name.startsWith(prefix)) { "Expected thread name to start with '$prefix', found: '$name'" }
     }
diff --git a/core/kotlinx-coroutines-core/test/RunBlockingTest.kt b/core/kotlinx-coroutines-core/test/RunBlockingTest.kt
index 5cc4d69..02b1002 100644
--- a/core/kotlinx-coroutines-core/test/RunBlockingTest.kt
+++ b/core/kotlinx-coroutines-core/test/RunBlockingTest.kt
@@ -99,7 +99,7 @@
                 }
             }
             expectUnreached()
-        } catch (e: JobCancellationException) {
+        } catch (e: CancellationException) {
             finish(4)
         }
     }
diff --git a/core/kotlinx-coroutines-core/test/TestBase.kt b/core/kotlinx-coroutines-core/test/TestBase.kt
index 21e4faa..7d576cf 100644
--- a/core/kotlinx-coroutines-core/test/TestBase.kt
+++ b/core/kotlinx-coroutines-core/test/TestBase.kt
@@ -4,10 +4,13 @@
 
 package kotlinx.coroutines.experimental
 
+import kotlinx.coroutines.experimental.internal.*
 import org.junit.*
 import kotlinx.coroutines.experimental.scheduling.*
 import java.util.concurrent.atomic.*
 
+private val VERBOSE = systemProp("test.verbose", false)
+
 /**
  * Base class for tests, so that tests for predictable scheduling of actions in multiple coroutines sharing a single
  * thread can be written. Use it like this:
@@ -27,6 +30,7 @@
  * }
  * ```
  */
+@Suppress("DEPRECATION")
 public actual open class TestBase actual constructor() {
     /**
      * Is `true` when nightly stress test is done.
@@ -67,7 +71,7 @@
      * Throws [IllegalStateException] when `value` is false like `check` in stdlib, but also ensures that the
      * test will not complete successfully even if this exception is consumed somewhere in the test.
      */
-    public inline fun check(value: Boolean, lazyMessage: () -> Any): Unit {
+    public inline fun check(value: Boolean, lazyMessage: () -> Any) {
         if (!value) error(lazyMessage())
     }
 
@@ -76,6 +80,7 @@
      */
     public actual fun expect(index: Int) {
         val wasIndex = actionIndex.incrementAndGet()
+        if (VERBOSE) println("expect($index), wasIndex=$wasIndex")
         check(index == wasIndex) { "Expecting action index $index but it is actually $wasIndex" }
     }
 
diff --git a/core/kotlinx-coroutines-core/test/TestSecurityManager.kt b/core/kotlinx-coroutines-core/test/TestSecurityManager.kt
index 03c9386..f5280f0 100644
--- a/core/kotlinx-coroutines-core/test/TestSecurityManager.kt
+++ b/core/kotlinx-coroutines-core/test/TestSecurityManager.kt
@@ -6,6 +6,7 @@
 
 import java.security.Permission
 
+@Suppress("unused")
 class TestSecurityManager : SecurityManager() {
     override fun checkPropertyAccess(key: String?) {
         if (key?.startsWith("kotlinx.") == true)
diff --git a/core/kotlinx-coroutines-core/test/Threads.kt b/core/kotlinx-coroutines-core/test/Threads.kt
index c0c5435..ca69586 100644
--- a/core/kotlinx-coroutines-core/test/Threads.kt
+++ b/core/kotlinx-coroutines-core/test/Threads.kt
@@ -37,7 +37,7 @@
     println("===")
 }
 
-fun ThreadPoolDispatcher.dumpThreads(header: String) =
+fun ExecutorCoroutineDispatcher.dumpThreads(header: String) =
     currentThreads().filter { it is PoolThread && it.dispatcher == this@dumpThreads }.dumpThreads(header)
 
 fun checkTestThreads(threadsBefore: Set<Thread>) {
diff --git a/core/kotlinx-coroutines-core/test/VirtualTimeSource.kt b/core/kotlinx-coroutines-core/test/VirtualTimeSource.kt
index 8b67535..370c871 100644
--- a/core/kotlinx-coroutines-core/test/VirtualTimeSource.kt
+++ b/core/kotlinx-coroutines-core/test/VirtualTimeSource.kt
@@ -24,7 +24,7 @@
     }
 }
 
-private val NOT_PARKED = -1L
+private const val NOT_PARKED = -1L
 
 private class ThreadStatus {
     @Volatile @JvmField
@@ -34,9 +34,9 @@
     override fun toString(): String = "parkedTill = ${TimeUnit.NANOSECONDS.toMillis(parkedTill)} ms, permit = $permit"
 }
 
-private val MAX_WAIT_NANOS = 10_000_000_000L // 10s
-private val REAL_TIME_STEP_NANOS = 200_000_000L // 200 ms
-private val REAL_PARK_NANOS = 10_000_000L // 10 ms -- park for a little to better track real-time
+private const val MAX_WAIT_NANOS = 10_000_000_000L // 10s
+private const val REAL_TIME_STEP_NANOS = 200_000_000L // 200 ms
+private const val REAL_PARK_NANOS = 10_000_000L // 10 ms -- park for a little to better track real-time
 
 @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
 internal class VirtualTimeSource(
diff --git a/core/kotlinx-coroutines-core/test/channels/ActorTest.kt b/core/kotlinx-coroutines-core/test/channels/ActorTest.kt
index 3cfa8ea..478d95e 100644
--- a/core/kotlinx-coroutines-core/test/channels/ActorTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/ActorTest.kt
@@ -127,7 +127,7 @@
         try {
             job.await()
             expectUnreached()
-        } catch (e: JobCancellationException) {
+        } catch (e: CancellationException) {
             assertTrue(e.message?.contains("Job was cancelled") ?: false)
         }
 
diff --git a/core/kotlinx-coroutines-core/test/channels/ArrayChannelStressTest.kt b/core/kotlinx-coroutines-core/test/channels/ArrayChannelStressTest.kt
index 450a42f..ad5014b 100644
--- a/core/kotlinx-coroutines-core/test/channels/ArrayChannelStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/ArrayChannelStressTest.kt
@@ -21,7 +21,7 @@
     @Test
     fun testStress() = runTest {
         val n = 100_000 * stressTestMultiplier
-        val q = ArrayChannel<Int>(capacity)
+        val q = Channel<Int>(capacity)
         val sender = launch(kotlin.coroutines.experimental.coroutineContext) {
             for (i in 1..n) {
                 q.send(i)
diff --git a/core/kotlinx-coroutines-core/test/channels/BroadcastChannelMultiReceiveStressTest.kt b/core/kotlinx-coroutines-core/test/channels/BroadcastChannelMultiReceiveStressTest.kt
index f234d04..83937c5 100644
--- a/core/kotlinx-coroutines-core/test/channels/BroadcastChannelMultiReceiveStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/BroadcastChannelMultiReceiveStressTest.kt
@@ -6,7 +6,6 @@
 
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.selects.*
-import kotlinx.coroutines.experimental.timeunit.*
 import org.junit.*
 import org.junit.runner.*
 import org.junit.runners.*
@@ -17,7 +16,7 @@
  */
 @RunWith(Parameterized::class)
 class BroadcastChannelMultiReceiveStressTest(
-    val kind: TestBroadcastChannelKind
+    private val kind: TestBroadcastChannelKind
 ) : TestBase() {
     companion object {
         @Parameterized.Parameters(name = "{0}")
@@ -87,7 +86,7 @@
         println("      Sent $total events, waiting for receivers")
         stopOnReceive.set(total)
         try {
-            withTimeout(5, TimeUnit.SECONDS) {
+            withTimeout(5000) {
                 receivers.forEachIndexed { index, receiver ->
                     if (lastReceived[index].get() == total)
                         receiver.cancel()
diff --git a/core/kotlinx-coroutines-core/test/channels/BroadcastChannelSubStressTest.kt b/core/kotlinx-coroutines-core/test/channels/BroadcastChannelSubStressTest.kt
index dbfd04e..a542aef 100644
--- a/core/kotlinx-coroutines-core/test/channels/BroadcastChannelSubStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/BroadcastChannelSubStressTest.kt
@@ -5,7 +5,6 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.timeunit.*
 import org.junit.*
 import org.junit.runner.*
 import org.junit.runners.*
@@ -18,7 +17,7 @@
  */
 @RunWith(Parameterized::class)
 class BroadcastChannelSubStressTest(
-    val kind: TestBroadcastChannelKind
+    private val kind: TestBroadcastChannelKind
 ) : TestBase() {
     companion object {
         @Parameterized.Parameters(name = "{0}")
@@ -63,7 +62,7 @@
             check(curSent > prevSent) { "Send stalled at $curSent events" }
             prevSent = curSent
         }
-        withTimeout(5, TimeUnit.SECONDS) {
+        withTimeout(5000) {
             sender.cancelAndJoin()
             receiver.cancelAndJoin()
         }
diff --git a/core/kotlinx-coroutines-core/test/channels/ChannelAtomicCancelStressTest.kt b/core/kotlinx-coroutines-core/test/channels/ChannelAtomicCancelStressTest.kt
index 1e61bf4..72f9bf4 100644
--- a/core/kotlinx-coroutines-core/test/channels/ChannelAtomicCancelStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/ChannelAtomicCancelStressTest.kt
@@ -17,27 +17,27 @@
  * Tests cancel atomicity for channel send & receive operations, including their select versions.
  */
 @RunWith(Parameterized::class)
-class ChannelAtomicCancelStressTest(val kind: TestChannelKind) : TestBase() {
+class ChannelAtomicCancelStressTest(private val kind: TestChannelKind) : TestBase() {
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun params(): Collection<Array<Any>> = TestChannelKind.values().map { arrayOf<Any>(it) }
     }
 
-    val TEST_DURATION = 3000L * stressTestMultiplier
+    private val TEST_DURATION = 3000L * stressTestMultiplier
 
     val channel = kind.create()
-    val senderDone = ArrayChannel<Boolean>(1)
-    val receiverDone = ArrayChannel<Boolean>(1)
+    private val senderDone = Channel<Boolean>(1)
+    private val receiverDone = Channel<Boolean>(1)
 
-    var lastSent = 0
-    var lastReceived = 0
+    private var lastSent = 0
+    private var lastReceived = 0
 
-    var stoppedSender = 0
-    var stoppedReceiver = 0
+    private var stoppedSender = 0
+    private var stoppedReceiver = 0
 
-    var missedCnt = 0
-    var dupCnt = 0
+    private var missedCnt = 0
+    private var dupCnt = 0
 
     val failed = AtomicReference<Throwable>()
 
@@ -46,7 +46,7 @@
 
     fun fail(e: Throwable) = failed.compareAndSet(null, e)
 
-    inline fun cancellable(done: ArrayChannel<Boolean>, block: () -> Unit) {
+    private inline fun cancellable(done: Channel<Boolean>, block: () -> Unit) {
         try {
             block()
         } catch (e: Throwable) {
@@ -59,7 +59,7 @@
     }
 
     @Test
-    fun testAtomicCancelStress() = runBlocking<Unit> {
+    fun testAtomicCancelStress() = runBlocking {
         println("--- ChannelAtomicCancelStressTest $kind")
         val deadline = System.currentTimeMillis() + TEST_DURATION
         launchSender()
@@ -94,7 +94,7 @@
         }
     }
 
-    fun launchSender() {
+    private fun launchSender() {
         sender = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
             val rnd = Random()
             cancellable(senderDone) {
@@ -113,13 +113,13 @@
         }
     }
 
-    suspend fun stopSender() {
+    private suspend fun stopSender() {
         stoppedSender++
         sender.cancel()
         senderDone.receive()
     }
 
-    fun launchReceiver() {
+    private fun launchReceiver() {
         receiver = GlobalScope.launch(start = CoroutineStart.ATOMIC) {
             val rnd = Random()
             cancellable(receiverDone) {
@@ -140,7 +140,7 @@
         }
     }
 
-    suspend fun stopReceiver() {
+    private suspend fun stopReceiver() {
         stoppedReceiver++
         receiver.cancel()
         receiverDone.receive()
diff --git a/core/kotlinx-coroutines-core/test/channels/ChannelIsClosedLinearizabilityTest.kt b/core/kotlinx-coroutines-core/test/channels/ChannelIsClosedLinearizabilityTest.kt
index f4cd7df..204dafb 100644
--- a/core/kotlinx-coroutines-core/test/channels/ChannelIsClosedLinearizabilityTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/ChannelIsClosedLinearizabilityTest.kt
@@ -2,6 +2,8 @@
  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
 
+@file:Suppress("unused")
+
 package kotlinx.coroutines.experimental.channels
 
 import com.devexperts.dxlab.lincheck.*
diff --git a/core/kotlinx-coroutines-core/test/channels/ChannelLinearizabilityTest.kt b/core/kotlinx-coroutines-core/test/channels/ChannelLinearizabilityTest.kt
index a80defc..40eee20 100644
--- a/core/kotlinx-coroutines-core/test/channels/ChannelLinearizabilityTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/ChannelLinearizabilityTest.kt
@@ -2,6 +2,8 @@
  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
 
+@file:Suppress("unused")
+
 package kotlinx.coroutines.experimental.channels
 
 import com.devexperts.dxlab.lincheck.*
diff --git a/core/kotlinx-coroutines-core/test/channels/ChannelSendReceiveStressTest.kt b/core/kotlinx-coroutines-core/test/channels/ChannelSendReceiveStressTest.kt
index 57e69ec..c00e60f 100644
--- a/core/kotlinx-coroutines-core/test/channels/ChannelSendReceiveStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/ChannelSendReceiveStressTest.kt
@@ -14,9 +14,9 @@
 
 @RunWith(Parameterized::class)
 class ChannelSendReceiveStressTest(
-    val kind: TestChannelKind,
-    val nSenders: Int,
-    val nReceivers: Int
+    private val kind: TestChannelKind,
+    private val nSenders: Int,
+    private val nReceivers: Int
 ) : TestBase() {
     companion object {
         @Parameterized.Parameters(name = "{0}, nSenders={1}, nReceivers={2}")
@@ -24,24 +24,24 @@
         fun params(): Collection<Array<Any>> =
                 listOf(1, 2, 10).flatMap { nSenders ->
                     listOf(1, 10).flatMap { nReceivers ->
-                        TestChannelKind.values().map { arrayOf<Any>(it, nSenders, nReceivers) }
+                        TestChannelKind.values().map { arrayOf(it, nSenders, nReceivers) }
                     }
                 }
     }
 
-    val timeLimit = 30_000L * stressTestMultiplier // 30 sec
-    val nEvents = 200_000 * stressTestMultiplier
+    private val timeLimit = 30_000L * stressTestMultiplier // 30 sec
+    private val nEvents = 200_000 * stressTestMultiplier
 
-    val maxBuffer = 10_000 // artificial limit for LinkedListChannel
+    private val maxBuffer = 10_000 // artificial limit for LinkedListChannel
 
     val channel = kind.create()
-    val sendersCompleted = AtomicInteger()
-    val receiversCompleted = AtomicInteger()
-    val dupes = AtomicInteger()
-    val sentTotal = AtomicInteger()
+    private val sendersCompleted = AtomicInteger()
+    private val receiversCompleted = AtomicInteger()
+    private val dupes = AtomicInteger()
+    private val sentTotal = AtomicInteger()
     val received = AtomicIntegerArray(nEvents)
-    val receivedTotal = AtomicInteger()
-    val receivedBy = IntArray(nReceivers)
+    private val receivedTotal = AtomicInteger()
+    private val receivedBy = IntArray(nReceivers)
 
     @Test
     fun testSendReceiveStress() = runBlocking {
diff --git a/core/kotlinx-coroutines-core/test/channels/ChannelsConsumeTest.kt b/core/kotlinx-coroutines-core/test/channels/ChannelsConsumeTest.kt
index aa58e7a..9875b78 100644
--- a/core/kotlinx-coroutines-core/test/channels/ChannelsConsumeTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/ChannelsConsumeTest.kt
@@ -630,7 +630,7 @@
 
     @Test
     fun testWithIndex() {
-        checkTransform(sourceList.withIndex().toList()) {
+        checkTransform(sourceList.asSequence().withIndex().toList()) {
             withIndex()
         }
     }
diff --git a/core/kotlinx-coroutines-core/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt b/core/kotlinx-coroutines-core/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt
index 3e0729a..2ec11eb 100644
--- a/core/kotlinx-coroutines-core/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/ConflatedBroadcastChannelNotifyStressTest.kt
@@ -11,20 +11,20 @@
 import java.util.concurrent.atomic.*
 
 class ConflatedBroadcastChannelNotifyStressTest : TestBase() {
-    val nSenders = 2
-    val nReceivers = 3
-    val nEvents = 500_000 * stressTestMultiplier
-    val timeLimit = 30_000L * stressTestMultiplier // 30 sec
+    private val nSenders = 2
+    private val nReceivers = 3
+    private val nEvents = 500_000 * stressTestMultiplier
+    private val timeLimit = 30_000L * stressTestMultiplier // 30 sec
 
-    val broadcast = ConflatedBroadcastChannel<Int>()
+    private val broadcast = ConflatedBroadcastChannel<Int>()
 
-    val sendersCompleted = AtomicInteger()
-    val receiversCompleted = AtomicInteger()
-    val sentTotal = AtomicInteger()
-    val receivedTotal = AtomicInteger()
+    private val sendersCompleted = AtomicInteger()
+    private val receiversCompleted = AtomicInteger()
+    private val sentTotal = AtomicInteger()
+    private val receivedTotal = AtomicInteger()
 
     @Test
-    fun testStressNotify()= runBlocking<Unit> {
+    fun testStressNotify()= runBlocking {
         println("--- ConflatedBroadcastChannelNotifyStressTest")
         val senders = List(nSenders) { senderId ->
             launch(Dispatchers.Default + CoroutineName("Sender$senderId")) {
@@ -81,7 +81,7 @@
         assertThat(sentTotal.get(), IsEqual(nEvents))
     }
 
-    suspend fun waitForEvent(): Int =
+    private suspend fun waitForEvent(): Int =
         with(broadcast.openSubscription()) {
             val value = receive()
             cancel()
diff --git a/core/kotlinx-coroutines-core/test/channels/ConflatedChannelCloseStressTest.kt b/core/kotlinx-coroutines-core/test/channels/ConflatedChannelCloseStressTest.kt
index 7d7b33c..a06224a 100644
--- a/core/kotlinx-coroutines-core/test/channels/ConflatedChannelCloseStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/ConflatedChannelCloseStressTest.kt
@@ -5,20 +5,17 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import org.junit.After
-import org.junit.Test
-import java.util.concurrent.atomic.AtomicInteger
-import java.util.concurrent.atomic.AtomicReference
-import kotlin.coroutines.experimental.*
+import org.junit.*
+import java.util.concurrent.atomic.*
 
 class ConflatedChannelCloseStressTest : TestBase() {
 
-    val nSenders = 2
-    val testSeconds = 3 * stressTestMultiplier
+    private val nSenders = 2
+    private val testSeconds = 3 * stressTestMultiplier
 
-    val curChannel = AtomicReference<ConflatedChannel<Int>>(ConflatedChannel())
-    val sent = AtomicInteger()
-    val closed = AtomicInteger()
+    private val curChannel = AtomicReference<Channel<Int>>(Channel(Channel.CONFLATED))
+    private val sent = AtomicInteger()
+    private val closed = AtomicInteger()
     val received = AtomicInteger()
 
     val pool = newFixedThreadPoolContext(nSenders + 2, "TestStressClose")
@@ -29,7 +26,7 @@
     }
 
     @Test
-    fun testStressClose() = runBlocking<Unit> {
+    fun testStressClose() = runBlocking {
         println("--- ConflatedChannelCloseStressTest with nSenders=$nSenders")
         val senderJobs = List(nSenders) { Job() }
         val senders = List(nSenders) { senderId ->
@@ -100,7 +97,7 @@
 
     private fun flipChannel() {
         val oldChannel = curChannel.get()
-        val newChannel = ConflatedChannel<Int>()
+        val newChannel = Channel<Int>(Channel.CONFLATED)
         curChannel.set(newChannel)
         check(oldChannel.close())
     }
diff --git a/core/kotlinx-coroutines-core/test/channels/InvokeOnCloseStressTest.kt b/core/kotlinx-coroutines-core/test/channels/InvokeOnCloseStressTest.kt
index 7c52df7..7203f1f 100644
--- a/core/kotlinx-coroutines-core/test/channels/InvokeOnCloseStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/InvokeOnCloseStressTest.kt
@@ -5,7 +5,6 @@
 package kotlinx.coroutines.experimental.channels
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.channels.*
 import org.junit.*
 import org.junit.Test
 import java.util.concurrent.*
diff --git a/core/kotlinx-coroutines-core/test/channels/RandevouzChannelStressTest.kt b/core/kotlinx-coroutines-core/test/channels/RandevouzChannelStressTest.kt
index 1fc2c8f..2558c29 100644
--- a/core/kotlinx-coroutines-core/test/channels/RandevouzChannelStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/RandevouzChannelStressTest.kt
@@ -12,7 +12,7 @@
     @Test
     fun testStress() = runTest {
         val n = 100_000 * stressTestMultiplier
-        val q = RendezvousChannel<Int>()
+        val q = Channel<Int>(Channel.RENDEZVOUS)
         val sender = launch {
             for (i in 1..n) q.send(i)
             expect(2)
diff --git a/core/kotlinx-coroutines-core/test/channels/SendReceiveJvmStressTest.kt b/core/kotlinx-coroutines-core/test/channels/SendReceiveJvmStressTest.kt
index 8c5b080..c1ed2b3 100644
--- a/core/kotlinx-coroutines-core/test/channels/SendReceiveJvmStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/SendReceiveJvmStressTest.kt
@@ -16,11 +16,11 @@
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun params(): Collection<Array<Any>> = listOf(
-            ArrayChannel<Int>(1),
-            ArrayChannel<Int>(10),
-            ArrayChannel<Int>(1_000_000),
-            LinkedListChannel<Int>(),
-            RendezvousChannel<Int>()
+            Channel<Int>(1),
+            Channel (10),
+            Channel(1_000_000),
+            Channel(Channel.UNLIMITED),
+            Channel(Channel.RENDEZVOUS)
         ).map { arrayOf<Any>(it) }
     }
 
diff --git a/core/kotlinx-coroutines-core/test/channels/SimpleSendReceiveJvmTest.kt b/core/kotlinx-coroutines-core/test/channels/SimpleSendReceiveJvmTest.kt
index 1198952..da5f7cd 100644
--- a/core/kotlinx-coroutines-core/test/channels/SimpleSendReceiveJvmTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/SimpleSendReceiveJvmTest.kt
@@ -10,11 +10,10 @@
 import org.junit.Assert.*
 import org.junit.runner.*
 import org.junit.runners.*
-import kotlin.coroutines.experimental.*
 
 @RunWith(Parameterized::class)
 class SimpleSendReceiveJvmTest(
-    val kind: TestChannelKind,
+    private val kind: TestChannelKind,
     val n: Int,
     val concurrent: Boolean
 ) {
diff --git a/core/kotlinx-coroutines-core/test/channels/TickerChannelCommonTest.kt b/core/kotlinx-coroutines-core/test/channels/TickerChannelCommonTest.kt
index b413097..9ad8ae3 100644
--- a/core/kotlinx-coroutines-core/test/channels/TickerChannelCommonTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/TickerChannelCommonTest.kt
@@ -23,12 +23,12 @@
     enum class Channel {
         FIXED_PERIOD {
             override fun invoke(delay: Long, initialDelay: Long) =
-                ticker(delay, initialDelay = initialDelay, mode = TickerMode.FIXED_PERIOD)
+                ticker(delay, initialDelayMillis = initialDelay, mode = TickerMode.FIXED_PERIOD)
         },
 
         FIXED_DELAY {
             override fun invoke(delay: Long, initialDelay: Long) =
-                ticker(delay, initialDelay = initialDelay, mode = TickerMode.FIXED_DELAY)
+                ticker(delay, initialDelayMillis = initialDelay, mode = TickerMode.FIXED_DELAY)
         };
 
         abstract operator fun invoke(delay: Long, initialDelay: Long = 0): ReceiveChannel<Unit>
diff --git a/core/kotlinx-coroutines-core/test/channels/TickerChannelTest.kt b/core/kotlinx-coroutines-core/test/channels/TickerChannelTest.kt
index 8bf9f4b..37c1c6e 100644
--- a/core/kotlinx-coroutines-core/test/channels/TickerChannelTest.kt
+++ b/core/kotlinx-coroutines-core/test/channels/TickerChannelTest.kt
@@ -11,7 +11,7 @@
     @Test
     fun testFixedDelayChannelBackpressure() = withVirtualTimeSource {
         runTest {
-            val delayChannel = ticker(delay = 1000, initialDelay = 0, mode = TickerMode.FIXED_DELAY)
+            val delayChannel = ticker(delayMillis = 1000, initialDelayMillis = 0, mode = TickerMode.FIXED_DELAY)
             delayChannel.checkNotEmpty()
             delayChannel.checkEmpty()
 
@@ -28,7 +28,7 @@
     @Test
     fun testDelayChannelBackpressure() = withVirtualTimeSource {
         runTest {
-            val delayChannel = ticker(delay = 1000, initialDelay = 0)
+            val delayChannel = ticker(delayMillis = 1000, initialDelayMillis = 0)
             delayChannel.checkNotEmpty()
             delayChannel.checkEmpty()
 
@@ -47,7 +47,7 @@
     @Test
     fun testDelayChannelBackpressure2() = withVirtualTimeSource {
         runTest {
-            val delayChannel = ticker(delay = 1000, initialDelay = 0)
+            val delayChannel = ticker(delayMillis = 1000, initialDelayMillis = 0)
             delayChannel.checkNotEmpty()
             delayChannel.checkEmpty()
 
diff --git a/core/kotlinx-coroutines-core/test/exceptions/JobExceptionHandlingTest.kt b/core/kotlinx-coroutines-core/test/exceptions/JobExceptionHandlingTest.kt
index 3e3ed6d..f91399b 100644
--- a/core/kotlinx-coroutines-core/test/exceptions/JobExceptionHandlingTest.kt
+++ b/core/kotlinx-coroutines-core/test/exceptions/JobExceptionHandlingTest.kt
@@ -106,7 +106,7 @@
                     expect(3) // <- child's child is launched successfully
                     try {
                         yield()
-                    } catch (e: JobCancellationException) {
+                    } catch (e: CancellationException) {
                         throw ArithmeticException()
                     }
                 }
@@ -169,7 +169,7 @@
                     expect(3) // <- child's child is launched successfully
                     try {
                         yield()
-                    } catch (e: JobCancellationException) {
+                    } catch (e: CancellationException) {
                         throw ArithmeticException()
                     }
                 }
diff --git a/core/kotlinx-coroutines-core/test/exceptions/JobExceptionsStressTest.kt b/core/kotlinx-coroutines-core/test/exceptions/JobExceptionsStressTest.kt
index ca44e27..bd0b597 100644
--- a/core/kotlinx-coroutines-core/test/exceptions/JobExceptionsStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/exceptions/JobExceptionsStressTest.kt
@@ -13,7 +13,7 @@
 
 class JobExceptionsStressTest : TestBase() {
 
-    private val executor: ThreadPoolDispatcher by lazy { newFixedThreadPoolContext(5, "JobExceptionsStressTest") }
+    private val executor = newFixedThreadPoolContext(5, "JobExceptionsStressTest")
 
     @After
     fun tearDown() {
diff --git a/core/kotlinx-coroutines-core/test/exceptions/WithContextExceptionHandlingTest.kt b/core/kotlinx-coroutines-core/test/exceptions/WithContextExceptionHandlingTest.kt
index d6e2f74..dad64a3 100644
--- a/core/kotlinx-coroutines-core/test/exceptions/WithContextExceptionHandlingTest.kt
+++ b/core/kotlinx-coroutines-core/test/exceptions/WithContextExceptionHandlingTest.kt
@@ -111,7 +111,7 @@
             assertEquals(1, thrown.suppressed().size)
 
             val suppressed = thrown.suppressed()[0]
-            assertTrue(suppressed is JobCancellationException)
+            assertTrue(suppressed is CancellationException)
             assertTrue(suppressed.cause is IllegalStateException)
         }
     }
@@ -130,7 +130,7 @@
             assertEquals(1, thrown.suppressed().size)
 
             val suppressed = thrown.suppressed()[0]
-            assertTrue(suppressed is JobCancellationException)
+            assertTrue(suppressed is CancellationException)
             assertTrue(suppressed.cause is IllegalStateException)
 
         }
diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt b/core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt
index 92b9367..fdaac97 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-basic-02b.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
+fun main(args: Array<String>) = runBlocking { // start main coroutine
     GlobalScope.launch { // launch new coroutine in background and continue
         delay(1000L)
         println("World!")
diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-03.kt b/core/kotlinx-coroutines-core/test/guide/example-basic-03.kt
index 8f12b7e..00af13d 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-basic-03.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-basic-03.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val job = GlobalScope.launch { // launch new coroutine and keep a reference to its Job
         delay(1000L)
         println("World!")
diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-03s.kt b/core/kotlinx-coroutines-core/test/guide/example-basic-03s.kt
index 94e0ee4..199237e 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-basic-03s.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-basic-03s.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> { // this: CoroutineScope
+fun main(args: Array<String>) = runBlocking { // this: CoroutineScope
     launch { // launch new coroutine in the scope of runBlocking
         delay(1000L)
         println("World!")
diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-04.kt b/core/kotlinx-coroutines-core/test/guide/example-basic-04.kt
index 1ff45e9..00483a2 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-basic-04.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-basic-04.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> { // this: CoroutineScope
+fun main(args: Array<String>) = runBlocking { // this: CoroutineScope
     launch { 
         delay(200L)
         println("Task from runBlocking")
diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-05.kt b/core/kotlinx-coroutines-core/test/guide/example-basic-05.kt
index 1380254..6d25eca 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-basic-05.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-basic-05.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     launch { doWorld() }
     println("Hello,")
 }
diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-05s.kt b/core/kotlinx-coroutines-core/test/guide/example-basic-05s.kt
index c3df91d..62f5d71 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-basic-05s.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-basic-05s.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     launchDoWorld()
     println("Hello,")
 }
diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-06.kt b/core/kotlinx-coroutines-core/test/guide/example-basic-06.kt
index bcf4e37..8182934 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-basic-06.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-basic-06.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     repeat(100_000) { // launch a lot of coroutines
         launch {
             delay(1000L)
diff --git a/core/kotlinx-coroutines-core/test/guide/example-basic-07.kt b/core/kotlinx-coroutines-core/test/guide/example-basic-07.kt
index a5af1ab..829e7b9 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-basic-07.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-basic-07.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     GlobalScope.launch {
         repeat(1000) { i ->
             println("I'm sleeping $i ...")
diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt b/core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt
index 8760f37..5862235 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-cancel-01.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val job = launch {
         repeat(1000) { i ->
             println("I'm sleeping $i ...")
diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt b/core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt
index a175490..77206eb 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-cancel-02.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val startTime = timeSource.currentTimeMillis()
     val job = launch(Dispatchers.Default) {
         var nextPrintTime = startTime
diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt b/core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt
index e44e502..ff97f75 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-cancel-03.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val startTime = timeSource.currentTimeMillis()
     val job = launch(Dispatchers.Default) {
         var nextPrintTime = startTime
diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt b/core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt
index fa7da09..8533d50 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-cancel-04.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val job = launch {
         try {
             repeat(1000) { i ->
diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt b/core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt
index 268a4e9..bed20d5 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-cancel-05.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val job = launch {
         try {
             repeat(1000) { i ->
diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt b/core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt
index 7e6f046..c0c38c0 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-cancel-06.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     withTimeout(1300L) {
         repeat(1000) { i ->
             println("I'm sleeping $i ...")
diff --git a/core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt b/core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt
index 1dbe8f4..16b27e2 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-cancel-07.kt
@@ -7,7 +7,7 @@
 
 import kotlinx.coroutines.experimental.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val result = withTimeoutOrNull(1300L) {
         repeat(1000) { i ->
             println("I'm sleeping $i ...")
diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-01.kt b/core/kotlinx-coroutines-core/test/guide/example-channel-01.kt
index 4758a86..95b8092 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-channel-01.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-channel-01.kt
@@ -8,7 +8,7 @@
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val channel = Channel<Int>()
     launch {
         // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-02.kt b/core/kotlinx-coroutines-core/test/guide/example-channel-02.kt
index 452401a..35d5a90 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-channel-02.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-channel-02.kt
@@ -8,7 +8,7 @@
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val channel = Channel<Int>()
     launch {
         for (x in 1..5) channel.send(x * x)
diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-03.kt b/core/kotlinx-coroutines-core/test/guide/example-channel-03.kt
index 0d52b32..a80cbab 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-channel-03.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-channel-03.kt
@@ -8,11 +8,11 @@
 import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
 
-fun CoroutineScope.produceSquares() = produce<Int> {
+fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
     for (x in 1..5) send(x * x)
 }
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val squares = produceSquares()
     squares.consumeEach { println(it) }
     println("Done!")
diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-04.kt b/core/kotlinx-coroutines-core/test/guide/example-channel-04.kt
index 197b5d0..50e04ec 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-channel-04.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-channel-04.kt
@@ -13,11 +13,11 @@
     while (true) send(x++) // infinite stream of integers starting from 1
 }
 
-fun CoroutineScope.square(numbers: ReceiveChannel<Int>) = produce<Int> {
+fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce {
     for (x in numbers) send(x * x)
 }
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val numbers = produceNumbers() // produces integers from 1 and on
     val squares = square(numbers) // squares integers
     for (i in 1..5) println(squares.receive()) // print first five
diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-05.kt b/core/kotlinx-coroutines-core/test/guide/example-channel-05.kt
index 5534e0f..0ef3e78 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-channel-05.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-channel-05.kt
@@ -18,7 +18,7 @@
     for (x in numbers) if (x % prime != 0) send(x)
 }
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     var cur = numbersFrom(2)
     for (i in 1..10) {
         val prime = cur.receive()
diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-07.kt b/core/kotlinx-coroutines-core/test/guide/example-channel-07.kt
index 4c1ae65..191c505 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-channel-07.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-channel-07.kt
@@ -16,7 +16,7 @@
     }
 }
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val channel = Channel<String>()
     launch { sendString(channel, "foo", 200L) }
     launch { sendString(channel, "BAR!", 500L) }
diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-09.kt b/core/kotlinx-coroutines-core/test/guide/example-channel-09.kt
index cf6421a..4eabebe 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-channel-09.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-channel-09.kt
@@ -11,7 +11,7 @@
 
 data class Ball(var hits: Int)
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val table = Channel<Ball>() // a shared table
     launch { player("ping", table) }
     launch { player("pong", table) }
diff --git a/core/kotlinx-coroutines-core/test/guide/example-channel-10.kt b/core/kotlinx-coroutines-core/test/guide/example-channel-10.kt
index 258f658..6d3622c 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-channel-10.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-channel-10.kt
@@ -9,7 +9,7 @@
 import kotlinx.coroutines.experimental.channels.*
 
 fun main(args: Array<String>) = runBlocking<Unit> {
-    val tickerChannel = ticker(delay = 100, initialDelay = 0) // create ticker channel
+    val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
     var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
     println("Initial element is available immediately: $nextElement") // initial delay hasn't passed yet
 
diff --git a/core/kotlinx-coroutines-core/test/guide/example-exceptions-06.kt b/core/kotlinx-coroutines-core/test/guide/example-exceptions-06.kt
index 6d95e3f..d08c57a 100644
--- a/core/kotlinx-coroutines-core/test/guide/example-exceptions-06.kt
+++ b/core/kotlinx-coroutines-core/test/guide/example-exceptions-06.kt
@@ -23,8 +23,8 @@
         }
         try {
             inner.join()
-        } catch (e: JobCancellationException) {
-            println("Rethrowing JobCancellationException with original cause")
+        } catch (e: CancellationException) {
+            println("Rethrowing CancellationException with original cause")
             throw e
         }
     }
diff --git a/core/kotlinx-coroutines-core/test/guide/test/CancellationTimeOutsGuideTest.kt b/core/kotlinx-coroutines-core/test/guide/test/CancellationTimeOutsGuideTest.kt
index 17b0998..36a7875 100644
--- a/core/kotlinx-coroutines-core/test/guide/test/CancellationTimeOutsGuideTest.kt
+++ b/core/kotlinx-coroutines-core/test/guide/test/CancellationTimeOutsGuideTest.kt
@@ -71,7 +71,7 @@
             "I'm sleeping 0 ...",
             "I'm sleeping 1 ...",
             "I'm sleeping 2 ...",
-            "Exception in thread \"main\" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 MILLISECONDS"
+            "Exception in thread \"main\" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 ms"
         )
     }
 
diff --git a/core/kotlinx-coroutines-core/test/guide/test/ExceptionsGuideTest.kt b/core/kotlinx-coroutines-core/test/guide/test/ExceptionsGuideTest.kt
index b9a46fc..5b2ae61 100644
--- a/core/kotlinx-coroutines-core/test/guide/test/ExceptionsGuideTest.kt
+++ b/core/kotlinx-coroutines-core/test/guide/test/ExceptionsGuideTest.kt
@@ -52,7 +52,7 @@
     @Test
     fun testKotlinxCoroutinesExperimentalGuideExceptions06() {
         test("KotlinxCoroutinesExperimentalGuideExceptions06") { kotlinx.coroutines.experimental.guide.exceptions06.main(emptyArray()) }.verifyLines(
-            "Rethrowing JobCancellationException with original cause",
+            "Rethrowing CancellationException with original cause",
             "Caught original java.io.IOException"
         )
     }
diff --git a/core/kotlinx-coroutines-core/test/guide/test/TestUtil.kt b/core/kotlinx-coroutines-core/test/guide/test/TestUtil.kt
index c1e55c8..8b3c051 100644
--- a/core/kotlinx-coroutines-core/test/guide/test/TestUtil.kt
+++ b/core/kotlinx-coroutines-core/test/guide/test/TestUtil.kt
@@ -24,6 +24,7 @@
 private const val SHUTDOWN_TIMEOUT = 5000L // 5 sec at most to wait
 private val OUT_ENABLED = systemProp("guide.tests.sout", false)
 
+@Suppress("DEPRECATION")
 fun test(name: String, block: () -> Unit): List<String> = outputException(name) {
     val sout = System.out
     val oldOut = if (OUT_ENABLED) System.out else NullOut
diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListAtomicStressLFTest.kt b/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListAtomicStressLFTest.kt
index a29af3d..832d6e6 100644
--- a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListAtomicStressLFTest.kt
+++ b/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListAtomicStressLFTest.kt
@@ -23,15 +23,15 @@
 
     private val TEST_DURATION_SEC = 5 * stressTestMultiplier
 
-    val nLists = 4
-    val nAdderThreads = 4
-    val nRemoverThreads = 4
+    private val nLists = 4
+    private val nAdderThreads = 4
+    private val nRemoverThreads = 4
 
-    val lists = Array(nLists) { LockFreeLinkedListHead() }
+    private val lists = Array(nLists) { LockFreeLinkedListHead() }
 
-    val undone = AtomicLong()
-    val missed = AtomicLong()
-    val removed = AtomicLong()
+    private val undone = AtomicLong()
+    private val missed = AtomicLong()
+    private val removed = AtomicLong()
     val error = AtomicReference<Throwable>()
 
     @Test
diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListLongStressTest.kt b/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListLongStressTest.kt
index 92a7457..e005327 100644
--- a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListLongStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListLongStressTest.kt
@@ -21,13 +21,13 @@
     val list = LockFreeLinkedListHead()
 
     val threads = mutableListOf<Thread>()
-    val nAdded = 10_000_000 // should not stress more, because that'll run out of memory
-    val nAddThreads = 4 // must be power of 2 (!!!)
-    val nRemoveThreads = 6
-    val removeProbability = 0.2
-    val workingAdders = AtomicInteger(nAddThreads)
+    private val nAdded = 10_000_000 // should not stress more, because that'll run out of memory
+    private val nAddThreads = 4 // must be power of 2 (!!!)
+    private val nRemoveThreads = 6
+    private val removeProbability = 0.2
+    private val workingAdders = AtomicInteger(nAddThreads)
 
-    fun shallRemove(i: Int) = i and 63 != 42
+    private fun shallRemove(i: Int) = i and 63 != 42
 
     @Test
     fun testStress() {
diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListShortStressTest.kt b/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListShortStressTest.kt
index f85702c..49c3e17 100644
--- a/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListShortStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/internal/LockFreeLinkedListShortStressTest.kt
@@ -20,17 +20,17 @@
     data class IntNode(val i: Int) : LockFreeLinkedListNode()
     val list = LockFreeLinkedListHead()
 
-    val TEST_DURATION = 5000L * stressTestMultiplier
+    private val TEST_DURATION = 5000L * stressTestMultiplier
 
     val threads = mutableListOf<Thread>()
-    val nAdderThreads = 6
-    val nRemoverThreads = 4
-    val completedAdder = AtomicInteger()
-    val completedRemover = AtomicInteger()
+    private val nAdderThreads = 6
+    private val nRemoverThreads = 4
+    private val completedAdder = AtomicInteger()
+    private val completedRemover = AtomicInteger()
 
-    val undone = AtomicInteger()
-    val missed = AtomicInteger()
-    val removed = AtomicInteger()
+    private val undone = AtomicInteger()
+    private val missed = AtomicInteger()
+    private val removed = AtomicInteger()
 
     @Test
     fun testStress() {
diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeListLinearizabilityTest.kt b/core/kotlinx-coroutines-core/test/internal/LockFreeListLinearizabilityTest.kt
index ce3e299..2464458 100644
--- a/core/kotlinx-coroutines-core/test/internal/LockFreeListLinearizabilityTest.kt
+++ b/core/kotlinx-coroutines-core/test/internal/LockFreeListLinearizabilityTest.kt
@@ -2,6 +2,8 @@
  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
 
+@file:Suppress("unused")
+
 package kotlinx.coroutines.experimental.internal
 
 import com.devexperts.dxlab.lincheck.*
@@ -15,7 +17,7 @@
 class LockFreeListLinearizabilityTest : TestBase() {
     class Node(val value: Int): LockFreeLinkedListNode()
 
-    lateinit var q: LockFreeLinkedListHead
+    private lateinit var q: LockFreeLinkedListHead
 
     @Reset
     fun resetList() {
@@ -44,7 +46,7 @@
         return node.value
     }
 
-    fun Any.isSame(value: Int) = this is Node && this.value == value
+    private fun Any.isSame(value: Int) = this is Node && this.value == value
 
     @Test
     fun testAddRemoveLinearizability() {
diff --git a/core/kotlinx-coroutines-core/test/internal/LockFreeMPSCQueueLinearizabilityTest.kt b/core/kotlinx-coroutines-core/test/internal/LockFreeMPSCQueueLinearizabilityTest.kt
index 69e24ad..befbc19 100644
--- a/core/kotlinx-coroutines-core/test/internal/LockFreeMPSCQueueLinearizabilityTest.kt
+++ b/core/kotlinx-coroutines-core/test/internal/LockFreeMPSCQueueLinearizabilityTest.kt
@@ -2,6 +2,8 @@
  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
 
+@file:Suppress("unused")
+
 package kotlinx.coroutines.experimental.internal
 
 import com.devexperts.dxlab.lincheck.*
diff --git a/core/kotlinx-coroutines-core/test/internal/ThreadSafeHeapTest.kt b/core/kotlinx-coroutines-core/test/internal/ThreadSafeHeapTest.kt
index 74e593c..12a24a5 100644
--- a/core/kotlinx-coroutines-core/test/internal/ThreadSafeHeapTest.kt
+++ b/core/kotlinx-coroutines-core/test/internal/ThreadSafeHeapTest.kt
@@ -87,7 +87,7 @@
             assertTrue(h.remove(rndNode))
             // remove head and validate
             val headNode = h.removeFirstOrNull()!! // must not be null!!!
-            assertTrue(headNode === set.first(), "Expected ${set.first()}, but found $headNode, remaining size ${h.size}")
+            assertSame(headNode, set.first(), "Expected ${set.first()}, but found $headNode, remaining size ${h.size}")
             assertTrue(set.remove(headNode))
             assertEquals(set.size, h.size)
         }
diff --git a/core/kotlinx-coroutines-core/test/linearizability/FixedBehaviourExecutionGenerator.kt b/core/kotlinx-coroutines-core/test/linearizability/FixedBehaviourExecutionGenerator.kt
index b223bba..644a7b0 100644
--- a/core/kotlinx-coroutines-core/test/linearizability/FixedBehaviourExecutionGenerator.kt
+++ b/core/kotlinx-coroutines-core/test/linearizability/FixedBehaviourExecutionGenerator.kt
@@ -68,6 +68,7 @@
 }
 
 // Ad-hoc fixed execution injection for lin-checker
+@Suppress("unused")
 class FixedBehaviourExecutionGenerator(testConfiguration: CTestConfiguration, testStructure: CTestStructure)
     : ExecutionGenerator(testConfiguration, testStructure) {
 
diff --git a/core/kotlinx-coroutines-core/test/linearizability/LinTesting.kt b/core/kotlinx-coroutines-core/test/linearizability/LinTesting.kt
index d417d59..e45fa7b 100644
--- a/core/kotlinx-coroutines-core/test/linearizability/LinTesting.kt
+++ b/core/kotlinx-coroutines-core/test/linearizability/LinTesting.kt
@@ -65,9 +65,10 @@
 ) : Verifier(actorsPerThread, testInstance, resetMethod) {
     private val possibleResultsSet: Set<List<List<Result>>> =
         generateAllLinearizableExecutions(actorsPerThread)
+            .asSequence()
             .map { linEx: List<Actor> ->
                 val res: List<Result> = executeActors(testInstance, linEx)
-                val actorIds = linEx.withIndex().associateBy({ it.value}, { it.index })
+                val actorIds = linEx.asSequence().withIndex().associateBy({ it.value}, { it.index })
                 actorsPerThread.map { actors -> actors.map { actor -> res[actorIds[actor]!!] } }
             }.toSet()
 
diff --git a/core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherStressTest.kt b/core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherStressTest.kt
index 79ec6d4..5c79f8b 100644
--- a/core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/scheduling/BlockingCoroutineDispatcherStressTest.kt
@@ -2,6 +2,8 @@
  * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
  */
 
+@file:Suppress("DeferredResultUnused")
+
 package kotlinx.coroutines.experimental.scheduling
 
 import kotlinx.coroutines.experimental.*
@@ -109,7 +111,7 @@
 
         repeat(iterations) {
             // Overwhelm global queue with external CPU tasks
-            val cpuTasks = (1..CORES_COUNT).map { async(dispatcher) { while (true) delay(1, TimeUnit.NANOSECONDS) } }
+            val cpuTasks = (1..CORES_COUNT).map { async(dispatcher) { while (true) delay(1) } }
 
             val barrier = CyclicBarrier(blockingLimit + 1)
             // Should eat all limit * 3 cpu without any starvation
diff --git a/core/kotlinx-coroutines-core/test/scheduling/BlockingIOTerminationStressTest.kt b/core/kotlinx-coroutines-core/test/scheduling/BlockingIOTerminationStressTest.kt
index 48e2653..f43f546 100644
--- a/core/kotlinx-coroutines-core/test/scheduling/BlockingIOTerminationStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/scheduling/BlockingIOTerminationStressTest.kt
@@ -29,7 +29,7 @@
         while (System.currentTimeMillis() < deadline) {
             Thread.sleep(rnd.nextInt(30).toLong())
             repeat(rnd.nextInt(5) + 1) {
-                launch(ioDispatcher) {
+                GlobalScope.launch(ioDispatcher) {
                     Thread.sleep(rnd.nextInt(5).toLong())
                 }
             }
diff --git a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerShrinkTest.kt b/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerShrinkTest.kt
index ab40311..e68361b 100644
--- a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerShrinkTest.kt
+++ b/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerShrinkTest.kt
@@ -35,7 +35,7 @@
         val blockingTasks = launchBlocking()
         checkBlockingTasks(blockingTasks)
 
-        delay(2, TimeUnit.SECONDS)
+        delay(2000)
         // Pool should shrink to core size +- eps
         checkPoolThreadsExist(CORES_COUNT..CORES_COUNT + 3)
     }
@@ -61,7 +61,7 @@
         // Check blocking tasks succeeded properly
         checkBlockingTasks(blockingTasks)
 
-        delay(2, TimeUnit.SECONDS)
+        delay(2000)
         // Pool should shrink to core size
         checkPoolThreadsExist(CORES_COUNT..CORES_COUNT + 3)
     }
@@ -99,7 +99,7 @@
 
         checkBlockingTasks(blockingTasks)
 
-        delay(2, TimeUnit.SECONDS)
+        delay(2000)
         // Pool should shrink almost to core size (+/- eps)
         checkPoolThreadsExist(CORES_COUNT..CORES_COUNT + 3)
 
diff --git a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt b/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt
index fb2947e..b4164bf 100644
--- a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerStressTest.kt
@@ -36,6 +36,7 @@
     }
 
     @Test
+    @Suppress("DEPRECATION")
     fun testExternalTasksSubmission() {
         stressTest(CommonPool)
     }
diff --git a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerTest.kt b/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerTest.kt
index de99f2c..7b39e69 100644
--- a/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerTest.kt
+++ b/core/kotlinx-coroutines-core/test/scheduling/CoroutineSchedulerTest.kt
@@ -5,8 +5,10 @@
 package kotlinx.coroutines.experimental.scheduling
 
 import kotlinx.coroutines.experimental.TestBase
-import org.junit.Test
-import java.util.concurrent.CountDownLatch
+import org.junit.*
+import java.lang.Runnable
+import java.util.concurrent.*
+import kotlin.coroutines.experimental.*
 
 class CoroutineSchedulerTest : TestBase() {
 
@@ -115,6 +117,16 @@
         ExperimentalCoroutineDispatcher(4, 1)
     }
 
+    @Test
+    fun testSelfClose() {
+        val dispatcher = ExperimentalCoroutineDispatcher(1, 1)
+        val latch = CountDownLatch(1)
+        dispatcher.dispatch(EmptyCoroutineContext, Runnable {
+            dispatcher.close(); latch.countDown()
+        })
+        latch.await()
+    }
+
     private fun testUniformDistribution(worker: CoroutineScheduler.Worker, bound: Int) {
         val result = IntArray(bound)
         val iterations = 10_000_000
diff --git a/core/kotlinx-coroutines-core/test/scheduling/SchedulerTestBase.kt b/core/kotlinx-coroutines-core/test/scheduling/SchedulerTestBase.kt
index ac403e8..a48590e 100644
--- a/core/kotlinx-coroutines-core/test/scheduling/SchedulerTestBase.kt
+++ b/core/kotlinx-coroutines-core/test/scheduling/SchedulerTestBase.kt
@@ -37,12 +37,12 @@
          * Asserts that any number of pool worker threads in [range] exists at the time of method invocation
          */
         fun checkPoolThreadsExist(range: IntRange) {
-            val threads = Thread.getAllStackTraces().keys.filter { it is CoroutineScheduler.Worker }.count()
+            val threads = Thread.getAllStackTraces().keys.asSequence().filter { it is CoroutineScheduler.Worker }.count()
             require(threads in range) { "Expected threads in $range interval, but has $threads" }
         }
 
         private fun maxSequenceNumber(): Int? {
-            return Thread.getAllStackTraces().keys.filter { it is CoroutineScheduler.Worker }
+            return Thread.getAllStackTraces().keys.asSequence().filter { it is CoroutineScheduler.Worker }
                 .map { sequenceNumber(it.name) }.max()
         }
 
@@ -94,8 +94,6 @@
         return _dispatcher!!.limited(parallelism) + handler
     }
 
-    fun initialPoolSize() = corePoolSize.coerceAtMost(2)
-
     @After
     fun after() {
         runBlocking {
diff --git a/core/kotlinx-coroutines-core/test/selects/SelectChannelStressTest.kt b/core/kotlinx-coroutines-core/test/selects/SelectChannelStressTest.kt
index a83b1c4..e842256 100644
--- a/core/kotlinx-coroutines-core/test/selects/SelectChannelStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/selects/SelectChannelStressTest.kt
@@ -13,7 +13,7 @@
 
     @Test
     fun testSelectSendResourceCleanupArrayChannel() = runTest {
-        val channel = ArrayChannel<Int>(1)
+        val channel = Channel<Int>(1)
         val n = 10_000_000 * stressTestMultiplier
         expect(1)
         channel.send(-1) // fill the buffer, so all subsequent sends cannot proceed
@@ -28,7 +28,7 @@
 
     @Test
     fun testSelectReceiveResourceCleanupArrayChannel() = runTest {
-        val channel = ArrayChannel<Int>(1)
+        val channel = Channel<Int>(1)
         val n = 10_000_000 * stressTestMultiplier
         expect(1)
         repeat(n) { i ->
@@ -42,7 +42,7 @@
 
     @Test
     fun testSelectSendResourceCleanupRendezvousChannel() = runTest {
-        val channel = RendezvousChannel<Int>()
+        val channel = Channel<Int>(Channel.RENDEZVOUS)
         val n = 1_000_000 * stressTestMultiplier
         expect(1)
         repeat(n) { i ->
@@ -56,7 +56,7 @@
 
     @Test
     fun testSelectReceiveResourceRendezvousChannel() = runTest {
-        val channel = RendezvousChannel<Int>()
+        val channel = Channel<Int>(Channel.RENDEZVOUS)
         val n = 1_000_000 * stressTestMultiplier
         expect(1)
         repeat(n) { i ->
diff --git a/core/kotlinx-coroutines-core/test/selects/SelectPhilosophersStressTest.kt b/core/kotlinx-coroutines-core/test/selects/SelectPhilosophersStressTest.kt
index f49da71..7559406 100644
--- a/core/kotlinx-coroutines-core/test/selects/SelectPhilosophersStressTest.kt
+++ b/core/kotlinx-coroutines-core/test/selects/SelectPhilosophersStressTest.kt
@@ -10,12 +10,12 @@
 import org.junit.Assert.*
 
 class SelectPhilosophersStressTest : TestBase() {
-    val TEST_DURATION = 3000L * stressTestMultiplier
+    private val TEST_DURATION = 3000L * stressTestMultiplier
 
     val n = 10 // number of philosophers
-    val forks = Array<Mutex>(n) { Mutex() }
+    private val forks = Array(n) { Mutex() }
 
-    suspend fun eat(id: Int, desc: String) {
+    private suspend fun eat(id: Int, desc: String) {
         val left = forks[id]
         val right = forks[(id + 1) % n]
         while (true) {
diff --git a/docs/basics.md b/docs/basics.md
index 30c4fdf..443a31f 100644
--- a/docs/basics.md
+++ b/docs/basics.md
@@ -115,7 +115,7 @@
 the execution of the main function:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> { // start main coroutine
+fun main(args: Array<String>) = runBlocking { // start main coroutine
     GlobalScope.launch { // launch new coroutine in background and continue
         delay(1000L)
         println("World!")
@@ -154,7 +154,7 @@
 wait (in a non-blocking way) until the background [Job] that we have launched is complete:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val job = GlobalScope.launch { // launch new coroutine and keep a reference to its Job
         delay(1000L)
         println("World!")
@@ -194,7 +194,7 @@
 in its scope complete. Thus, we can make our example simpler:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> { // this: CoroutineScope
+fun main(args: Array<String>) = runBlocking { // this: CoroutineScope
     launch { // launch new coroutine in the scope of runBlocking
         delay(1000L)
         println("World!")
@@ -217,7 +217,7 @@
 while waiting for all children to complete.
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> { // this: CoroutineScope
+fun main(args: Array<String>) = runBlocking { // this: CoroutineScope
     launch { 
         delay(200L)
         println("Task from runBlocking")
@@ -255,7 +255,7 @@
 use other suspending functions, like `delay` in this example, to _suspend_ execution of a coroutine.
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     launch { doWorld() }
     println("Hello,")
 }
@@ -281,7 +281,7 @@
 [currentScope] builder comes to help: it inherits current [CoroutineScope] from the coroutine context it is invoked.
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     launchDoWorld()
     println("Hello,")
 }
@@ -306,7 +306,7 @@
 Run the following code:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     repeat(100_000) { // launch a lot of coroutines
         launch {
             delay(1000L)
@@ -329,7 +329,7 @@
 returns from the main function after some delay:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     GlobalScope.launch {
         repeat(1000) { i ->
             println("I'm sleeping $i ...")
diff --git a/docs/cancellation-and-timeouts.md b/docs/cancellation-and-timeouts.md
index 9522ca3..a026fd4 100644
--- a/docs/cancellation-and-timeouts.md
+++ b/docs/cancellation-and-timeouts.md
@@ -43,7 +43,7 @@
 The [launch] function returns a [Job] that can be used to cancel running coroutine:
  
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val job = launch {
         repeat(1000) { i ->
             println("I'm sleeping $i ...")
@@ -85,7 +85,7 @@
 example shows:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val startTime = System.currentTimeMillis()
     val job = launch(Dispatchers.Default) {
         var nextPrintTime = startTime
@@ -129,7 +129,7 @@
 Replace `while (i < 5)` in the previous example with `while (isActive)` and rerun it. 
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val startTime = System.currentTimeMillis()
     val job = launch(Dispatchers.Default) {
         var nextPrintTime = startTime
@@ -169,7 +169,7 @@
 finalization actions normally when coroutine is cancelled:
  
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val job = launch {
         try {
             repeat(1000) { i ->
@@ -213,7 +213,7 @@
 `withContext(NonCancellable) {...}` using [withContext] function and [NonCancellable] context as the following example shows:
  
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val job = launch {
         try {
             repeat(1000) { i ->
@@ -256,7 +256,7 @@
 Look at the following example:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     withTimeout(1300L) {
         repeat(1000) { i ->
             println("I'm sleeping $i ...")
@@ -274,7 +274,7 @@
 I'm sleeping 0 ...
 I'm sleeping 1 ...
 I'm sleeping 2 ...
-Exception in thread "main" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 MILLISECONDS
+Exception in thread "main" kotlinx.coroutines.experimental.TimeoutCancellationException: Timed out waiting for 1300 ms
 ```
 
 <!--- TEST STARTS_WITH -->
@@ -290,7 +290,7 @@
 that is similar to [withTimeout], but returns `null` on timeout instead of throwing an exception:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val result = withTimeoutOrNull(1300L) {
         repeat(1000) { i ->
             println("I'm sleeping $i ...")
@@ -327,7 +327,7 @@
 [isActive]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/is-active.html
 [CoroutineScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-scope/index.html
 [withContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-context.html
-[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
+[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable.html
 [withTimeout]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout.html
 [withTimeoutOrNull]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/with-timeout-or-null.html
 <!--- END -->
diff --git a/docs/channels.md b/docs/channels.md
index 70a4614..adf89ed 100644
--- a/docs/channels.md
+++ b/docs/channels.md
@@ -56,7 +56,7 @@
 a blocking `take` operation it has a suspending [receive][ReceiveChannel.receive].
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val channel = Channel<Int>()
     launch {
         // this might be heavy CPU-consuming computation or async logic, we'll just send five squares
@@ -94,7 +94,7 @@
 that all previously sent elements before the close are received:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val channel = Channel<Int>()
     launch {
         for (x in 1..5) channel.send(x * x)
@@ -128,11 +128,11 @@
 and an extension function [consumeEach], that replaces a `for` loop on the consumer side:
 
 ```kotlin
-fun CoroutineScope.produceSquares() = produce<Int> {
+fun CoroutineScope.produceSquares(): ReceiveChannel<Int> = produce {
     for (x in 1..5) send(x * x)
 }
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val squares = produceSquares()
     squares.consumeEach { println(it) }
     println("Done!")
@@ -165,7 +165,7 @@
 In the below example the numbers are just squared:
 
 ```kotlin
-fun CoroutineScope.square(numbers: ReceiveChannel<Int>) = produce<Int> {
+fun CoroutineScope.square(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce {
     for (x in numbers) send(x * x)
 }
 ```
@@ -173,7 +173,7 @@
 The main code starts and connects the whole pipeline:
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val numbers = produceNumbers() // produces integers from 1 and on
     val squares = square(numbers) // squares integers
     for (i in 1..5) println(squares.receive()) // print first five
@@ -238,7 +238,7 @@
 the first ten prime numbers. 
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     var cur = numbersFrom(2)
     for (i in 1..10) {
         val prime = cur.receive()
@@ -370,7 +370,7 @@
 (in this example we launch them in the context of the main thread as main coroutine's children):
 
 ```kotlin
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val channel = Channel<String>()
     launch { sendString(channel, "foo", 200L) }
     launch { sendString(channel, "BAR!", 500L) }
@@ -457,7 +457,7 @@
 ```kotlin
 data class Ball(var hits: Int)
 
-fun main(args: Array<String>) = runBlocking<Unit> {
+fun main(args: Array<String>) = runBlocking {
     val table = Channel<Ball>() // a shared table
     launch { player("ping", table) }
     launch { player("pong", table) }
@@ -508,7 +508,7 @@
 
 ```kotlin
 fun main(args: Array<String>) = runBlocking<Unit> {
-    val tickerChannel = ticker(delay = 100, initialDelay = 0) // create ticker channel
+    val tickerChannel = ticker(delayMillis = 100, initialDelayMillis = 0) // create ticker channel
     var nextElement = withTimeoutOrNull(1) { tickerChannel.receive() }
     println("Initial element is available immediately: $nextElement") // initial delay hasn't passed yet
 
diff --git a/docs/coroutine-context-and-dispatchers.md b/docs/coroutine-context-and-dispatchers.md
index e9247cf..b900db5 100644
--- a/docs/coroutine-context-and-dispatchers.md
+++ b/docs/coroutine-context-and-dispatchers.md
@@ -105,7 +105,7 @@
   
 [newSingleThreadContext] creates a new thread for the coroutine to run. 
 A dedicated thread is a very expensive resource. 
-In a real application it must be either released, when no longer needed, using [close][ThreadPoolDispatcher.close] 
+In a real application it must be either released, when no longer needed, using [close][ExecutorCoroutineDispatcher.close] 
 function, or stored in a top-level variable and reused throughout the application.  
 
 ### Unconfined vs confined dispatcher
@@ -608,7 +608,7 @@
 [GlobalScope]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-global-scope/index.html
 [Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-dispatchers/-default.html
 [newSingleThreadContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-single-thread-context.html
-[ThreadPoolDispatcher.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-thread-pool-dispatcher/close.html
+[ExecutorCoroutineDispatcher.close]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-executor-coroutine-dispatcher/close.html
 [runBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/run-blocking.html
 [delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
 [newCoroutineContext]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/new-coroutine-context.html
diff --git a/docs/exception-handling.md b/docs/exception-handling.md
index 9d024ac..e754bc3 100644
--- a/docs/exception-handling.md
+++ b/docs/exception-handling.md
@@ -300,8 +300,8 @@
         }
         try {
             inner.join()
-        } catch (e: JobCancellationException) {
-            println("Rethrowing JobCancellationException with original cause")
+        } catch (e: CancellationException) {
+            println("Rethrowing CancellationException with original cause")
             throw e
         }
     }
@@ -314,7 +314,7 @@
 The output of this code is:
 
 ```text
-Rethrowing JobCancellationException with original cause
+Rethrowing CancellationException with original cause
 Caught original java.io.IOException
 ```
 <!--- TEST-->
diff --git a/integration/README.md b/integration/README.md
index 099a17e..8a01b78 100644
--- a/integration/README.md
+++ b/integration/README.md
@@ -6,10 +6,9 @@
 ## Modules
 
 * [kotlinx-coroutines-jdk8](kotlinx-coroutines-jdk8/README.md) -- integration with JDK8 `CompletableFuture` (Android API level 24).
-* [kotlinx-coroutines-nio](kotlinx-coroutines-nio/README.md) -- integration with asynchronous IO on JDK7+ (Android O Preview).
 * [kotlinx-coroutines-guava](kotlinx-coroutines-guava/README.md) -- integration with Guava [ListenableFuture](https://github.com/google/guava/wiki/ListenableFutureExplained).
-* [kotlinx-coroutines-quasar](kotlinx-coroutines-quasar/README.md) -- integration with [Quasar](http://docs.paralleluniverse.co/quasar/).
 * [kotlinx-coroutines-slf4j](kotlinx-coroutines-slf4j/README.md) -- integration with SLF4J [MDC](https://logback.qos.ch/manual/mdc.html).
+* [kotlinx-coroutines-play-services](kotlinx-coroutines-play-services) -- integration with Google Play Services [Tasks API](https://developers.google.com/android/guides/tasks). |
 
 ## Contributing
 
diff --git a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt b/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt
index bb77ad0..2a7f6a2 100644
--- a/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt
+++ b/integration/kotlinx-coroutines-guava/src/ListenableFuture.kt
@@ -28,12 +28,29 @@
  *
  * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
- * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
 public fun <T> CoroutineScope.future(
     context: CoroutineContext = EmptyCoroutineContext,
     start: CoroutineStart = CoroutineStart.DEFAULT,
+    block: suspend CoroutineScope.() -> T
+): ListenableFuture<T> {
+    require(!start.isLazy) { "$start start is not supported" }
+    val newContext = newCoroutineContext(context)
+    val job = Job(newContext[Job])
+    val future = ListenableFutureCoroutine<T>(newContext + job)
+    job.cancelFutureOnCompletion(future)
+    start(block, receiver=future, completion=future) // use the specified start strategy
+    return future
+}
+
+/**
+ * @suppress **Deprecated**: onCompletion parameter is deprecated.
+ */
+@Deprecated("onCompletion parameter is deprecated")
+public fun <T> CoroutineScope.future(
+    context: CoroutineContext = EmptyCoroutineContext,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
     onCompletion: CompletionHandler? = null,
     block: suspend CoroutineScope.() -> T
 ): ListenableFuture<T> {
diff --git a/integration/kotlinx-coroutines-jdk8/src/channels8/Channels.kt b/integration/kotlinx-coroutines-jdk8/src/channels8/Channels.kt
index c199328..96390bd 100644
--- a/integration/kotlinx-coroutines-jdk8/src/channels8/Channels.kt
+++ b/integration/kotlinx-coroutines-jdk8/src/channels8/Channels.kt
@@ -17,6 +17,7 @@
 /**
  * Creates a [ProducerJob] to read all element of the [Stream].
  */
+@Deprecated("No replacement")
 public fun <E> Stream<E>.asReceiveChannel(context: CoroutineContext = EmptyCoroutineContext): ReceiveChannel<E> =
     GlobalScope.produce(context) {
         for (element in this@asReceiveChannel)
@@ -26,6 +27,7 @@
 /**
  * Creates a [Stream] of elements in this [ReceiveChannel].
  */
+@Deprecated(message = "Use toList().stream()", replaceWith = ReplaceWith("toList().stream()"))
 public fun <E : Any> ReceiveChannel<E>.asStream(): Stream<E> = StreamSupport.stream<E>(SpliteratorAdapter(this), false)
 
 /**
diff --git a/integration/kotlinx-coroutines-jdk8/src/future/Future.kt b/integration/kotlinx-coroutines-jdk8/src/future/Future.kt
index 8ec3ad0..b494563 100644
--- a/integration/kotlinx-coroutines-jdk8/src/future/Future.kt
+++ b/integration/kotlinx-coroutines-jdk8/src/future/Future.kt
@@ -28,15 +28,33 @@
  *
  * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
- * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
 public fun <T> CoroutineScope.future(
+    context: CoroutineContext = EmptyCoroutineContext,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
+    block: suspend CoroutineScope.() -> T
+) : CompletableFuture<T> {
+    require(!start.isLazy) { "$start start is not supported" }
+    val newContext = this.newCoroutineContext(context)
+    val job = Job(newContext[Job])
+    val future = CompletableFutureCoroutine<T>(newContext + job)
+    job.cancelFutureOnCompletion(future)
+    future.whenComplete { _, exception -> job.cancel(exception) }
+    start(block, receiver = future, completion = future) // use the specified start strategy
+    return future
+}
+
+/**
+ * @suppress **Deprecated**: onCompletion parameter is deprecated.
+ */
+@Deprecated("onCompletion parameter is deprecated")
+public fun <T> CoroutineScope.future(
     context: CoroutineContext = Dispatchers.Default,
     start: CoroutineStart = CoroutineStart.DEFAULT,
     onCompletion: CompletionHandler? = null,
     block: suspend CoroutineScope.() -> T
-): CompletableFuture<T> {
+) : CompletableFuture<T> {
     require(!start.isLazy) { "$start start is not supported" }
     val newContext = this.newCoroutineContext(context)
     val job = Job(newContext[Job])
diff --git a/integration/kotlinx-coroutines-jdk8/src/time/Time.kt b/integration/kotlinx-coroutines-jdk8/src/time/Time.kt
index de30e5a..2f05a68 100644
--- a/integration/kotlinx-coroutines-jdk8/src/time/Time.kt
+++ b/integration/kotlinx-coroutines-jdk8/src/time/Time.kt
@@ -12,36 +12,44 @@
  * "java.time" adapter method for [kotlinx.coroutines.experimental.delay]
  */
 public suspend fun delay(duration: Duration) =
-        kotlinx.coroutines.experimental.delay(duration.toNanos(), TimeUnit.NANOSECONDS)
+    kotlinx.coroutines.experimental.delay(duration.toMillis())
 
 /**
  * "java.time" adapter method for [SelectBuilder.onTimeout]
  */
-public suspend fun <R> SelectBuilder<R>.onTimeout(duration: Duration, block: suspend () -> R) =
-        onTimeout(duration.toNanos(), TimeUnit.NANOSECONDS, block)
+public fun <R> SelectBuilder<R>.onTimeout(duration: Duration, block: suspend () -> R) =
+    onTimeout(duration.toMillis(), block)
+
+/**
+ * @suppress
+ */
+@Deprecated(level = DeprecationLevel.HIDDEN, message = "binary")
+@JvmName("onTimeout")
+public suspend fun <R> SelectBuilder<R>.onTimeout0(duration: Duration, block: suspend () -> R) =
+    onTimeout(duration.toMillis(), block)
 
 /**
  * "java.time" adapter method for [kotlinx.coroutines.experimental.withTimeout]
  */
 public suspend fun <T> withTimeout(duration: Duration, block: suspend CoroutineScope.() -> T): T =
-        kotlinx.coroutines.experimental.withTimeout(duration.toNanos(), TimeUnit.NANOSECONDS, block)
+    kotlinx.coroutines.experimental.withTimeout(duration.toMillis(), block)
 
 /**
  * @suppress **Deprecated**: for binary compatibility only
  */
 @Deprecated("for binary compatibility only", level=DeprecationLevel.HIDDEN)
 public suspend fun <T> withTimeout(duration: Duration, block: suspend () -> T): T =
-        kotlinx.coroutines.experimental.withTimeout(duration.toNanos(), TimeUnit.NANOSECONDS) { block() }
+    kotlinx.coroutines.experimental.withTimeout(duration.toNanos(), TimeUnit.NANOSECONDS) { block() }
 
 /**
  * "java.time" adapter method for [kotlinx.coroutines.experimental.withTimeoutOrNull]
  */
 public suspend fun <T> withTimeoutOrNull(duration: Duration, block: suspend CoroutineScope.() -> T): T? =
-        kotlinx.coroutines.experimental.withTimeoutOrNull(duration.toNanos(), TimeUnit.NANOSECONDS, block)
+    kotlinx.coroutines.experimental.withTimeoutOrNull(duration.toMillis(), block)
 
 /**
  * @suppress **Deprecated**: for binary compatibility only
  */
 @Deprecated("for binary compatibility only", level=DeprecationLevel.HIDDEN)
 public suspend fun <T> withTimeoutOrNull(duration: Duration, block: suspend () -> T): T? =
-        kotlinx.coroutines.experimental.withTimeoutOrNull(duration.toNanos(), TimeUnit.NANOSECONDS) { block() }
+    kotlinx.coroutines.experimental.withTimeoutOrNull(duration.toNanos(), TimeUnit.NANOSECONDS) { block() }
diff --git a/integration/kotlinx-coroutines-jdk8/test/channels8/ChannelsTest.kt b/integration/kotlinx-coroutines-jdk8/test/channels8/ChannelsTest.kt
index 005bb16..6b52a16 100644
--- a/integration/kotlinx-coroutines-jdk8/test/channels8/ChannelsTest.kt
+++ b/integration/kotlinx-coroutines-jdk8/test/channels8/ChannelsTest.kt
@@ -27,6 +27,7 @@
 
     @Test
     fun testReceiveChannelAsStream() {
-        assertEquals(testList, testList.asReceiveChannel().asStream().collect(Collectors.toList()))
+        testList.asReceiveChannel()
+        assertEquals(testList, testList.toList().stream().collect(Collectors.toList()))
     }
 }
diff --git a/integration/kotlinx-coroutines-jdk8/test/examples/ToFuture-example.kt b/integration/kotlinx-coroutines-jdk8/test/examples/ToFuture-example.kt
index abf5fe1..d2b2178 100644
--- a/integration/kotlinx-coroutines-jdk8/test/examples/ToFuture-example.kt
+++ b/integration/kotlinx-coroutines-jdk8/test/examples/ToFuture-example.kt
@@ -12,7 +12,7 @@
     log("Started")
     val deferred = GlobalScope.async {
         log("Busy...")
-        delay(1, TimeUnit.SECONDS)
+        delay(1000)
         log("Done...")
         42
     }
diff --git a/integration/kotlinx-coroutines-jdk8/test/examples/simple-example-2.kt b/integration/kotlinx-coroutines-jdk8/test/examples/simple-example-2.kt
index 9de9798..0c0a660 100644
--- a/integration/kotlinx-coroutines-jdk8/test/examples/simple-example-2.kt
+++ b/integration/kotlinx-coroutines-jdk8/test/examples/simple-example-2.kt
@@ -11,7 +11,7 @@
 // this function returns a CompletableFuture using Kotlin coroutines
 fun supplyTheAnswerAsync(): CompletableFuture<Int> = GlobalScope.future {
     println("We might be doing some asynchronous IO here or something else...")
-    delay(1, TimeUnit.SECONDS) // just do a non-blocking delay
+    delay(1000) // just do a non-blocking delay
     42 // The answer!
 }
 
diff --git a/integration/kotlinx-coroutines-nio/README.md b/integration/kotlinx-coroutines-nio/README.md
deleted file mode 100644
index 5141863..0000000
--- a/integration/kotlinx-coroutines-nio/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Module kotlinx-coroutines-nio
-
-Integration with asynchronous IO on JDK7+ (Android API level 26).
-
-# Package kotlinx.coroutines.experimental.nio
-
-Integration with asynchronous IO on JDK7+ (Android API level 26).
-
-* `AsynchronousFileChannel` extensions `aLock`, `aRead`, and `aWrite`.
-* `AsynchronousServerSocketChannel` extension `aAccept`.
-* `AsynchronousSocketChannel` extensions `aConnect`, `aRead`, and `aWrite`.
diff --git a/integration/kotlinx-coroutines-nio/build.gradle b/integration/kotlinx-coroutines-nio/build.gradle
deleted file mode 100644
index afcdc2b..0000000
--- a/integration/kotlinx-coroutines-nio/build.gradle
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-dependencies {
-    testCompile 'org.apache.commons:commons-io:1.3.2'
-}
\ No newline at end of file
diff --git a/integration/kotlinx-coroutines-nio/src/Nio.kt b/integration/kotlinx-coroutines-nio/src/Nio.kt
deleted file mode 100644
index 1175a14..0000000
--- a/integration/kotlinx-coroutines-nio/src/Nio.kt
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.experimental.nio
-
-import kotlinx.coroutines.experimental.CancellableContinuation
-import kotlinx.coroutines.experimental.CancellationException
-import kotlinx.coroutines.experimental.Job
-import kotlinx.coroutines.experimental.suspendCancellableCoroutine
-import java.net.SocketAddress
-import java.nio.ByteBuffer
-import java.nio.channels.*
-import java.util.concurrent.TimeUnit
-
-/**
- * Performs [AsynchronousFileChannel.lock] without blocking a thread and resumes when asynchronous operation completes.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * *closes the underlying channel* and immediately resumes with [CancellationException].
- */
-suspend fun AsynchronousFileChannel.aLock() = suspendCancellableCoroutine<FileLock> { cont ->
-    lock(cont, asyncIOHandler())
-    closeOnCancel(cont)
-}
-
-/**
- * Performs [AsynchronousFileChannel.lock] without blocking a thread and resumes when asynchronous operation completes.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * *closes the underlying channel* and immediately resumes with [CancellationException].
- */
-suspend fun AsynchronousFileChannel.aLock(
-    position: Long,
-    size: Long,
-    shared: Boolean
-) = suspendCancellableCoroutine<FileLock> { cont ->
-    lock(position, size, shared, cont, asyncIOHandler())
-    closeOnCancel(cont)
-}
-
-/**
- * Performs [AsynchronousFileChannel.read] without blocking a thread and resumes when asynchronous operation completes.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * *closes the underlying channel* and immediately resumes with [CancellationException].
- */
-suspend fun AsynchronousFileChannel.aRead(
-    buf: ByteBuffer,
-    position: Long
-) = suspendCancellableCoroutine<Int> { cont ->
-    read(buf, position, cont, asyncIOHandler())
-    closeOnCancel(cont)
-}
-
-/**
- * Performs [AsynchronousFileChannel.write] without blocking a thread and resumes when asynchronous operation completes.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * *closes the underlying channel* and immediately resumes with [CancellationException].
- */
-suspend fun AsynchronousFileChannel.aWrite(
-    buf: ByteBuffer,
-    position: Long
-) = suspendCancellableCoroutine<Int> { cont ->
-    write(buf, position, cont, asyncIOHandler())
-    closeOnCancel(cont)
-}
-
-/**
- * Performs [AsynchronousServerSocketChannel.accept] without blocking a thread and resumes when asynchronous operation completes.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * *closes the underlying channel* and immediately resumes with [CancellationException].
- */
-suspend fun AsynchronousServerSocketChannel.aAccept() = suspendCancellableCoroutine<AsynchronousSocketChannel> { cont ->
-    accept(cont, asyncIOHandler())
-    closeOnCancel(cont)
-}
-
-/**
- * Performs [AsynchronousSocketChannel.connect] without blocking a thread and resumes when asynchronous operation completes.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * *closes the underlying channel* and immediately resumes with [CancellationException].
- */
-suspend fun AsynchronousSocketChannel.aConnect(
-    socketAddress: SocketAddress
-) = suspendCancellableCoroutine<Unit> { cont ->
-    connect(socketAddress, cont, AsyncVoidIOHandler)
-    closeOnCancel(cont)
-}
-
-/**
- * Performs [AsynchronousSocketChannel.read] without blocking a thread and resumes when asynchronous operation completes.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * *closes the underlying channel* and immediately resumes with [CancellationException].
- */
-suspend fun AsynchronousSocketChannel.aRead(
-    buf: ByteBuffer,
-    timeout: Long = 0L,
-    timeUnit: TimeUnit = TimeUnit.MILLISECONDS
-) = suspendCancellableCoroutine<Int> { cont ->
-    read(buf, timeout, timeUnit, cont, asyncIOHandler())
-    closeOnCancel(cont)
-}
-
-/**
- * Performs [AsynchronousSocketChannel.write] without blocking a thread and resumes when asynchronous operation completes.
- * This suspending function is cancellable.
- * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
- * *closes the underlying channel* and immediately resumes with [CancellationException].
- */
-suspend fun AsynchronousSocketChannel.aWrite(
-    buf: ByteBuffer,
-    timeout: Long = 0L,
-    timeUnit: TimeUnit = TimeUnit.MILLISECONDS
-) = suspendCancellableCoroutine<Int> { cont ->
-    write(buf, timeout, timeUnit, cont, asyncIOHandler())
-    closeOnCancel(cont)
-}
-
-// ---------------- private details ----------------
-
-private fun Channel.closeOnCancel(cont: CancellableContinuation<*>) {
-    cont.invokeOnCancellation {
-        try {
-            close()
-        } catch (ex: Throwable) {
-            // Specification says that it is Ok to call it any time, but reality is different,
-            // so we have just to ignore exception
-        }
-    }
-}
-
-@Suppress("UNCHECKED_CAST")
-private fun <T> asyncIOHandler(): CompletionHandler<T, CancellableContinuation<T>> =
-    AsyncIOHandlerAny as CompletionHandler<T, CancellableContinuation<T>>
-
-private object AsyncIOHandlerAny : CompletionHandler<Any, CancellableContinuation<Any>> {
-    override fun completed(result: Any, cont: CancellableContinuation<Any>) {
-        cont.resume(result)
-    }
-
-    override fun failed(ex: Throwable, cont: CancellableContinuation<Any>) {
-        // just return if already cancelled and got an expected exception for that case
-        if (ex is AsynchronousCloseException && cont.isCancelled) return
-        cont.resumeWithException(ex)
-    }
-}
-
-private object AsyncVoidIOHandler : CompletionHandler<Void?, CancellableContinuation<Unit>> {
-    override fun completed(result: Void?, cont: CancellableContinuation<Unit>) {
-        cont.resume(Unit)
-    }
-
-    override fun failed(ex: Throwable, cont: CancellableContinuation<Unit>) {
-        // just return if already cancelled and got an expected exception for that case
-        if (ex is AsynchronousCloseException && cont.isCancelled) return
-        cont.resumeWithException(ex)
-    }
-}
-
-
diff --git a/integration/kotlinx-coroutines-nio/test/AsyncIOTest.kt b/integration/kotlinx-coroutines-nio/test/AsyncIOTest.kt
deleted file mode 100644
index a57385d..0000000
--- a/integration/kotlinx-coroutines-nio/test/AsyncIOTest.kt
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.experimental.nio
-
-import kotlinx.coroutines.experimental.*
-import org.apache.commons.io.*
-import org.junit.*
-import org.junit.Assert.*
-import org.junit.rules.*
-import java.net.*
-import java.nio.*
-import java.nio.channels.*
-import java.nio.file.*
-
-class AsyncIOTest {
-    @Rule
-    @JvmField
-    val tmpDir = TemporaryFolder()
-
-    @Test
-    fun testFileChannels() {
-        val inputFile = tmpDir.newFile()
-        val outputFile = tmpDir.newFile()
-
-        FileUtils.writeStringToFile(
-                inputFile,
-                (1..100000).map(Int::toString).joinToString(""))
-
-        val input = AsynchronousFileChannel.open(inputFile.toPath())
-        val output =
-                AsynchronousFileChannel.open(
-                        outputFile.toPath(),
-                    StandardOpenOption.CREATE, StandardOpenOption.WRITE)
-        val buf = ByteBuffer.allocate(1024)
-
-        runBlocking {
-            var totalBytesRead = 0L
-            var totalBytesWritten = 0L
-            while (totalBytesRead < input.size()) {
-                while (buf.hasRemaining() && totalBytesRead < input.size()) {
-                    // async read
-                    totalBytesRead += input.aRead(buf, totalBytesRead)
-                }
-
-                buf.flip()
-
-                while (buf.hasRemaining()) {
-                    // async write
-                    totalBytesWritten += output.aWrite(buf, totalBytesWritten)
-                }
-
-                buf.clear()
-            }
-        }
-
-        assertTrue(FileUtils.contentEquals(inputFile, outputFile))
-    }
-
-    @Test
-    fun testNetworkChannels() = runBlocking {
-        val serverChannel =
-                AsynchronousServerSocketChannel
-                        .open()
-                        .bind(InetSocketAddress(0))
-
-        val serverPort = (serverChannel.localAddress as InetSocketAddress).port
-
-        val c1 = launch {
-            val client = serverChannel.aAccept()
-            val buffer = ByteBuffer.allocate(2)
-            client.aRead(buffer)
-            buffer.flip()
-            assertEquals("OK", Charsets.UTF_8.decode(buffer).toString())
-
-            client.aWrite(Charsets.UTF_8.encode("123"))
-            client.close()
-        }
-
-        val c2 = launch {
-            val connection =
-                    AsynchronousSocketChannel.open()
-            // async calls
-            connection.aConnect(InetSocketAddress("127.0.0.1", serverPort))
-            connection.aWrite(Charsets.UTF_8.encode("OK"))
-
-            val buffer = ByteBuffer.allocate(3)
-
-            // async call
-            connection.aRead(buffer)
-            buffer.flip()
-            assertEquals("123", Charsets.UTF_8.decode(buffer).toString())
-        }
-
-        c1.join()
-        c2.join()
-    }
-}
diff --git a/integration/kotlinx-coroutines-nio/test/examples/echo-example.kt b/integration/kotlinx-coroutines-nio/test/examples/echo-example.kt
deleted file mode 100644
index 723fdc5..0000000
--- a/integration/kotlinx-coroutines-nio/test/examples/echo-example.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.experimental.examples
-
-import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.nio.*
-import java.net.*
-import java.nio.*
-import java.nio.channels.*
-
-val PORT = 12345
-val CLIENT_READ_TIMEOUT = 5000L // 5 sec
-val CLIENT_WRITE_TIMEOUT = 1000L // 1 sec
-val BUFFER_SIZE = 1024
-
-fun main(args: Array<String>) = runBlocking {
-    val serverChannel =
-        AsynchronousServerSocketChannel
-            .open()
-            .bind(InetSocketAddress(PORT))
-    log("Listening on port $PORT")
-    // loop and accept connections forever
-    while (true) {
-        val client = serverChannel.aAccept()
-        val address = try {
-            val ia = client.remoteAddress as InetSocketAddress
-            "${ia.address.hostAddress}:${ia.port}"
-        } catch (ex: Throwable) {
-            log("Accepted client connection but failed to get its address because of $ex")
-            continue /* accept next connection */
-        }
-        log("Accepted client connection from $address")
-        // just start a new coroutine for each client connection
-        launch {
-            try {
-                handleClient(client)
-                log("Client connection from $address has terminated normally")
-            } catch (ex: Throwable) {
-                log("Client connection from $address has terminated because of $ex")
-            }
-        }
-    }
-}
-
-suspend fun handleClient(client: AsynchronousSocketChannel) {
-    val buffer = ByteBuffer.allocate(BUFFER_SIZE)
-    while (true) {
-        val bytes = withTimeout(CLIENT_READ_TIMEOUT) { client.aRead(buffer) }
-        if (bytes < 0) break
-        buffer.flip()
-        withTimeout(CLIENT_WRITE_TIMEOUT) { client.aWrite(buffer) }
-        buffer.clear()
-    }
-}
-
diff --git a/integration/kotlinx-coroutines-nio/test/examples/log.kt b/integration/kotlinx-coroutines-nio/test/examples/log.kt
deleted file mode 100644
index 59c1ccb..0000000
--- a/integration/kotlinx-coroutines-nio/test/examples/log.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.experimental.examples
-
-import java.text.SimpleDateFormat
-import java.util.*
-
-fun log(msg: String) = println("${SimpleDateFormat("yyyyMMdd-HHmmss.sss").format(Date())} [${Thread.currentThread().name}] $msg")
\ No newline at end of file
diff --git a/integration/kotlinx-coroutines-play-services/README.md b/integration/kotlinx-coroutines-play-services/README.md
new file mode 100644
index 0000000..7f9a5bb
--- /dev/null
+++ b/integration/kotlinx-coroutines-play-services/README.md
@@ -0,0 +1,29 @@
+# Module kotlinx-coroutines-play-services
+
+Integration with Google Play Services [Tasks API](https://developers.google.com/android/guides/tasks).
+
+Extension functions:
+
+| **Name** | **Description**
+| -------- | ---------------
+| [Task.await][await] | Awaits for completion of the Task (cancellable)
+| [Deferred.asTask][asTask] | Converts a deferred value to a Task
+
+## Example
+
+Using Firebase APIs becomes simple:
+
+```kotlin
+FirebaseAuth.getInstance().signInAnonymously().await()
+val snapshot = try {
+    FirebaseFirestore.getInstance().document("users/$id").get().await() // Cancellable await
+} catch (e: FirebaseFirestoreException) {
+    // Handle exception
+    return@async
+}
+
+// Do stuff
+```
+
+[await]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-play-services/kotlinx.coroutines.experimental.tasks/com.google.android.gms.tasks.-task/await.html
+[asTask]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-play-services/kotlinx.coroutines.experimental.tasks/kotlinx.coroutines.experimental.-deferred/as-task.html
diff --git a/integration/kotlinx-coroutines-play-services/build.gradle b/integration/kotlinx-coroutines-play-services/build.gradle
new file mode 100644
index 0000000..4350b3d
--- /dev/null
+++ b/integration/kotlinx-coroutines-play-services/build.gradle
@@ -0,0 +1,82 @@
+import java.nio.file.Files
+import java.nio.file.NoSuchFileException
+import java.util.zip.ZipEntry
+import java.util.zip.ZipFile
+
+/*
+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+ext.tasks_version = '15.0.1'
+
+repositories {
+    google()
+}
+
+def attr = Attribute.of("artifactType", String.class)
+configurations {
+    aar {
+        attributes { attribute(attr, ArtifactTypeDefinition.JAR_TYPE) }
+        sourceSets.main.compileClasspath += it
+        sourceSets.test.compileClasspath += it
+        sourceSets.test.runtimeClasspath += it
+    }
+}
+
+dependencies {
+    registerTransform {
+        from.attribute(attr, "aar")
+        to.attribute(attr, "jar")
+        artifactTransform(ExtractJars.class)
+    }
+
+    aar("com.google.android.gms:play-services-tasks:$tasks_version") {
+        exclude group: 'com.android.support'
+    }
+}
+
+tasks.withType(dokka.getClass()) {
+    externalDocumentationLink {
+        url = new URL("https://developers.google.com/android/reference/")
+    }
+}
+
+class ExtractJars extends ArtifactTransform {
+    @Override
+    List<File> transform(File input) {
+        unzip(input)
+
+        List<File> jars = new ArrayList<>()
+        outputDirectory.traverse(nameFilter: ~/.*\.jar/) { jars += it }
+
+        return jars
+    }
+
+    private void unzip(File zipFile) {
+        ZipFile zip
+        try {
+            zip = new ZipFile(zipFile)
+            for (entry in zip.entries()) {
+                unzipEntryTo(zip, entry)
+            }
+        } finally {
+            if (zip != null) zip.close()
+        }
+    }
+
+    private void unzipEntryTo(ZipFile zip, ZipEntry entry) {
+        File output = new File(outputDirectory, entry.name)
+        if (entry.isDirectory()) {
+            output.mkdirs()
+        } else {
+            InputStream stream
+            try {
+                stream = zip.getInputStream(entry)
+                Files.copy(stream, output.toPath())
+            } catch (NoSuchFileException ignored) {
+            } finally {
+                if (stream != null) stream.close()
+            }
+        }
+    }
+}
diff --git a/integration/kotlinx-coroutines-play-services/src/Tasks.kt b/integration/kotlinx-coroutines-play-services/src/Tasks.kt
new file mode 100644
index 0000000..c2932b0
--- /dev/null
+++ b/integration/kotlinx-coroutines-play-services/src/Tasks.kt
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+@file:Suppress("RedundantVisibilityModifier")
+
+package kotlinx.coroutines.experimental.tasks
+
+import com.google.android.gms.tasks.CancellationTokenSource
+import com.google.android.gms.tasks.RuntimeExecutionException
+import com.google.android.gms.tasks.Task
+import com.google.android.gms.tasks.TaskCompletionSource
+import kotlinx.coroutines.experimental.CancellationException
+import kotlinx.coroutines.experimental.CompletableDeferred
+import kotlinx.coroutines.experimental.Deferred
+import kotlinx.coroutines.experimental.Job
+import kotlinx.coroutines.experimental.suspendCancellableCoroutine
+
+/**
+ * Converts this deferred to the instance of [Task].
+ * If deferred is cancelled then resulting task will be cancelled as well.
+ */
+public fun <T> Deferred<T>.asTask(): Task<T> {
+    val cancellation = CancellationTokenSource()
+    val source = TaskCompletionSource<T>(cancellation.token)
+
+    invokeOnCompletion callback@{
+        if (isCancelled) {
+            cancellation.cancel()
+            return@callback
+        }
+
+        val t = getCompletionExceptionOrNull()
+        if (t == null) {
+            source.setResult(getCompleted())
+        } else {
+            source.setException(t as? Exception ?: RuntimeExecutionException(t))
+        }
+    }
+
+    return source.task
+}
+
+/**
+ * Converts this task to an instance of [Deferred].
+ * If task is cancelled then resulting deferred will be cancelled as well.
+ */
+public fun <T> Task<T>.asDeferred(): Deferred<T> {
+    if (isComplete) {
+        val e = exception
+        return if (e == null) {
+            CompletableDeferred<T>().apply { if (isCanceled) cancel() else complete(result) }
+        } else {
+            CompletableDeferred<T>().apply { completeExceptionally(e) }
+        }
+    }
+
+    val result = CompletableDeferred<T>()
+    addOnCompleteListener {
+        val e = it.exception
+        if (e == null) {
+            if (isCanceled) result.cancel() else result.complete(it.result)
+        } else {
+            result.completeExceptionally(e)
+        }
+    }
+    return result
+}
+
+/**
+ * Awaits for completion of the task without blocking a thread.
+ *
+ * This suspending function is cancellable.
+ * If the [Job] of the current coroutine is cancelled or completed while this suspending function is waiting, this function
+ * stops waiting for the completion stage and immediately resumes with [CancellationException].
+ */
+public suspend fun <T> Task<T>.await(): T {
+    // fast path
+    if (isComplete) {
+        val e = exception
+        return if (e == null) {
+            if (isCanceled) {
+                throw CancellationException("Task $this was cancelled normally.")
+            } else {
+                result
+            }
+        } else {
+            throw e
+        }
+    }
+
+    return suspendCancellableCoroutine { cont ->
+        addOnCompleteListener {
+            val e = exception
+            if (e == null) {
+                if (isCanceled) cont.cancel() else cont.resume(result)
+            } else {
+                cont.resumeWithException(e)
+            }
+        }
+    }
+}
diff --git a/integration/kotlinx-coroutines-play-services/test/FakeAndroid.kt b/integration/kotlinx-coroutines-play-services/test/FakeAndroid.kt
new file mode 100644
index 0000000..119ef53
--- /dev/null
+++ b/integration/kotlinx-coroutines-play-services/test/FakeAndroid.kt
@@ -0,0 +1,18 @@
+package android.os
+
+import kotlinx.coroutines.experimental.GlobalScope
+import kotlinx.coroutines.experimental.launch
+
+class Handler(val looper: Looper) {
+    fun post(r: Runnable): Boolean {
+        GlobalScope.launch { r.run() }
+        return true
+    }
+}
+
+class Looper {
+    companion object {
+        @JvmStatic
+        fun getMainLooper() = Looper()
+    }
+}
diff --git a/integration/kotlinx-coroutines-play-services/test/TaskTest.kt b/integration/kotlinx-coroutines-play-services/test/TaskTest.kt
new file mode 100644
index 0000000..bef3d74
--- /dev/null
+++ b/integration/kotlinx-coroutines-play-services/test/TaskTest.kt
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.coroutines.experimental.tasks
+
+import com.google.android.gms.tasks.RuntimeExecutionException
+import com.google.android.gms.tasks.Tasks
+import kotlinx.coroutines.experimental.CancellationException
+import kotlinx.coroutines.experimental.CoroutineStart
+import kotlinx.coroutines.experimental.Deferred
+import kotlinx.coroutines.experimental.GlobalScope
+import kotlinx.coroutines.experimental.TestBase
+import kotlinx.coroutines.experimental.async
+import kotlinx.coroutines.experimental.delay
+import kotlinx.coroutines.experimental.ignoreLostThreads
+import kotlinx.coroutines.experimental.runBlocking
+import org.hamcrest.core.IsEqual
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import java.util.concurrent.locks.ReentrantLock
+import kotlin.concurrent.withLock
+
+class TaskTest : TestBase() {
+    @Before
+    fun setup() {
+        ignoreLostThreads("ForkJoinPool.commonPool-worker-")
+    }
+
+    @Test
+    fun `Completed deferred as task`() = runBlocking {
+        expect(1)
+        val deferred = async(coroutineContext, CoroutineStart.UNDISPATCHED) {
+            expect(2) // Completed immediately
+            "OK"
+        }
+        expect(3)
+        val task = deferred.asTask()
+        Assert.assertThat(task.await(), IsEqual("OK"))
+        finish(4)
+    }
+
+    @Test
+    fun `Deferred as task`() = runBlocking {
+        expect(1)
+        val deferred = async(coroutineContext) {
+            expect(3) // Completed later
+            "OK"
+        }
+        expect(2)
+        val task = deferred.asTask()
+        Assert.assertThat(task.await(), IsEqual("OK"))
+        finish(4)
+    }
+
+    @Test
+    fun `Threw cancellation exception as task`() {
+        val deferred = GlobalScope.async {
+            throw CancellationException()
+        }
+
+        val task = deferred.asTask()
+        try {
+            runBlocking { task.await() }
+        } catch (e: Exception) {
+            Assert.assertTrue(e is CancellationException)
+            Assert.assertFalse(task.isSuccessful)
+            Assert.assertFalse(task.isCanceled)
+        }
+    }
+
+    @Test
+    fun `Cancelled as task`() {
+        val deferred = GlobalScope.async {
+            delay(100)
+        }.apply { cancel() }
+
+        val task = deferred.asTask()
+        try {
+            runBlocking { task.await() }
+        } catch (e: Exception) {
+            Assert.assertTrue(e is CancellationException)
+            Assert.assertTrue(task.isCanceled)
+        }
+    }
+
+    @Test
+    fun `Threw as task`() {
+        val deferred = GlobalScope.async {
+            throw OutOfMemoryError()
+        }
+
+        val task = deferred.asTask()
+        try {
+            runBlocking { task.await() }
+        } catch (e: RuntimeExecutionException) {
+            Assert.assertFalse(task.isSuccessful)
+            Assert.assertTrue(e.cause is OutOfMemoryError)
+        }
+    }
+
+    @Test
+    fun `Task stages as task`() = runBlocking {
+        val lock = ReentrantLock().apply { lock() }
+
+        val deferred: Deferred<Int> = Tasks.call {
+            lock.withLock { 42 }
+        }.asDeferred()
+
+        Assert.assertFalse(deferred.isCompleted)
+        lock.unlock()
+
+        Assert.assertEquals(42, deferred.await())
+        Assert.assertTrue(deferred.isCompleted)
+    }
+
+    @Test
+    fun `Task as deferred`() = runBlocking {
+        val deferred = Tasks.forResult(42).asDeferred()
+        Assert.assertEquals(42, deferred.await())
+    }
+
+    @Test
+    fun `Cancelled task as deferred`() = runBlocking {
+        val deferred = Tasks.forCanceled<Int>().asDeferred()
+
+        Assert.assertTrue(deferred.isCancelled)
+        try {
+            deferred.await()
+            Assert.fail("deferred.await() should be cancelled")
+        } catch (e: Exception) {
+            Assert.assertTrue(e is CancellationException)
+        }
+    }
+
+    @Test
+    fun `Failed task as deferred`() = runBlocking {
+        val deferred = Tasks.forException<Int>(TestException("something went wrong")).asDeferred()
+
+        Assert.assertTrue(deferred.isCompletedExceptionally)
+        val completionException = deferred.getCompletionExceptionOrNull()!!
+        Assert.assertTrue(completionException is TestException)
+        Assert.assertEquals("something went wrong", completionException.message)
+
+        try {
+            deferred.await()
+            Assert.fail("deferred.await() should throw an exception")
+        } catch (e: Exception) {
+            Assert.assertTrue(e is TestException)
+            Assert.assertEquals("something went wrong", e.message)
+        }
+    }
+
+    @Test
+    fun `Failed task stages as deferred`() = runBlocking {
+        val lock = ReentrantLock().apply { lock() }
+
+        val deferred: Deferred<Int> = Tasks.call {
+            lock.withLock { throw TestException("something went wrong") }
+        }.asDeferred()
+
+        Assert.assertFalse(deferred.isCompleted)
+        lock.unlock()
+
+        try {
+            deferred.await()
+            Assert.fail("deferred.await() should throw an exception")
+        } catch (e: Exception) {
+            Assert.assertTrue(e is TestException)
+            Assert.assertEquals("something went wrong", e.message)
+            Assert.assertSame(e, deferred.getCompletionExceptionOrNull())
+        }
+    }
+
+    class TestException(message: String) : Exception(message)
+}
diff --git a/integration/kotlinx-coroutines-quasar/README.md b/integration/kotlinx-coroutines-quasar/README.md
deleted file mode 100644
index 99fd973..0000000
--- a/integration/kotlinx-coroutines-quasar/README.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# Module kotlinx-coroutines-quasar
-
-Integration with [Quasar](http://docs.paralleluniverse.co/quasar/).
-It supports invoking Quasar-instrumented suspendable code from within Kotlin
-coroutines via [runSuspendable] and invoking Kotlin suspending code from 
-Quasar-instrumented code via [runFiberBlocking].
-
-## Example
-
-Invoke Quasar-instrumented suspendable code from Kotlin coroutine via [runSuspendable]:
-
-```kotlin
-runSuspendable(SuspendableCallable {
-    // Your suspendable code that will be instrumented by Quasar here
-})
-```
-
-Invoke Kotlin suspending function from Quasar-instrumented suspendable code via [runFiberBlocking]:
-
-```kotlin
-runFiberBlocking {
-    // Your Kotlin suspending code here
-}
-```
-
-# Package kotlinx.coroutines.experimental.quasar
-
-Integration with [Quasar](http://docs.paralleluniverse.co/quasar/).
-
-<!--- MODULE kotlinx-coroutines-core -->
-<!--- INDEX kotlinx.coroutines.experimental -->
-<!--- MODULE kotlinx-coroutines-quasar -->
-<!--- INDEX kotlinx.coroutines.experimental.quasar -->
-[runSuspendable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-quasar/kotlinx.coroutines.experimental.quasar/run-suspendable.html
-[runFiberBlocking]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-quasar/kotlinx.coroutines.experimental.quasar/run-fiber-blocking.html
-<!--- END -->
diff --git a/integration/kotlinx-coroutines-quasar/build.gradle b/integration/kotlinx-coroutines-quasar/build.gradle
deleted file mode 100644
index ff76b0d..0000000
--- a/integration/kotlinx-coroutines-quasar/build.gradle
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-configurations {
-    quasarAgent {
-        transitive = false
-    }
-}
-
-dependencies {
-    compile "co.paralleluniverse:quasar-core:0.7.9"
-    quasarAgent "co.paralleluniverse:quasar-core:0.7.9"
-}
-
-test {
-    jvmArgs "-javaagent:${configurations.quasarAgent.singleFile}"
-}
\ No newline at end of file
diff --git a/integration/kotlinx-coroutines-quasar/resources/META-INF/services/co.paralleluniverse.fibers.instrument.SuspendableClassifier b/integration/kotlinx-coroutines-quasar/resources/META-INF/services/co.paralleluniverse.fibers.instrument.SuspendableClassifier
deleted file mode 100644
index 7d16870..0000000
--- a/integration/kotlinx-coroutines-quasar/resources/META-INF/services/co.paralleluniverse.fibers.instrument.SuspendableClassifier
+++ /dev/null
@@ -1 +0,0 @@
-kotlinx.coroutines.experimental.quasar.KotlinSuspendableClassifier
\ No newline at end of file
diff --git a/integration/kotlinx-coroutines-quasar/src/KotlinSuspendableClassifier.kt b/integration/kotlinx-coroutines-quasar/src/KotlinSuspendableClassifier.kt
deleted file mode 100644
index 64d3bf8..0000000
--- a/integration/kotlinx-coroutines-quasar/src/KotlinSuspendableClassifier.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.experimental.quasar
-
-import co.paralleluniverse.fibers.instrument.MethodDatabase
-import co.paralleluniverse.fibers.instrument.SuspendableClassifier
-
-/**
- * @suppress **Internal implementation**.
- */
-class KotlinSuspendableClassifier : SuspendableClassifier {
-    override fun isSuspendable(
-            db: MethodDatabase,
-            sourceName: String?,
-            sourceDebugInfo: String?,
-            isInterface: Boolean,
-            className: String?,
-            superClassName: String?,
-            interfaces: Array<out String>,
-            methodName: String,
-            methodDesc: String,
-            methodSignature: String?,
-            methodExceptions: Array<out String>?
-    ): MethodDatabase.SuspendableType? {
-        if (methodName == "run" &&
-            methodDesc.startsWith("()") &&
-            interfaces.contains("co/paralleluniverse/strands/SuspendableCallable"))
-            return MethodDatabase.SuspendableType.SUSPENDABLE
-        return null
-    }
-}
\ No newline at end of file
diff --git a/integration/kotlinx-coroutines-quasar/src/Quasar.kt b/integration/kotlinx-coroutines-quasar/src/Quasar.kt
deleted file mode 100644
index 182d799..0000000
--- a/integration/kotlinx-coroutines-quasar/src/Quasar.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.experimental.quasar
-
-import co.paralleluniverse.fibers.Fiber
-import co.paralleluniverse.fibers.FiberAsync
-import co.paralleluniverse.fibers.SuspendExecution
-import co.paralleluniverse.fibers.Suspendable
-import co.paralleluniverse.strands.SuspendableCallable
-import kotlinx.coroutines.experimental.*
-import kotlin.coroutines.experimental.Continuation
-import kotlin.coroutines.experimental.CoroutineContext
-import kotlin.coroutines.experimental.startCoroutine
-
-/**
- * Runs Quasar-instrumented suspendable code from Kotlin coroutine.
- */
-suspend fun <T> runSuspendable(callable: SuspendableCallable<T>): T = suspendCancellableCoroutine { cont ->
-    val fiber = object : Fiber<Unit>() {
-        @Throws(SuspendExecution::class)
-        override fun run() {
-            val result = try { callable.run() }
-            catch (e: Throwable) {
-                cont.resumeWithException(e)
-                return
-            }
-            cont.resume(result)
-        }
-    }
-    cont.cancelFutureOnCancellation(fiber)
-    fiber.start()
-}
-
-/**
- * Runs Kotlin suspending function from Quasar-instrumented suspendable code.
- */
-@Suspendable
-fun <T> runFiberBlocking(block: suspend () -> T): T =
-    CoroutineAsync(block).run()
-
-private class CoroutineAsync<T>(
-    private val block: suspend () -> T
-) : FiberAsync<T, Throwable>(), Continuation<T> {
-    override val context: CoroutineContext =
-        GlobalScope.newCoroutineContext(Fiber.currentFiber().scheduler.executor.asCoroutineDispatcher())
-    override fun resume(value: T) { asyncCompleted(value) }
-    override fun resumeWithException(exception: Throwable) { asyncFailed(exception) }
-
-    override fun requestAsync() {
-        block.startCoroutine(completion = this)
-    }
-}
diff --git a/integration/kotlinx-coroutines-quasar/test/QuasarTest.kt b/integration/kotlinx-coroutines-quasar/test/QuasarTest.kt
deleted file mode 100644
index 784286f..0000000
--- a/integration/kotlinx-coroutines-quasar/test/QuasarTest.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package kotlinx.coroutines.experimental.quasar
-
-import co.paralleluniverse.fibers.*
-import co.paralleluniverse.strands.*
-import co.paralleluniverse.strands.dataflow.*
-import kotlinx.coroutines.experimental.*
-import org.junit.*
-import java.util.concurrent.*
-
-class QuasarTest : TestBase() {
-    @Before
-    fun setup() {
-        ignoreLostThreads(
-            "FiberTimedScheduler-default-fiber-pool",
-            "ForkJoinPool-default-fiber-pool-worker-",
-            "Timer-")
-    }
-
-    @Test
-    fun testRunSuspendable() = runBlocking<Unit> {
-        expect(1)
-        val started = CompletableDeferred<Unit>() // Kotlin's event
-        val x = Val<String>() // Quasar's data flow
-        launch {
-            started.await() // await Quasar's scheduler
-            expect(3) // will get scheduled when runSuspendable suspends
-            x.set("OK")
-        }
-        val result = runSuspendable(SuspendableCallable {
-            expect(2)
-            started.complete(Unit) // signal that we've started
-            x.get(10, TimeUnit.SECONDS) // will get suspended
-        })
-        finish(4)
-        check(result == "OK")
-    }
-
-    @Test
-    fun testRunFiberBlocking() = runBlocking {
-        expect(1)
-        val started = CompletableDeferred<Unit>() // Kotlin's event
-        val result = CompletableDeferred<String>() // result goes here
-        val fiber = object : Fiber<String>() {
-            @Throws(SuspendExecution::class)
-            override fun run(): String {
-                expect(3)
-                started.complete(Unit) // signal that fiber is started
-                // block fiber on suspendable await
-                val value = runFiberBlocking {
-                    result.await()
-                }
-                expect(5)
-                return value
-            }
-        }
-        expect(2) // before starting fiber
-        fiber.start() // now start fiber
-        started.await() // wait fiber to start
-        expect(4)
-        result.complete("OK") // send Ok to fiber
-        val answer = runSuspendable(SuspendableCallable {
-            fiber.get()
-        })
-        finish(6)
-        check(answer == "OK")
-    }
-}
\ No newline at end of file
diff --git a/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt b/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt
index 6976b36..e70c8a5 100644
--- a/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt
+++ b/integration/kotlinx-coroutines-slf4j/src/MDCContext.kt
@@ -50,12 +50,14 @@
      */
     companion object Key : CoroutineContext.Key<MDCContext>
 
+    /** @suppress */
     override fun updateThreadContext(context: CoroutineContext): MDCContextMap {
         val oldState = MDC.getCopyOfContextMap()
         setCurrent(contextMap)
         return oldState
     }
 
+    /** @suppress */
     override fun restoreThreadContext(context: CoroutineContext, oldState: MDCContextMap) {
         setCurrent(oldState)
     }
diff --git a/js/kotlinx-coroutines-core-js/README.md b/js/kotlinx-coroutines-core-js/README.md
index a4dff92..21e6b7b 100644
--- a/js/kotlinx-coroutines-core-js/README.md
+++ b/js/kotlinx-coroutines-core-js/README.md
@@ -69,7 +69,7 @@
 [CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
 [Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-dispatchers/-default.html
 [Dispatchers.Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-dispatchers/-unconfined.html
-[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
+[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable.html
 [CoroutineExceptionHandler]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-exception-handler/index.html
 [delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
 [yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
diff --git a/js/kotlinx-coroutines-core-js/src/Exceptions.kt b/js/kotlinx-coroutines-core-js/src/Exceptions.kt
index 9022417..42919e5 100644
--- a/js/kotlinx-coroutines-core-js/src/Exceptions.kt
+++ b/js/kotlinx-coroutines-core-js/src/Exceptions.kt
@@ -16,7 +16,7 @@
  * Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled while it is suspending.
  * It indicates _normal_ cancellation of a coroutine.
  * **It is not printed to console/log by default uncaught exception handler**.
- * (see [handleCoroutineException]).
+ * (see [CoroutineExceptionHandler]).
  */
 public actual open class CancellationException actual constructor(message: String?) : IllegalStateException(message)
 
diff --git a/js/kotlinx-coroutines-core-js/src/JSDispatcher.kt b/js/kotlinx-coroutines-core-js/src/JSDispatcher.kt
index 8317cae..e94bcb4 100644
--- a/js/kotlinx-coroutines-core-js/src/JSDispatcher.kt
+++ b/js/kotlinx-coroutines-core-js/src/JSDispatcher.kt
@@ -4,17 +4,21 @@
 
 package kotlinx.coroutines.experimental
 
-import kotlinx.coroutines.experimental.timeunit.TimeUnit
 import kotlin.coroutines.experimental.*
 import org.w3c.dom.*
 
+private const val MAX_DELAY = Int.MAX_VALUE.toLong()
+
+private fun delayToInt(timeMillis: Long): Int =
+    timeMillis.coerceIn(0, MAX_DELAY).toInt()
+
 internal class NodeDispatcher : CoroutineDispatcher(), Delay {
     override fun dispatch(context: CoroutineContext, block: Runnable) {
         setTimeout({ block.run() }, 0)
     }
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
-        val handle = setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, time.toIntMillis(unit))
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
+        val handle = setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, delayToInt(timeMillis))
         // Actually on cancellation, but clearTimeout is idempotent
         continuation.invokeOnCancellation(handler = ClearTimeout(handle).asHandler)
     }
@@ -25,8 +29,8 @@
         override fun toString(): String = "ClearTimeout[$handle]"
     }
 
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
-        val handle = setTimeout({ block.run() }, time.toIntMillis(unit))
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
+        val handle = setTimeout({ block.run() }, delayToInt(timeMillis))
         return ClearTimeout(handle)
     }
 }
@@ -53,12 +57,12 @@
         queue.enqueue(block)
     }
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
-        window.setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, time.toIntMillis(unit))
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
+        window.setTimeout({ with(continuation) { resumeUndispatched(Unit) } }, delayToInt(timeMillis))
     }
 
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
-        val handle = window.setTimeout({ block.run() }, time.toIntMillis(unit))
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
+        val handle = window.setTimeout({ block.run() }, delayToInt(timeMillis))
         return object : DisposableHandle {
             override fun dispose() {
                 window.clearTimeout(handle)
@@ -99,9 +103,6 @@
     }
 }
 
-private fun Long.toIntMillis(unit: TimeUnit): Int =
-    unit.toMillis(this).coerceIn(0L, Int.MAX_VALUE.toLong()).toInt()
-
 internal open class Queue<T : Any> {
     private var queue = arrayOfNulls<Any?>(8)
     private var head = 0
diff --git a/js/kotlinx-coroutines-core-js/src/Promise.kt b/js/kotlinx-coroutines-core-js/src/Promise.kt
index 929cd70..a963347 100644
--- a/js/kotlinx-coroutines-core-js/src/Promise.kt
+++ b/js/kotlinx-coroutines-core-js/src/Promise.kt
@@ -20,16 +20,26 @@
  *
  * @param context additional to [CoroutineScope.coroutineContext] context of the coroutine.
  * @param start coroutine start option. The default value is [CoroutineStart.DEFAULT].
- * @param onCompletion optional completion handler for the coroutine (see [Job.invokeOnCompletion]).
  * @param block the coroutine code.
  */
 public fun <T> CoroutineScope.promise(
     context: CoroutineContext = EmptyCoroutineContext,
     start: CoroutineStart = CoroutineStart.DEFAULT,
+    block: suspend CoroutineScope.() -> T
+): Promise<T> =
+    async(context, start, block).asPromise()
+
+/**
+ * @suppress **Deprecated**: onCompletion parameter is deprecated.
+ */
+@Deprecated("onCompletion parameter is deprecated")
+public fun <T> CoroutineScope.promise(
+    context: CoroutineContext = EmptyCoroutineContext,
+    start: CoroutineStart = CoroutineStart.DEFAULT,
     onCompletion: CompletionHandler? = null,
     block: suspend CoroutineScope.() -> T
 ): Promise<T> =
-    async(context, start, onCompletion, block = block).asPromise()
+    async(context, start, block).also { if (onCompletion != null) it.invokeOnCompletion(onCompletion) }.asPromise()
 
 /**
  * Starts new coroutine and returns its result as an implementation of [Promise].
diff --git a/native/kotlinx-coroutines-core-native/README.md b/native/kotlinx-coroutines-core-native/README.md
index 824268a..de0bd06 100644
--- a/native/kotlinx-coroutines-core-native/README.md
+++ b/native/kotlinx-coroutines-core-native/README.md
@@ -72,7 +72,7 @@
 [CoroutineDispatcher]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-dispatcher/index.html
 [Dispatchers.Default]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-dispatchers/-default.html
 [Dispatchers.Unconfined]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-dispatchers/-unconfined.html
-[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable/index.html
+[NonCancellable]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-non-cancellable.html
 [CoroutineExceptionHandler]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/-coroutine-exception-handler/index.html
 [delay]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/delay.html
 [yield]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental/yield.html
diff --git a/native/kotlinx-coroutines-core-native/src/CoroutineContext.kt b/native/kotlinx-coroutines-core-native/src/CoroutineContext.kt
index 6fca7ff..cb54cb8 100644
--- a/native/kotlinx-coroutines-core-native/src/CoroutineContext.kt
+++ b/native/kotlinx-coroutines-core-native/src/CoroutineContext.kt
@@ -5,7 +5,6 @@
 package kotlinx.coroutines.experimental
 
 import kotlin.coroutines.experimental.*
-import kotlinx.coroutines.experimental.timeunit.*
 
 internal val currentEventLoop = ArrayList<BlockingEventLoop>()
 
@@ -15,10 +14,10 @@
 internal object DefaultExecutor : CoroutineDispatcher(), Delay {
     override fun dispatch(context: CoroutineContext, block: Runnable) =
         takeEventLoop().dispatch(context, block)
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) =
-        takeEventLoop().scheduleResumeAfterDelay(time, unit, continuation)
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle =
-        takeEventLoop().invokeOnTimeout(time, unit, block)
+    override fun scheduleResumeAfterDelay(time: Long, continuation: CancellableContinuation<Unit>) =
+        takeEventLoop().scheduleResumeAfterDelay(time, continuation)
+    override fun invokeOnTimeout(time: Long, block: Runnable): DisposableHandle =
+        takeEventLoop().invokeOnTimeout(time, block)
 
     fun execute(task: Runnable) {
         error("Cannot execute task because event loop was shut down")
diff --git a/native/kotlinx-coroutines-core-native/src/EventLoop.kt b/native/kotlinx-coroutines-core-native/src/EventLoop.kt
index e3a9227..021db70 100644
--- a/native/kotlinx-coroutines-core-native/src/EventLoop.kt
+++ b/native/kotlinx-coroutines-core-native/src/EventLoop.kt
@@ -7,7 +7,6 @@
 import kotlinx.atomicfu.*
 import kotlinx.cinterop.*
 import kotlinx.coroutines.experimental.internal.*
-import kotlinx.coroutines.experimental.timeunit.*
 import platform.posix.*
 import kotlin.coroutines.experimental.*
 import kotlin.system.*
@@ -44,6 +43,15 @@
 private const val REMOVED = 1
 private const val RESCHEDULED = 2
 
+private const val MS_TO_NS = 1_000_000L
+private const val MAX_MS = Long.MAX_VALUE / MS_TO_NS
+
+private fun delayToNanos(timeMillis: Long): Long = when {
+    timeMillis <= 0 -> 0L
+    timeMillis >= MAX_MS -> Long.MAX_VALUE
+    else -> timeMillis * MS_TO_NS
+}
+
 @Suppress("PrivatePropertyName")
 private val CLOSED_EMPTY = Symbol("CLOSED_EMPTY")
 
@@ -86,11 +94,11 @@
     override fun dispatch(context: CoroutineContext, block: Runnable) =
         execute(block)
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) =
-        schedule(DelayedResumeTask(time, unit, continuation))
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) =
+        schedule(DelayedResumeTask(timeMillis, continuation))
 
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle =
-        DelayedRunnableTask(time, unit, block).also { schedule(it) }
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle =
+        DelayedRunnableTask(timeMillis, block).also { schedule(it) }
 
     override fun processNextEvent(): Long {
         // queue all delayed tasks that are due to be executed
@@ -235,11 +243,11 @@
     }
 
     internal abstract inner class DelayedTask(
-        time: Long, timeUnit: TimeUnit
+        timeMillis: Long
     ) : Runnable, Comparable<DelayedTask>, DisposableHandle, ThreadSafeHeapNode {
         override var index: Int = -1
         var state = DELAYED // Guarded by by lock on this task for reschedule/dispose purposes
-        val nanoTime: Long = nanoTime() + timeUnit.toNanos(time)
+        val nanoTime: Long = nanoTime() + delayToNanos(timeMillis)
 
         override fun compareTo(other: DelayedTask): Int {
             val dTime = nanoTime - other.nanoTime
@@ -274,18 +282,18 @@
     }
 
     private inner class DelayedResumeTask(
-        time: Long, timeUnit: TimeUnit,
+        timeMillis: Long,
         private val cont: CancellableContinuation<Unit>
-    ) : DelayedTask(time, timeUnit) {
+    ) : DelayedTask(timeMillis) {
         override fun run() {
             with(cont) { resumeUndispatched(Unit) }
         }
     }
 
     private inner class DelayedRunnableTask(
-        time: Long, timeUnit: TimeUnit,
+        timeMillis: Long,
         private val block: Runnable
-    ) : DelayedTask(time, timeUnit) {
+    ) : DelayedTask(timeMillis) {
         override fun run() { block.run() }
         override fun toString(): String = super.toString() + block.toString()
     }
diff --git a/native/kotlinx-coroutines-core-native/src/Exceptions.kt b/native/kotlinx-coroutines-core-native/src/Exceptions.kt
index d76797b..8110fef 100644
--- a/native/kotlinx-coroutines-core-native/src/Exceptions.kt
+++ b/native/kotlinx-coroutines-core-native/src/Exceptions.kt
@@ -16,7 +16,7 @@
  * Thrown by cancellable suspending functions if the [Job] of the coroutine is cancelled while it is suspending.
  * It indicates _normal_ cancellation of a coroutine.
  * **It is not printed to console/log by default uncaught exception handler**.
- * (see [handleCoroutineException]).
+ * (see [CoroutineExceptionHandler]).
  */
 public actual open class CancellationException actual constructor(message: String?) : IllegalStateException(message)
 
diff --git a/reactive/coroutines-guide-reactive.md b/reactive/coroutines-guide-reactive.md
index e4b05bf..29cd34f 100644
--- a/reactive/coroutines-guide-reactive.md
+++ b/reactive/coroutines-guide-reactive.md
@@ -531,7 +531,9 @@
 
 <!--- TEST -->
 
-Another implementation of [BroadcastChannel] is [ArrayBroadcastChannel]. It delivers every event to every
+Another implementation of [BroadcastChannel] is `ArrayBroadcastChannel` with an array-based buffer of
+a specified `capacity`. It can be created with `BroadcastChannel(capacity)`. 
+It delivers every event to every
 subscriber since the moment the corresponding subscription is open. It corresponds to 
 [PublishSubject](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/subjects/PublishSubject.html) in Rx.
 The capacity of the buffer in the constructor of `ArrayBroadcastChannel` controls the numbers of elements
@@ -1069,7 +1071,6 @@
 [SendChannel.send]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/send.html
 [BroadcastChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-broadcast-channel/index.html
 [ConflatedBroadcastChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-conflated-broadcast-channel/index.html
-[ArrayBroadcastChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-array-broadcast-channel/index.html
 <!--- INDEX kotlinx.coroutines.experimental.selects -->
 [select]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/select.html
 [whileSelect]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.selects/while-select.html
diff --git a/reactive/kotlinx-coroutines-reactive/src/Channel.kt b/reactive/kotlinx-coroutines-reactive/src/Channel.kt
index a3fe5f1..42556db 100644
--- a/reactive/kotlinx-coroutines-reactive/src/Channel.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/Channel.kt
@@ -5,14 +5,20 @@
 package kotlinx.coroutines.experimental.reactive
 
 import kotlinx.atomicfu.*
+import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
 import org.reactivestreams.*
 
 /**
  * Subscribes to this [Publisher] and returns a channel to receive elements emitted by it.
  * The resulting channel shall be [cancelled][ReceiveChannel.cancel] to unsubscribe from this publisher.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
+ *
  * @param request how many items to request from publisher in advance (optional, on-demand request by default).
  */
+@ObsoleteCoroutinesApi
 @Suppress("CONFLICTING_OVERLOADS")
 public fun <T> Publisher<T>.openSubscription(request: Int = 0): ReceiveChannel<T> {
     val channel = SubscriptionChannel<T>(request)
diff --git a/reactive/kotlinx-coroutines-reactive/src/Convert.kt b/reactive/kotlinx-coroutines-reactive/src/Convert.kt
index 5fa826a..f6487db 100644
--- a/reactive/kotlinx-coroutines-reactive/src/Convert.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/Convert.kt
@@ -15,8 +15,12 @@
  * Every subscriber receives values from this channel in **fan-out** fashion. If the are multiple subscribers,
  * they'll receive values in round-robin way.
  *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
+ *
  * @param context -- the coroutine context from which the resulting observable is going to be signalled
  */
+@ObsoleteCoroutinesApi
 public fun <T> ReceiveChannel<T>.asPublisher(context: CoroutineContext = EmptyCoroutineContext): Publisher<T> = GlobalScope.publish(context) {
     for (t in this@asPublisher)
         send(t)
diff --git a/reactive/kotlinx-coroutines-reactive/src/Publish.kt b/reactive/kotlinx-coroutines-reactive/src/Publish.kt
index 7222208..f86b5d8 100644
--- a/reactive/kotlinx-coroutines-reactive/src/Publish.kt
+++ b/reactive/kotlinx-coroutines-reactive/src/Publish.kt
@@ -31,9 +31,13 @@
  * The parent job is inherited from a [CoroutineScope] as well, but it can also be overridden
  * with corresponding [coroutineContext] element.
  *
+ * **Note: This is an experimental api.** Behaviour of publishers that work as children in a parent scope with respect
+ *        to cancellation and error handling may change in the future.
+ *
  * @param context context of the coroutine.
  * @param block the coroutine code.
  */
+@ExperimentalCoroutinesApi
 public fun <T> CoroutineScope.publish(
     context: CoroutineContext = EmptyCoroutineContext,
     block: suspend ProducerScope<T>.() -> Unit
@@ -62,6 +66,7 @@
 private const val CLOSED = -1L    // closed, but have not signalled onCompleted/onError yet
 private const val SIGNALLED = -2L  // already signalled subscriber onCompleted/onError
 
+@Suppress("CONFLICTING_JVM_DECLARATIONS", "RETURN_TYPE_MISMATCH_ON_INHERITANCE")
 private class PublisherCoroutine<in T>(
     parentContext: CoroutineContext,
     private val subscriber: Subscriber<T>
@@ -216,7 +221,7 @@
     }
 
     // Subscription impl
-    override fun cancel() {
-        cancel(cause = null)
-    }
+    @JvmName("cancel")
+    @Suppress("NOTHING_TO_OVERRIDE", "ACCIDENTAL_OVERRIDE")
+    override fun cancelSubscription() = super.cancel(null)
 }
\ No newline at end of file
diff --git a/reactive/kotlinx-coroutines-reactor/src/Convert.kt b/reactive/kotlinx-coroutines-reactor/src/Convert.kt
index 822a64a..d4d565c 100644
--- a/reactive/kotlinx-coroutines-reactor/src/Convert.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/Convert.kt
@@ -16,9 +16,27 @@
  * Every subscriber gets the signal at the same time.
  * Unsubscribing from the resulting mono **does not** affect the original job in any way.
  *
+ * **Note: This is an experimental api.** Conversion of coroutines primitives to reactive entities may change
+ *    in the future to account for the concept of structured concurrency.
+ *
  * @param context -- the coroutine context from which the resulting mono is going to be signalled
  */
-public fun Job.asMono(context: CoroutineContext = EmptyCoroutineContext): Mono<Unit> = GlobalScope.mono(context) { this@asMono.join() }
+@ExperimentalCoroutinesApi
+public fun Job.asMono(context: CoroutineContext): Mono<Unit> = GlobalScope.mono(context) { this@asMono.join() }
+
+/**
+ * @suppress **Deprecated**: Specify explicit context
+ */
+@Deprecated("Specify explicit context", level = DeprecationLevel.HIDDEN)
+@JvmName("asMono\$default")
+public fun Job.asMono0(context: CoroutineContext?, flags: Int, obj: Any?): Mono<Unit> =
+    asMono(context ?: EmptyCoroutineContext)
+
+/**
+ * @suppress **Deprecated**: Specify explicit context
+ */
+@Deprecated("Specify explicit context", replaceWith = ReplaceWith("asMono(EmptyCoroutineContext)"))
+public fun Job.asMono(): Mono<Unit> = asMono(EmptyCoroutineContext)
 
 /**
  * Converts this deferred value to the hot reactive mono that signals
@@ -27,9 +45,27 @@
  * Every subscriber gets the same completion value.
  * Unsubscribing from the resulting mono **does not** affect the original deferred value in any way.
  *
+ * **Note: This is an experimental api.** Conversion of coroutines primitives to reactive entities may change
+ *    in the future to account for the concept of structured concurrency.
+ *
  * @param context -- the coroutine context from which the resulting mono is going to be signalled
  */
-public fun <T> Deferred<T?>.asMono(context: CoroutineContext = EmptyCoroutineContext): Mono<T> = GlobalScope.mono(context) { this@asMono.await() }
+@ExperimentalCoroutinesApi
+public fun <T> Deferred<T?>.asMono(context: CoroutineContext): Mono<T> = GlobalScope.mono(context) { this@asMono.await() }
+
+/**
+ * @suppress **Deprecated**: Specify explicit context
+ */
+@Deprecated("Specify explicit context", level = DeprecationLevel.HIDDEN)
+@JvmName("asMono\$default")
+public fun <T> Deferred<T?>.asMono0(context: CoroutineContext?, flags: Int, obj: Any?): Mono<T> =
+    asMono(context ?: EmptyCoroutineContext)
+
+/**
+ * @suppress **Deprecated**: Specify explicit context
+ */
+@Deprecated("Specify explicit context", replaceWith = ReplaceWith("asMono(EmptyCoroutineContext)"))
+public fun <T> Deferred<T?>.asMono(): Mono<T> = asMono(EmptyCoroutineContext)
 
 /**
  * Converts a stream of elements received from the channel to the hot reactive flux.
@@ -37,8 +73,12 @@
  * Every subscriber receives values from this channel in **fan-out** fashion. If the are multiple subscribers,
  * they'll receive values in round-robin way.
  *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
+ *
  * @param context -- the coroutine context from which the resulting flux is going to be signalled
  */
+@ObsoleteCoroutinesApi
 public fun <T> ReceiveChannel<T>.asFlux(context: CoroutineContext = EmptyCoroutineContext): Flux<T> = GlobalScope.flux(context) {
     for (t in this@asFlux)
         send(t)
diff --git a/reactive/kotlinx-coroutines-reactor/src/Flux.kt b/reactive/kotlinx-coroutines-reactor/src/Flux.kt
index 73e1a6a..1873d3b 100644
--- a/reactive/kotlinx-coroutines-reactor/src/Flux.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/Flux.kt
@@ -28,7 +28,11 @@
  * | `send`                                       | `onNext`
  * | Normal completion or `close` without cause   | `onComplete`
  * | Failure with exception or `close` with cause | `onError`
+ * 
+ * **Note: This is an experimental api.** Behaviour of publishers that work as children in a parent scope with respect
+ *        to cancellation and error handling may change in the future.
  */
+@ExperimentalCoroutinesApi
 fun <T> CoroutineScope.flux(
     context: CoroutineContext = EmptyCoroutineContext,
     block: suspend ProducerScope<T>.() -> Unit
diff --git a/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt b/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt
index 6496732..1819b36 100644
--- a/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt
+++ b/reactive/kotlinx-coroutines-reactor/src/Scheduler.kt
@@ -7,35 +7,46 @@
 import kotlinx.coroutines.experimental.*
 import reactor.core.Disposable
 import reactor.core.scheduler.Scheduler
-import java.util.concurrent.TimeUnit
+import java.util.concurrent.*
 import kotlin.coroutines.experimental.CoroutineContext
 
 /**
  * Converts an instance of [Scheduler] to an implementation of [CoroutineDispatcher].
  */
-fun Scheduler.asCoroutineDispatcher() = SchedulerCoroutineDispatcher(this)
+fun Scheduler.asCoroutineDispatcher(): SchedulerCoroutineDispatcher = SchedulerCoroutineDispatcher(this)
 
 /**
  * Implements [CoroutineDispatcher] on top of an arbitrary [Scheduler].
  * @param scheduler a scheduler.
  */
-open class SchedulerCoroutineDispatcher(private val scheduler: Scheduler) : CoroutineDispatcher(), Delay {
+public class SchedulerCoroutineDispatcher(
+    /**
+     * Underlying scheduler of current [CoroutineDispatcher].
+     */
+    public val scheduler: Scheduler
+) : CoroutineDispatcher(), Delay {
+    /** @suppress */
     override fun dispatch(context: CoroutineContext, block: Runnable) {
         scheduler.schedule(block)
     }
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
+    /** @suppress */
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
         val disposable = scheduler.schedule({
             with(continuation) { resumeUndispatched(Unit) }
-        }, time, unit)
+        }, timeMillis, TimeUnit.MILLISECONDS)
         continuation.disposeOnCancellation(disposable.asDisposableHandle())
     }
 
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle =
-        scheduler.schedule(block, time, unit).asDisposableHandle()
+    /** @suppress */
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle =
+        scheduler.schedule(block, timeMillis, TimeUnit.MILLISECONDS).asDisposableHandle()
 
+    /** @suppress */
     override fun toString(): String = scheduler.toString()
+    /** @suppress */
     override fun equals(other: Any?): Boolean = other is SchedulerCoroutineDispatcher && other.scheduler === scheduler
+    /** @suppress */
     override fun hashCode(): Int = System.identityHashCode(scheduler)
 }
 
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt b/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt
index a124494..eb41658 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxAwait.kt
@@ -5,11 +5,8 @@
 package kotlinx.coroutines.experimental.rx2
 
 import io.reactivex.*
-import io.reactivex.disposables.Disposable
-import kotlinx.coroutines.experimental.CancellableContinuation
-import kotlinx.coroutines.experimental.CancellationException
-import kotlinx.coroutines.experimental.Job
-import kotlinx.coroutines.experimental.suspendCancellableCoroutine
+import io.reactivex.disposables.*
+import kotlinx.coroutines.experimental.*
 
 // ------------------------ CompletableSource ------------------------
 
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt b/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt
new file mode 100644
index 0000000..be353bf
--- /dev/null
+++ b/reactive/kotlinx-coroutines-rx2/src/RxCancellable.kt
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.coroutines.experimental.rx2
+
+import io.reactivex.functions.*
+import kotlinx.coroutines.experimental.*
+
+internal class RxCancellable(private val job: Job) : Cancellable {
+    override fun cancel() {
+        job.cancel()
+    }
+}
\ No newline at end of file
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt b/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt
index 28bebc2..00e3a02 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxChannel.kt
@@ -6,12 +6,17 @@
 
 import io.reactivex.*
 import io.reactivex.disposables.*
+import kotlinx.coroutines.experimental.*
 import kotlinx.coroutines.experimental.channels.*
 
 /**
  * Subscribes to this [MaybeSource] and returns a channel to receive elements emitted by it.
  * The resulting channel shall be [cancelled][ReceiveChannel.cancel] to unsubscribe from this source.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 @Suppress("CONFLICTING_OVERLOADS")
 public fun <T> MaybeSource<T>.openSubscription(): ReceiveChannel<T> {
     val channel = SubscriptionChannel<T>()
@@ -27,7 +32,11 @@
 /**
  * Subscribes to this [ObservableSource] and returns a channel to receive elements emitted by it.
  * The resulting channel shall be [cancelled][ReceiveChannel.cancel] to unsubscribe from this source.
+ *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
  */
+@ObsoleteCoroutinesApi
 @Suppress("CONFLICTING_OVERLOADS")
 public fun <T> ObservableSource<T>.openSubscription(): ReceiveChannel<T> {
     val channel = SubscriptionChannel<T>()
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt b/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt
index 50dcb9f..159bc3c 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxCompletable.kt
@@ -33,7 +33,7 @@
 ): Completable = Completable.create { subscriber ->
     val newContext = newCoroutineContext(context)
     val coroutine = RxCompletableCoroutine(newContext, subscriber)
-    subscriber.setCancellable(coroutine)
+    subscriber.setCancellable(RxCancellable(coroutine))
     coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
 }
 
@@ -55,7 +55,7 @@
 private class RxCompletableCoroutine(
     parentContext: CoroutineContext,
     private val subscriber: CompletableEmitter
-) : AbstractCoroutine<Unit>(parentContext, true), Cancellable {
+) : AbstractCoroutine<Unit>(parentContext, true) {
     override fun onCompleted(value: Unit) {
         if (!subscriber.isDisposed) subscriber.onComplete()
     }
@@ -63,7 +63,4 @@
     override fun onCompletedExceptionally(exception: Throwable) {
         if (!subscriber.isDisposed) subscriber.onError(exception)
     }
-
-    // Cancellable impl
-    override fun cancel() { cancel(cause = null) }
 }
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt
index d0bade4..72de46c 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxConvert.kt
@@ -16,8 +16,12 @@
  * Every subscriber gets the signal at the same time.
  * Unsubscribing from the resulting completable **does not** affect the original job in any way.
  *
+ * **Note: This is an experimental api.** Conversion of coroutines primitives to reactive entities may change
+ *    in the future to account for the concept of structured concurrency.
+ *
  * @param context -- the coroutine context from which the resulting completable is going to be signalled
  */
+@ExperimentalCoroutinesApi
 public fun Job.asCompletable(context: CoroutineContext): Completable = GlobalScope.rxCompletable(context) {
     this@asCompletable.join()
 }
@@ -29,8 +33,12 @@
  * Every subscriber gets the same completion value.
  * Unsubscribing from the resulting maybe **does not** affect the original deferred value in any way.
  *
+ * **Note: This is an experimental api.** Conversion of coroutines primitives to reactive entities may change
+ *    in the future to account for the concept of structured concurrency.
+ *
  * @param context -- the coroutine context from which the resulting maybe is going to be signalled
  */
+@ExperimentalCoroutinesApi
 public fun <T> Deferred<T?>.asMaybe(context: CoroutineContext): Maybe<T> = GlobalScope.rxMaybe(context) {
     this@asMaybe.await()
 }
@@ -42,8 +50,12 @@
  * Every subscriber gets the same completion value.
  * Unsubscribing from the resulting single **does not** affect the original deferred value in any way.
  *
+ * **Note: This is an experimental api.** Conversion of coroutines primitives to reactive entities may change
+ *    in the future to account for the concept of structured concurrency.
+ *
  * @param context -- the coroutine context from which the resulting single is going to be signalled
  */
+@ExperimentalCoroutinesApi
 public fun <T> Deferred<T>.asSingle(context: CoroutineContext): Single<T> = GlobalScope.rxSingle(context) {
     this@asSingle.await()
 }
@@ -54,8 +66,12 @@
  * Every subscriber receives values from this channel in **fan-out** fashion. If the are multiple subscribers,
  * they'll receive values in round-robin way.
  *
+ * **Note: This API will become obsolete in future updates with introduction of lazy asynchronous streams.**
+ *           See [issue #254](https://github.com/Kotlin/kotlinx.coroutines/issues/254).
+ *
  * @param context -- the coroutine context from which the resulting observable is going to be signalled
  */
+@ObsoleteCoroutinesApi
 public fun <T> ReceiveChannel<T>.asObservable(context: CoroutineContext): Observable<T> = GlobalScope.rxObservable(context) {
     for (t in this@asObservable)
         send(t)
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt b/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt
index ad3b53d..4ce4325 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxFlowable.kt
@@ -29,9 +29,13 @@
  * The parent job is inherited from a [CoroutineScope] as well, but it can also be overridden
  * with corresponding [coroutineContext] element.
  *
+ * **Note: This is an experimental api.** Behaviour of publishers that work as children in a parent scope with respect
+ *        to cancellation and error handling may change in the future.
+ *        
  * @param context context of the coroutine.
  * @param block the coroutine code.
  */
+@ExperimentalCoroutinesApi
 public fun <T> CoroutineScope.rxFlowable(
     context: CoroutineContext = EmptyCoroutineContext,
     block: suspend ProducerScope<T>.() -> Unit
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt
index 44aee95..4b9496b 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxMaybe.kt
@@ -34,7 +34,7 @@
 ): Maybe<T> = Maybe.create { subscriber ->
     val newContext = newCoroutineContext(context)
     val coroutine = RxMaybeCoroutine(newContext, subscriber)
-    subscriber.setCancellable(coroutine)
+    subscriber.setCancellable(RxCancellable(coroutine))
     coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
 }
 
@@ -56,7 +56,7 @@
 private class RxMaybeCoroutine<T>(
     parentContext: CoroutineContext,
     private val subscriber: MaybeEmitter<T>
-) : AbstractCoroutine<T>(parentContext, true), Cancellable {
+) : AbstractCoroutine<T>(parentContext, true) {
     override fun onCompleted(value: T) {
         if (!subscriber.isDisposed) {
             if (value == null) subscriber.onComplete() else subscriber.onSuccess(value)
@@ -66,7 +66,4 @@
     override fun onCompletedExceptionally(exception: Throwable) {
         if (!subscriber.isDisposed) subscriber.onError(exception)
     }
-
-    // Cancellable impl
-    override fun cancel() { cancel(cause = null) }
 }
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt
index 1744968..23b3f69 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxObservable.kt
@@ -32,16 +32,20 @@
  * The parent job is inherited from a [CoroutineScope] as well, but it can also be overridden
  * with corresponding [coroutineContext] element.
  *
+ * **Note: This is an experimental api.** Behaviour of publishers that work as children in a parent scope with respect
+ *        to cancellation and error handling may change in the future.
+ *        
  * @param context context of the coroutine.
  * @param block the coroutine code.
  */
+@ExperimentalCoroutinesApi
 public fun <T> CoroutineScope.rxObservable(
     context: CoroutineContext = EmptyCoroutineContext,
     block: suspend ProducerScope<T>.() -> Unit
 ): Observable<T> = Observable.create { subscriber ->
     val newContext = newCoroutineContext(context)
     val coroutine = RxObservableCoroutine(newContext, subscriber)
-    subscriber.setCancellable(coroutine) // do it first (before starting coroutine), to await unnecessary suspensions
+    subscriber.setCancellable(RxCancellable(coroutine)) // do it first (before starting coroutine), to await unnecessary suspensions
     coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
 }
 
@@ -67,7 +71,7 @@
 private class RxObservableCoroutine<T>(
     parentContext: CoroutineContext,
     private val subscriber: ObservableEmitter<T>
-) : AbstractCoroutine<Unit>(parentContext, true), ProducerScope<T>, Cancellable, SelectClause2<T, SendChannel<T>> {
+) : AbstractCoroutine<Unit>(parentContext, true), ProducerScope<T>, SelectClause2<T, SendChannel<T>> {
     override val channel: SendChannel<T> get() = this
 
     // Mutex is locked when while subscriber.onXXX is being invoked
@@ -167,7 +171,4 @@
         if (mutex.tryLock()) // if we can acquire the lock
             doLockedSignalCompleted()
     }
-
-    // Cancellable impl
-    override fun cancel() { cancel(cause = null) }
 }
\ No newline at end of file
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt b/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt
index 66747db..d2ade17 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxScheduler.kt
@@ -16,34 +16,41 @@
  * Converts an instance of [Scheduler] to an implementation of [CoroutineDispatcher]
  * and provides native [delay][Delay.delay] support.
  */
-public fun Scheduler.asCoroutineDispatcher() = SchedulerCoroutineDispatcher(this)
+public fun Scheduler.asCoroutineDispatcher(): SchedulerCoroutineDispatcher = SchedulerCoroutineDispatcher(this)
 
 /**
  * Implements [CoroutineDispatcher] on top of an arbitrary [Scheduler].
  * @param scheduler a scheduler.
  */
-public class SchedulerCoroutineDispatcher(private val scheduler: Scheduler) : CoroutineDispatcher(), Delay {
+public class SchedulerCoroutineDispatcher(
+    /**
+     * Underlying scheduler of current [CoroutineDispatcher].
+     */
+    public val scheduler: Scheduler
+) : CoroutineDispatcher(), Delay {
+    /** @suppress */
     override fun dispatch(context: CoroutineContext, block: Runnable) {
         scheduler.scheduleDirect(block)
     }
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
+    /** @suppress */
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
         val disposable = scheduler.scheduleDirect({
             with(continuation) { resumeUndispatched(Unit) }
-        }, time, unit)
+        }, timeMillis, TimeUnit.MILLISECONDS)
         continuation.disposeOnCancellation(disposable)
     }
 
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
-        val disposable = scheduler.scheduleDirect(block, time, unit)
-        return object : DisposableHandle {
-            override fun dispose() {
-                disposable.dispose()
-            }
-        }
+    /** @suppress */
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
+        val disposable = scheduler.scheduleDirect(block, timeMillis, TimeUnit.MILLISECONDS)
+        return DisposableHandle { disposable.dispose() }
     }
 
+    /** @suppress */
     override fun toString(): String = scheduler.toString()
+    /** @suppress */
     override fun equals(other: Any?): Boolean = other is SchedulerCoroutineDispatcher && other.scheduler === scheduler
+    /** @suppress */
     override fun hashCode(): Int = System.identityHashCode(scheduler)
 }
diff --git a/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt b/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt
index 00bb9fe..7ffe1cd 100644
--- a/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt
+++ b/reactive/kotlinx-coroutines-rx2/src/RxSingle.kt
@@ -33,7 +33,7 @@
 ): Single<T> = Single.create { subscriber ->
     val newContext = newCoroutineContext(context)
     val coroutine = RxSingleCoroutine(newContext, subscriber)
-    subscriber.setCancellable(coroutine)
+    subscriber.setCancellable(RxCancellable(coroutine))
     coroutine.start(CoroutineStart.DEFAULT, coroutine, block)
 }
 
@@ -55,7 +55,7 @@
 private class RxSingleCoroutine<T>(
     parentContext: CoroutineContext,
     private val subscriber: SingleEmitter<T>
-) : AbstractCoroutine<T>(parentContext, true), Cancellable {
+) : AbstractCoroutine<T>(parentContext, true) {
     override fun onCompleted(value: T) {
         if (!subscriber.isDisposed) subscriber.onSuccess(value)
     }
@@ -63,7 +63,4 @@
     override fun onCompletedExceptionally(exception: Throwable) {
         if (!subscriber.isDisposed) subscriber.onError(exception)
     }
-
-    // Cancellable impl
-    override fun cancel() { cancel(cause = null) }
 }
diff --git a/settings.gradle b/settings.gradle
index d07e2bf..95a0f11 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -26,9 +26,8 @@
 
 module('integration/kotlinx-coroutines-guava')
 module('integration/kotlinx-coroutines-jdk8')
-module('integration/kotlinx-coroutines-nio')
-module('integration/kotlinx-coroutines-quasar')
 module('integration/kotlinx-coroutines-slf4j')
+module('integration/kotlinx-coroutines-play-services')
 
 module('reactive/kotlinx-coroutines-reactive')
 module('reactive/kotlinx-coroutines-reactor')
diff --git a/site/docs/index.md b/site/docs/index.md
index 58a42d7..74e9b7e 100644
--- a/site/docs/index.md
+++ b/site/docs/index.md
@@ -10,20 +10,19 @@
 
 ## Modules
 
-| Name                                                       | Description                                      |
-| ---------------------------------------------------------- | ------------------------------------------------ |
-| [kotlinx-coroutines-core](kotlinx-coroutines-core)         | Core primitives to work with coroutines          |
-| [kotlinx-coroutines-reactive](kotlinx-coroutines-reactive) | Utilities for [Reactive Streams](http://www.reactive-streams.org) |
-| [kotlinx-coroutines-reactor](kotlinx-coroutines-reactor)   | Utilities for [Reactor](https://projectreactor.io) |
-| [kotlinx-coroutines-rx2](kotlinx-coroutines-rx2)           | Utilities for [RxJava 2.x](https://github.com/ReactiveX/RxJava) |
-| [kotlinx-coroutines-android](kotlinx-coroutines-android)   | `UI` context for Android applications |
-| [kotlinx-coroutines-javafx](kotlinx-coroutines-javafx)     | `JavaFx` context for JavaFX UI applications |
-| [kotlinx-coroutines-swing](kotlinx-coroutines-swing)       | `Swing` context for Swing UI applications |
-| [kotlinx-coroutines-jdk8](kotlinx-coroutines-jdk8)         | Integration with JDK8 `CompletableFuture` (Android API level 24) |
-| [kotlinx-coroutines-nio](kotlinx-coroutines-nio)           | Integration with asynchronous IO on JDK7+ (Android O Preview) |
-| [kotlinx-coroutines-guava](kotlinx-coroutines-guava)       | Integration with Guava [ListenableFuture](https://github.com/google/guava/wiki/ListenableFutureExplained) |
-| [kotlinx-coroutines-quasar](kotlinx-coroutines-quasar)     | Integration with [Quasar](http://docs.paralleluniverse.co/quasar/) |
-| [kotlinx-coroutines-slf4j](kotlinx-coroutines-slf4j)       | Integration with SLF4J [MDC](https://logback.qos.ch/manual/mdc.html) |
+| Name                                                                 | Description                                      |
+| ----------------------------------------------------------           | ------------------------------------------------ |
+| [kotlinx-coroutines-core](kotlinx-coroutines-core)                   | Core primitives to work with coroutines          |
+| [kotlinx-coroutines-reactive](kotlinx-coroutines-reactive)           | Utilities for [Reactive Streams](http://www.reactive-streams.org) |
+| [kotlinx-coroutines-reactor](kotlinx-coroutines-reactor)             | Utilities for [Reactor](https://projectreactor.io) |
+| [kotlinx-coroutines-rx2](kotlinx-coroutines-rx2)                     | Utilities for [RxJava 2.x](https://github.com/ReactiveX/RxJava) |
+| [kotlinx-coroutines-android](kotlinx-coroutines-android)             | `UI` context for Android applications |
+| [kotlinx-coroutines-javafx](kotlinx-coroutines-javafx)               | `JavaFx` context for JavaFX UI applications |
+| [kotlinx-coroutines-swing](kotlinx-coroutines-swing)                 | `Swing` context for Swing UI applications |
+| [kotlinx-coroutines-jdk8](kotlinx-coroutines-jdk8)                   | Integration with JDK8 `CompletableFuture` (Android API level 24) |
+| [kotlinx-coroutines-guava](kotlinx-coroutines-guava)                 | Integration with Guava [ListenableFuture](https://github.com/google/guava/wiki/ListenableFutureExplained) |
+| [kotlinx-coroutines-slf4j](kotlinx-coroutines-slf4j)                 | Integration with SLF4J [MDC](https://logback.qos.ch/manual/mdc.html) |
+| [kotlinx-coroutines-play-services](kotlinx-coroutines-play-services) | Integration with Google Play Services [Tasks API](https://developers.google.com/android/guides/tasks) |
 
 ## Examples
 
diff --git a/ui/coroutines-guide-ui.md b/ui/coroutines-guide-ui.md
index be1e214..5eae387 100644
--- a/ui/coroutines-guide-ui.md
+++ b/ui/coroutines-guide-ui.md
@@ -339,7 +339,7 @@
 
 Try clicking repeatedly on a circle in this version of the code. The clicks are just ignored while the countdown 
 animation is running. This happens because the actor is busy with an animation and does not receive from its channel.
-By default, an actor's mailbox is backed by [RendezvousChannel], whose `offer` operation succeeds only when 
+By default, an actor's mailbox is backed by `RendezvousChannel`, whose `offer` operation succeeds only when 
 the `receive` is active. 
 
 > On Android, there is `View` sent in OnClickListener, so we send the `View` to the actor as a signal. 
@@ -368,7 +368,7 @@
 controls the implementation of the channel that this actor is using for its mailbox. The description of all 
 the available choices is given in documentation of the [`Channel()`][Channel] factory function.
 
-Let us change the code to use [ConflatedChannel] by passing [Channel.CONFLATED] capacity value. The 
+Let us change the code to use `ConflatedChannel` by passing [Channel.CONFLATED] capacity value. The 
 change is only to the line that creates an actor:
 
 ```kotlin
@@ -393,10 +393,10 @@
 
 This is also a desired behaviour for UI applications that have to react to incoming high-frequency
 event streams by updating their UI based on the most recently received update. A coroutine that is using
-[ConflatedChannel] avoids delays that are usually introduced by buffering of events.
+`ConflatedChannel` avoids delays that are usually introduced by buffering of events.
 
 You can experiment with `capacity` parameter in the above line to see how it affects the behaviour of the code.
-Setting `capacity = Channel.UNLIMITED` creates a coroutine with [LinkedListChannel] mailbox that buffers all 
+Setting `capacity = Channel.UNLIMITED` creates a coroutine with `LinkedListChannel` mailbox that buffers all 
 events. In this case, the animation runs as many times as the circle is clicked.
 
 ## Blocking operations
@@ -715,11 +715,8 @@
 [actor]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/actor.html
 [SendChannel.offer]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/offer.html
 [SendChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-send-channel/index.html
-[RendezvousChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-rendezvous-channel/index.html
 [Channel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/index.html
-[ConflatedChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-conflated-channel/index.html
 [Channel.CONFLATED]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-channel/-c-o-n-f-l-a-t-e-d.html
-[LinkedListChannel]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.experimental.channels/-linked-list-channel/index.html
 <!--- MODULE kotlinx-coroutines-javafx -->
 <!--- INDEX kotlinx.coroutines.experimental.javafx -->
 [kotlinx.coroutines.experimental.Dispatchers.JavaFx]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-javafx/kotlinx.coroutines.experimental.javafx/kotlinx.coroutines.experimental.-dispatchers/-java-fx.html
diff --git a/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/Animation.kt b/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/Animation.kt
index 90c83db..3360fd8 100644
--- a/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/Animation.kt
+++ b/ui/kotlinx-coroutines-android/animation-app/app/src/main/java/org/jetbrains/kotlinx/animation/Animation.kt
@@ -11,8 +11,12 @@
 import android.graphics.RectF
 import android.util.AttributeSet
 import android.view.View
+import kotlinx.coroutines.experimental.CoroutineScope
+import kotlinx.coroutines.experimental.Dispatchers
 import kotlinx.coroutines.experimental.Job
-import kotlinx.coroutines.experimental.android.UI
+import kotlinx.coroutines.experimental.android.Main
+import kotlinx.coroutines.experimental.android.awaitFrame
+import kotlinx.coroutines.experimental.cancelChildren
 import kotlinx.coroutines.experimental.launch
 import java.util.*
 
@@ -58,9 +62,11 @@
 
 private val rnd = Random()
 
-class AnimationModel : ViewModel() {
+class AnimationModel : ViewModel(), CoroutineScope {
+
+    override val coroutineContext = Job() + Dispatchers.Main
+
     private val shapes = MutableLiveData<Set<AnimatedShape>>()
-    private val jobs = arrayListOf<Job>()
 
     fun observe(owner: LifecycleOwner, observer: Observer<Set<AnimatedShape>>) =
         shapes.observe(owner, observer)
@@ -71,13 +77,13 @@
     }
 
     fun addAnimation() {
-        jobs += launch(UI) {
+        launch {
             animateShape(if (rnd.nextBoolean()) AnimatedCircle() else AnimatedSquare())
         }
     }
 
     fun clearAnimations() {
-        jobs.forEach { it.cancel() }
+        coroutineContext.cancelChildren()
         shapes.value = NO_SHAPES
     }
 }
@@ -101,7 +107,7 @@
     var time = System.nanoTime() // nanos
     var checkTime = time
     while (true) {
-        val dt = time.let { old -> UI.awaitFrame().also { time = it } - old }
+        val dt = time.let { old -> awaitFrame().also { time = it } - old }
         if (dt > 0.5e9) continue // don't animate through over a half second lapses
         val dx = shape.x - 0.5f
         val dy = shape.y - 0.5f
@@ -121,7 +127,7 @@
             when (rnd.nextInt(20)) { // roll d20
                 0 -> {
                     animateColor(shape) // wait a second & animate color
-                    time = UI.awaitFrame() // and sync with next frame
+                    time = awaitFrame() // and sync with next frame
                 }
                 1 -> { // random speed change
                     sx = rnd.nextSpeed()
@@ -138,7 +144,7 @@
     val aColor = shape.color
     val bColor = rnd.nextColor()
     while (true) {
-        val time = UI.awaitFrame()
+        val time = awaitFrame()
         val b = (time - startTime) / duration
         if (b >= 1.0f) break
         val a = 1 - b
diff --git a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt
index e7129f4..3776d1c 100644
--- a/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt
+++ b/ui/kotlinx-coroutines-android/src/AndroidExceptionPreHandler.kt
@@ -25,7 +25,8 @@
  * @suppress This is an internal impl class.
  */
 @Keep
-class AndroidExceptionPreHandler :
+@InternalCoroutinesApi
+internal class AndroidExceptionPreHandler :
     AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler
 {
     override fun handleException(context: CoroutineContext, exception: Throwable) {
diff --git a/ui/kotlinx-coroutines-android/src/HandlerDispatcher.kt b/ui/kotlinx-coroutines-android/src/HandlerDispatcher.kt
index dcd3e15..88f14c4 100644
--- a/ui/kotlinx-coroutines-android/src/HandlerDispatcher.kt
+++ b/ui/kotlinx-coroutines-android/src/HandlerDispatcher.kt
@@ -11,14 +11,13 @@
 import android.view.*
 import kotlinx.coroutines.experimental.*
 import java.lang.reflect.Constructor
-import java.util.concurrent.*
 import kotlin.coroutines.experimental.*
 
 /**
  * Dispatches execution onto Android main thread and provides native [delay][Delay.delay] support.
  */
 public val Dispatchers.Main: HandlerDispatcher
-    get() = mainDispatcher
+    get() = kotlinx.coroutines.experimental.android.Main
 
 /**
  * Dispatches execution onto Android [Handler].
@@ -30,19 +29,23 @@
      * Returns dispatcher that executes coroutines immediately when it is already in the right handler context
      * (current looper is the same as this handler's looper). See [isDispatchNeeded] documentation on
      * why this should not be done by default.
+     *
+     * **Note: This is an experimental api.** Semantics of this dispatcher may change in the future.
      */
+    @ExperimentalCoroutinesApi
     public abstract val immediate: HandlerDispatcher
 }
 
 /**
  * Represents an arbitrary [Handler] as a implementation of [CoroutineDispatcher].
  */
+@JvmName("from") // this is for a nice Java API, see issue #255
 public fun Handler.asCoroutineDispatcher(): HandlerDispatcher =
     HandlerContext(this)
 
 private const val MAX_DELAY = Long.MAX_VALUE / 2 // cannot delay for too long on Android
 
-private val mainHandler = Looper.getMainLooper().asHandler(async = true)
+internal val mainHandler = Looper.getMainLooper().asHandler(async = true)
 
 @VisibleForTesting
 internal fun Looper.asHandler(async: Boolean): Handler {
@@ -68,7 +71,8 @@
     return constructor.newInstance(this, null, true)
 }
 
-private val mainDispatcher = HandlerContext(mainHandler, "Main")
+@JvmField // this is for a nice Java API, see issue #255
+internal val Main: HandlerDispatcher = HandlerContext(mainHandler, "Main")
 
 /**
  * Implements [CoroutineDispatcher] on top of an arbitrary Android [Handler].
@@ -109,14 +113,14 @@
         handler.post(block)
     }
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
         handler.postDelayed({
             with(continuation) { resumeUndispatched(Unit) }
-        }, unit.toMillis(time).coerceAtMost(MAX_DELAY))
+        }, timeMillis.coerceAtMost(MAX_DELAY))
     }
 
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
-        handler.postDelayed(block, unit.toMillis(time).coerceAtMost(MAX_DELAY))
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
+        handler.postDelayed(block, timeMillis.coerceAtMost(MAX_DELAY))
         return object : DisposableHandle {
             override fun dispose() {
                 handler.removeCallbacks(block)
@@ -171,6 +175,6 @@
 
 private fun postFrameCallback(choreographer: Choreographer, cont: CancellableContinuation<Long>) {
     choreographer.postFrameCallback { nanos ->
-        with(cont) { mainDispatcher.resumeUndispatched(nanos) }
+        with(cont) { Main.resumeUndispatched(nanos) }
     }
 }
diff --git a/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt b/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt
index cbeba40..4d40345 100644
--- a/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt
+++ b/ui/kotlinx-coroutines-javafx/src/JavaFxDispatcher.kt
@@ -9,7 +9,6 @@
 import javafx.event.*
 import javafx.util.*
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.javafx.JavaFx.delay
 import java.util.concurrent.*
 import kotlin.coroutines.experimental.*
 
@@ -24,8 +23,7 @@
  *
  * This class provides type-safety and a point for future extensions.
  */
-public sealed class JavaFxDispatcher : CoroutineDispatcher(), Delay {
-}
+public sealed class JavaFxDispatcher : CoroutineDispatcher(), Delay
 
 /**
  * Dispatches execution onto JavaFx application thread and provides native [delay] support.
@@ -37,7 +35,7 @@
         imports = ["kotlinx.coroutines.experimental.Dispatchers", "kotlinx.coroutines.experimental.javafx.JavaFx"])
 )
 // todo: it will become an internal implementation object
-object JavaFx : JavaFxDispatcher(), Delay {
+object JavaFx : JavaFxDispatcher() {
     init {
         // :kludge: to make sure Toolkit is initialized if we use JavaFx dispatcher outside of JavaFx app
         initPlatform()
@@ -59,15 +57,15 @@
     suspend fun awaitPulse(): Long =
         kotlinx.coroutines.experimental.javafx.awaitPulse()
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
-        val timeline = schedule(time, unit, EventHandler {
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
+        val timeline = schedule(timeMillis, TimeUnit.MILLISECONDS, EventHandler {
             with(continuation) { resumeUndispatched(Unit) }
         })
         continuation.invokeOnCancellation { timeline.stop() }
     }
 
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
-        val timeline = schedule(time, unit, EventHandler {
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
+        val timeline = schedule(timeMillis, TimeUnit.MILLISECONDS, EventHandler {
             block.run()
         })
         return object : DisposableHandle {
@@ -90,7 +88,7 @@
 /**
  * Suspends coroutine until next JavaFx pulse and returns time of the pulse on resumption.
  * If the [Job] of the current coroutine is completed while this suspending function is waiting, this function
- * immediately resumes with [CancellationException] .
+ * immediately resumes with [CancellationException][kotlinx.coroutines.experimental.CancellationException].
  */
 public suspend fun awaitPulse(): Long = suspendCancellableCoroutine { cont ->
     pulseTimer.onNext(cont)
diff --git a/ui/kotlinx-coroutines-swing/src/SwingDispatcher.kt b/ui/kotlinx-coroutines-swing/src/SwingDispatcher.kt
index 8ee7761..a78e2ed 100644
--- a/ui/kotlinx-coroutines-swing/src/SwingDispatcher.kt
+++ b/ui/kotlinx-coroutines-swing/src/SwingDispatcher.kt
@@ -5,7 +5,6 @@
 package kotlinx.coroutines.experimental.swing
 
 import kotlinx.coroutines.experimental.*
-import kotlinx.coroutines.experimental.swing.Swing.delay
 import java.awt.event.*
 import java.util.concurrent.*
 import javax.swing.*
@@ -34,18 +33,18 @@
         imports = ["kotlinx.coroutines.experimental.Dispatchers", "kotlinx.coroutines.experimental.swing.Swing"])
 )
 // todo: it will become an internal implementation object
-object Swing : SwingDispatcher(), Delay {
+object Swing : SwingDispatcher() {
     override fun dispatch(context: CoroutineContext, block: Runnable) = SwingUtilities.invokeLater(block)
 
-    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
-        val timer = schedule(time, unit, ActionListener {
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) {
+        val timer = schedule(timeMillis, TimeUnit.MILLISECONDS, ActionListener {
             with(continuation) { resumeUndispatched(Unit) }
         })
         continuation.invokeOnCancellation { timer.stop() }
     }
 
-    override fun invokeOnTimeout(time: Long, unit: TimeUnit, block: Runnable): DisposableHandle {
-        val timer = schedule(time, unit, ActionListener {
+    override fun invokeOnTimeout(timeMillis: Long, block: Runnable): DisposableHandle {
+        val timer = schedule(timeMillis, TimeUnit.MILLISECONDS, ActionListener {
             block.run()
         })
         return object : DisposableHandle {