Quasar integration
diff --git a/integration/README.md b/integration/README.md
index 8349cd0..9845b07 100644
--- a/integration/README.md
+++ b/integration/README.md
@@ -7,6 +7,7 @@
 * [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/).
 
 ## Contributing
 
diff --git a/integration/kotlinx-coroutines-quasar/README.md b/integration/kotlinx-coroutines-quasar/README.md
new file mode 100644
index 0000000..99fd973
--- /dev/null
+++ b/integration/kotlinx-coroutines-quasar/README.md
@@ -0,0 +1,36 @@
+# 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/pom.xml b/integration/kotlinx-coroutines-quasar/pom.xml
new file mode 100644
index 0000000..4666ad0
--- /dev/null
+++ b/integration/kotlinx-coroutines-quasar/pom.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016-2017 JetBrains s.r.o.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.jetbrains.kotlinx</groupId>
+        <artifactId>kotlinx-coroutines</artifactId>
+        <version>0.17-SNAPSHOT</version>
+        <relativePath>../../pom.xml</relativePath>
+    </parent>
+
+    <artifactId>kotlinx-coroutines-quasar</artifactId>
+    <packaging>jar</packaging>
+
+    <build>
+        <sourceDirectory>src/main/kotlin</sourceDirectory>
+        <testSourceDirectory>src/test/kotlin</testSourceDirectory>
+
+        <plugins>
+            <plugin>
+                <groupId>org.jetbrains.dokka</groupId>
+                <artifactId>dokka-maven-plugin</artifactId>
+                <version>${dokka.version}</version>
+                <configuration>
+                    <externalDocumentationLinks combine.children="append">
+                        <link>
+                            <url>${core.docs.url}</url>
+                            <packageListUrl>file:///${project.parent.basedir}/kotlinx-coroutines-core/target/dokka/kotlinx-coroutines-core/package-list</packageListUrl>
+                        </link>
+                        <link>
+                            <url>https://google.github.io/guava/releases/18.0/api/docs/</url>
+                        </link>
+                    </externalDocumentationLinks>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>getClasspathFilenames</id>
+                        <goals>
+                            <goal>properties</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <!-- add -Dco.paralleluniverse.fibers.writeInstrumentedClasses=QuasarTest to dump classes -->
+                    <!-- add =v for verbose -->
+                    <argLine>-javaagent:@{co.paralleluniverse:quasar-core:jar}</argLine>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <!-- dependency on coroutines core -->
+        <dependency>
+            <groupId>org.jetbrains.kotlinx</groupId>
+            <artifactId>kotlinx-coroutines-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- coroutines test framework dependency -->
+        <dependency>
+            <groupId>org.jetbrains.kotlinx</groupId>
+            <artifactId>kotlinx-coroutines-core</artifactId>
+            <version>${project.version}</version>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+        <!-- 3rd party dependencies -->
+        <dependency>
+            <groupId>co.paralleluniverse</groupId>
+            <artifactId>quasar-core</artifactId>
+            <version>0.7.9</version>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/integration/kotlinx-coroutines-quasar/src/main/kotlin/kotlinx/coroutines/experimental/quasar/KotlinSuspendableClassifier.kt b/integration/kotlinx-coroutines-quasar/src/main/kotlin/kotlinx/coroutines/experimental/quasar/KotlinSuspendableClassifier.kt
new file mode 100644
index 0000000..40006fd
--- /dev/null
+++ b/integration/kotlinx-coroutines-quasar/src/main/kotlin/kotlinx/coroutines/experimental/quasar/KotlinSuspendableClassifier.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the 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/main/kotlin/kotlinx/coroutines/experimental/quasar/Quasar.kt b/integration/kotlinx-coroutines-quasar/src/main/kotlin/kotlinx/coroutines/experimental/quasar/Quasar.kt
new file mode 100644
index 0000000..a88ef8e
--- /dev/null
+++ b/integration/kotlinx-coroutines-quasar/src/main/kotlin/kotlinx/coroutines/experimental/quasar/Quasar.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the 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.asCoroutineDispatcher
+import kotlinx.coroutines.experimental.cancelFutureOnCompletion
+import kotlinx.coroutines.experimental.suspendCancellableCoroutine
+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.cancelFutureOnCompletion(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 = 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/src/main/resources/META-INF/services/co.paralleluniverse.fibers.instrument.SuspendableClassifier b/integration/kotlinx-coroutines-quasar/src/main/resources/META-INF/services/co.paralleluniverse.fibers.instrument.SuspendableClassifier
new file mode 100644
index 0000000..7d16870
--- /dev/null
+++ b/integration/kotlinx-coroutines-quasar/src/main/resources/META-INF/services/co.paralleluniverse.fibers.instrument.SuspendableClassifier
@@ -0,0 +1 @@
+kotlinx.coroutines.experimental.quasar.KotlinSuspendableClassifier
\ No newline at end of file
diff --git a/integration/kotlinx-coroutines-quasar/src/test/kotlin/kotlinx/coroutines/experimental/quasar/QuasarTest.kt b/integration/kotlinx-coroutines-quasar/src/test/kotlin/kotlinx/coroutines/experimental/quasar/QuasarTest.kt
new file mode 100644
index 0000000..402a880
--- /dev/null
+++ b/integration/kotlinx-coroutines-quasar/src/test/kotlin/kotlinx/coroutines/experimental/quasar/QuasarTest.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2016-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package kotlinx.coroutines.experimental.quasar
+
+import co.paralleluniverse.fibers.Fiber
+import co.paralleluniverse.fibers.SuspendExecution
+import co.paralleluniverse.strands.SuspendableCallable
+import co.paralleluniverse.strands.dataflow.Val
+import guide.test.ignoreLostThreads
+import kotlinx.coroutines.experimental.CompletableDeferred
+import kotlinx.coroutines.experimental.TestBase
+import kotlinx.coroutines.experimental.launch
+import kotlinx.coroutines.experimental.runBlocking
+import org.junit.Before
+import org.junit.Test
+import java.util.concurrent.TimeUnit
+
+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(coroutineContext) {
+            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
+            }
+        }
+        fiber.start()
+        expect(2)
+        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/pom.xml b/pom.xml
index 0912c19..bfc6b3c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -112,6 +112,7 @@
         <module>integration/kotlinx-coroutines-jdk8</module>
         <module>integration/kotlinx-coroutines-nio</module>
         <module>integration/kotlinx-coroutines-guava</module>
+        <module>integration/kotlinx-coroutines-quasar</module>
     </modules>
 
     <dependencies>
diff --git a/site/build.xml b/site/build.xml
index 410a6b3..e67458c 100644
--- a/site/build.xml
+++ b/site/build.xml
@@ -44,6 +44,7 @@
             <fileset dir="../integration/kotlinx-coroutines-jdk8/target/dokka" includes="**/*.md"/>
             <fileset dir="../integration/kotlinx-coroutines-nio/target/dokka" includes="**/*.md"/>
             <fileset dir="../integration/kotlinx-coroutines-guava/target/dokka" includes="**/*.md"/>
+            <fileset dir="../integration/kotlinx-coroutines-quasar/target/dokka" includes="**/*.md"/>
         </copy>
         <antcall target="jekyll"/>
     </target>
diff --git a/site/docs/index.md b/site/docs/index.md
index 02373cc..39057bd 100644
--- a/site/docs/index.md
+++ b/site/docs/index.md
@@ -21,3 +21,4 @@
 [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/)
diff --git a/site/pom.xml b/site/pom.xml
index ce0e03a..4ce3e16 100644
--- a/site/pom.xml
+++ b/site/pom.xml
@@ -84,6 +84,11 @@
             <artifactId>kotlinx-coroutines-guava</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.jetbrains.kotlinx</groupId>
+            <artifactId>kotlinx-coroutines-quasar</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 
     <build>