Merge branch 'master' into develop
diff --git a/common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt b/common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt
index c3eda77..be12640 100644
--- a/common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt
+++ b/common/kotlinx-coroutines-core-common/src/Dispatchers.common.kt
@@ -9,7 +9,7 @@
 /**
  * Groups various implementations of [CoroutineDispatcher].
  */
-expect object Dispatchers {
+public expect object Dispatchers {
     /**
      * The default [CoroutineDispatcher] that is used by all standard builders like
      * [launch][CoroutineScope.launch], [async][CoroutineScope.async], etc
diff --git a/core/kotlinx-coroutines-core/src/Dispatchers.kt b/core/kotlinx-coroutines-core/src/Dispatchers.kt
index 50396a9..a79a219 100644
--- a/core/kotlinx-coroutines-core/src/Dispatchers.kt
+++ b/core/kotlinx-coroutines-core/src/Dispatchers.kt
@@ -19,15 +19,7 @@
 /**
  * Groups various implementations of [CoroutineDispatcher].
  */
-actual object Dispatchers {
-
-    private val mainDispatcher = loadMainDispatcher()
-
-    private fun loadMainDispatcher(): MainCoroutineDispatcher? {
-        return MainDispatcherFactory::class.java.let { clz ->
-            ServiceLoader.load(clz, clz.classLoader).toList()
-        }.maxBy { it.loadPriority }?.createDispatcher()
-    }
+public actual object Dispatchers {
 
     /**
      * The default [CoroutineDispatcher] that is used by all standard builders like
@@ -59,8 +51,7 @@
      * Implementation note: [MainCoroutineDispatcher.immediate] is not supported on Native and JS platforms.
      */
     @JvmStatic
-    public actual val Main: MainCoroutineDispatcher get() = mainDispatcher ?: error("Module with Main dispatcher is missing. " +
-            "Add dependency with required Main dispatcher, e.g. 'kotlinx-coroutines-android'")
+    public actual val Main: MainCoroutineDispatcher get() = MainDispatcherLoader.dispatcher
 
     /**
      * A coroutine dispatcher that is not confined to any specific thread.
@@ -97,3 +88,47 @@
     @JvmStatic
     public val IO: CoroutineDispatcher = DefaultScheduler.IO
 }
+
+// Lazy loader for the main dispatcher
+private object MainDispatcherLoader {
+    @JvmField
+    val dispatcher: MainCoroutineDispatcher =
+        MainDispatcherFactory::class.java.let { clz ->
+            ServiceLoader.load(clz, clz.classLoader).toList()
+        }.maxBy { it.loadPriority }?.tryCreateDispatcher() ?: MissingMainCoroutineDispatcher(null)
+
+    /**
+     * If anything goes wrong while trying to create main dispatcher (class not found,
+     * initialization failed, etc), then replace the main dispatcher with a special
+     * stub that throws an error message on any attempt to actually use it.
+     */
+    private fun MainDispatcherFactory.tryCreateDispatcher(): MainCoroutineDispatcher =
+        try {
+            createDispatcher()
+        } catch (cause: Throwable) {
+            MissingMainCoroutineDispatcher(cause)
+        }
+}
+
+private class MissingMainCoroutineDispatcher(val cause: Throwable?) : MainCoroutineDispatcher(), Delay {
+    override val immediate: MainCoroutineDispatcher get() = this
+
+    override fun dispatch(context: CoroutineContext, block: Runnable) =
+        missing()
+
+    override fun scheduleResumeAfterDelay(timeMillis: Long, continuation: CancellableContinuation<Unit>) =
+        missing()
+
+    private fun missing() {
+        if  (cause == null) {
+            throw IllegalStateException(
+                "Module with the Main dispatcher is missing. " +
+                    "Add dependency providing the Main dispatcher, e.g. 'kotlinx-coroutines-android'"
+            )
+        } else {
+            throw IllegalStateException("Module with the Main dispatcher had failed to initialize", cause)
+        }
+    }
+
+    override fun toString(): String = "Main[missing${if (cause != null) ", cause=$cause" else ""}]"
+}
\ No newline at end of file
diff --git a/core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt b/core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt
index 6a56396..37f17b9 100644
--- a/core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt
+++ b/core/kotlinx-coroutines-core/src/ThreadPoolDispatcher.kt
@@ -14,8 +14,19 @@
  * **NOTE: The resulting [ExecutorCoroutineDispatcher] owns native resources (its thread).
  * Resources are reclaimed by [ExecutorCoroutineDispatcher.close].**
  *
+ * **NOTE: This API will be replaced in the future**. A different API to create thread-limited thread pools
+ * that is based on a shared thread-pool and does not require the resulting dispatcher to be explicitly closed
+ * will be provided, thus avoiding potential thread leaks and also significantly improving performance, due
+ * to coroutine-oriented scheduling policy and thread-switch minimization.
+ * See [issue #261](https://github.com/Kotlin/kotlinx.coroutines/issues/261) for details.
+ * If you need a completely separate thread-pool with scheduling policy that is based on the standard
+ * JDK executors, use the following expression:
+ * `Executors.newSingleThreadExecutor().asCoroutineDispatcher()`.
+ * See [Executor.asCoroutineDispatcher] for details.
+ *
  * @param name the base name of the created thread.
  */
+@ObsoleteCoroutinesApi
 fun newSingleThreadContext(name: String): ExecutorCoroutineDispatcher =
     newFixedThreadPoolContext(1, name)
 
@@ -40,9 +51,20 @@
  * **NOTE: The resulting [ExecutorCoroutineDispatcher] owns native resources (its threads).
  * Resources are reclaimed by [ExecutorCoroutineDispatcher.close].**
  *
+ * **NOTE: This API will be replaced in the future**. A different API to create thread-limited thread pools
+ * that is based on a shared thread-pool and does not require the resulting dispatcher to be explicitly closed
+ * will be provided, thus avoiding potential thread leaks and also significantly improving performance, due
+ * to coroutine-oriented scheduling policy and thread-switch minimization.
+ * See [issue #261](https://github.com/Kotlin/kotlinx.coroutines/issues/261) for details.
+ * If you need a completely separate thread-pool with scheduling policy that is based on the standard
+ * JDK executors, use the following expression:
+ * `Executors.newFixedThreadPool().asCoroutineDispatcher()`.
+ * See [Executor.asCoroutineDispatcher] for details.
+ *
  * @param nThreads the number of threads.
  * @param name the base name of the created threads.
  */
+@ObsoleteCoroutinesApi
 fun newFixedThreadPoolContext(nThreads: Int, name: String): ExecutorCoroutineDispatcher {
     require(nThreads >= 1) { "Expected at least one thread, but $nThreads specified" }
     return ThreadPoolDispatcher(nThreads, name)
diff --git a/core/kotlinx-coroutines-core/src/scheduling/Dispatcher.kt b/core/kotlinx-coroutines-core/src/scheduling/Dispatcher.kt
index 7a718f5..7e359fb 100644
--- a/core/kotlinx-coroutines-core/src/scheduling/Dispatcher.kt
+++ b/core/kotlinx-coroutines-core/src/scheduling/Dispatcher.kt
@@ -20,6 +20,11 @@
     override fun close() {
         throw UnsupportedOperationException("$DEFAULT_SCHEDULER_NAME cannot be closed")
     }
+
+    override fun toString(): String = DEFAULT_SCHEDULER_NAME
+
+    @InternalCoroutinesApi
+    fun toDebugString(): String = super.toString()
 }
 
 /**
diff --git a/gradle/atomicfu-common.gradle b/gradle/atomicfu-common.gradle
index 9a55e17..236fbfd 100644
--- a/gradle/atomicfu-common.gradle
+++ b/gradle/atomicfu-common.gradle
@@ -3,5 +3,5 @@
  */
 
 dependencies {
-    compile "org.jetbrains.kotlinx:atomicfu-common:$atomicFU_version"
+    compileOnly "org.jetbrains.kotlinx:atomicfu-common:$atomicFU_version"
 }
\ No newline at end of file
diff --git a/js/kotlinx-coroutines-core-js/src/Dispatchers.kt b/js/kotlinx-coroutines-core-js/src/Dispatchers.kt
index 8679199..6a0a776 100644
--- a/js/kotlinx-coroutines-core-js/src/Dispatchers.kt
+++ b/js/kotlinx-coroutines-core-js/src/Dispatchers.kt
@@ -6,7 +6,7 @@
 
 import kotlin.coroutines.experimental.*
 
-actual object Dispatchers {
+public actual object Dispatchers {
 
     public actual val Default: CoroutineDispatcher = createDefaultDispatcher()
 
diff --git a/native/kotlinx-coroutines-core-native/src/Dispatchers.kt b/native/kotlinx-coroutines-core-native/src/Dispatchers.kt
index 759743c..ba86913 100644
--- a/native/kotlinx-coroutines-core-native/src/Dispatchers.kt
+++ b/native/kotlinx-coroutines-core-native/src/Dispatchers.kt
@@ -6,8 +6,7 @@
 
 import kotlin.coroutines.experimental.*
 
-
-actual object Dispatchers {
+public actual object Dispatchers {
 
     public actual val Default: CoroutineDispatcher = createDefaultDispatcher()