actors moved from stdlib to example
This commit is contained in:
+62
-78
@@ -76,16 +76,7 @@
|
||||
<file leaf-file-name="Actors.kt" pinned="false" current="true" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/src/org/jetbrains/examples/actors/Actors.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="2" column="37" selection-start="62" selection-end="62" vertical-scroll-proportion="-0.550152">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="Actors.kt" pinned="false" current="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/../../stdlib/ktSrc/concurrent/Actors.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="2" column="43" selection-start="47" selection-end="47" vertical-scroll-proportion="0.0">
|
||||
<state line="130" column="0" selection-start="4054" selection-end="4054" vertical-scroll-proportion="0.9736434">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
@@ -179,8 +170,8 @@
|
||||
<option value="$PROJECT_DIR$/../../stdlib/ktSrc/JavaLang.kt" />
|
||||
<option value="$PROJECT_DIR$/../../stdlib/ktSrc/concurrent/Thread.kt" />
|
||||
<option value="$PROJECT_DIR$/src/org/jetbrains/examples/actors/Sample.kt" />
|
||||
<option value="$PROJECT_DIR$/src/org/jetbrains/examples/actors/Actors.kt" />
|
||||
<option value="$PROJECT_DIR$/../../stdlib/ktSrc/concurrent/Actors.kt" />
|
||||
<option value="$PROJECT_DIR$/src/org/jetbrains/examples/actors/Actors.kt" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
@@ -216,26 +207,6 @@
|
||||
<sortByType />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="PackagesPane">
|
||||
<subPane>
|
||||
<PATH>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="example-actors" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope">
|
||||
<subPane subId="Project Files">
|
||||
<PATH>
|
||||
<PATH_ELEMENT USER_OBJECT="Root">
|
||||
<option name="myItemId" value="" />
|
||||
<option name="myItemType" value="" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<PATH>
|
||||
@@ -348,20 +319,40 @@
|
||||
</PATH>
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="PackagesPane">
|
||||
<subPane>
|
||||
<PATH>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="example-actors" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PackageViewProjectNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope">
|
||||
<subPane subId="Project Files">
|
||||
<PATH>
|
||||
<PATH_ELEMENT USER_OBJECT="Root">
|
||||
<option name="myItemId" value="" />
|
||||
<option name="myItemType" value="" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
</subPane>
|
||||
</pane>
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="project.structure.last.edited" value="Modules" />
|
||||
<property name="GoToFile.includeJavaFiles" value="false" />
|
||||
<property name="project.structure.proportion" value="0.0" />
|
||||
<property name="project.structure.last.edited" value="Modules" />
|
||||
<property name="GoToClass.toSaveIncludeLibraries" value="false" />
|
||||
<property name="recentsLimit" value="5" />
|
||||
<property name="project.structure.proportion" value="0.0" />
|
||||
<property name="MemberChooser.sorted" value="false" />
|
||||
<property name="recentsLimit" value="5" />
|
||||
<property name="MemberChooser.showClasses" value="true" />
|
||||
<property name="project.structure.side.proportion" value="0.0" />
|
||||
<property name="GoToClass.includeLibraries" value="false" />
|
||||
<property name="dynamic.classpath" value="false" />
|
||||
<property name="project.structure.side.proportion" value="0.0" />
|
||||
<property name="MemberChooser.copyJavadoc" value="false" />
|
||||
<property name="dynamic.classpath" value="false" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
@@ -429,24 +420,6 @@
|
||||
<option name="Maven.BeforeRunTask" enabled="false" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="Applet" factoryName="Applet">
|
||||
<module name="" />
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="HTML_FILE_NAME" />
|
||||
<option name="HTML_USED" value="false" />
|
||||
<option name="WIDTH" value="400" />
|
||||
<option name="HEIGHT" value="300" />
|
||||
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" />
|
||||
<method>
|
||||
<option name="AntTarget" enabled="false" />
|
||||
<option name="BuildArtifacts" enabled="false" />
|
||||
<option name="Make" enabled="true" />
|
||||
<option name="Maven.BeforeRunTask" enabled="false" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="TestNG" factoryName="TestNG">
|
||||
<module name="" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
@@ -479,6 +452,24 @@
|
||||
<option name="Maven.BeforeRunTask" enabled="false" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="Applet" factoryName="Applet">
|
||||
<module name="" />
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="HTML_FILE_NAME" />
|
||||
<option name="HTML_USED" value="false" />
|
||||
<option name="WIDTH" value="400" />
|
||||
<option name="HEIGHT" value="300" />
|
||||
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" />
|
||||
<method>
|
||||
<option name="AntTarget" enabled="false" />
|
||||
<option name="BuildArtifacts" enabled="false" />
|
||||
<option name="Make" enabled="true" />
|
||||
<option name="Maven.BeforeRunTask" enabled="false" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration default="true" type="Application" factoryName="Application">
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
@@ -560,7 +551,7 @@
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="1" y="22" width="1411" height="826" extended-state="0" />
|
||||
<editor active="false" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
@@ -576,7 +567,7 @@
|
||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3294204" sideWeight="0.21782178" order="1" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.3294204" sideWeight="0.67043847" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.3294204" sideWeight="0.67043847" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32956153" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="ResolveWindow" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3294204" sideWeight="0.67043847" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
||||
@@ -673,6 +664,20 @@
|
||||
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../stdlib/ktSrc/JavaCollections.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../stdlib/ktSrc/JavaUtil.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../stdlib/ktSrc/concurrent/FunctionalQueue.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" />
|
||||
@@ -703,30 +708,9 @@
|
||||
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" />
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../stdlib/ktSrc/JavaCollections.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../stdlib/ktSrc/JavaUtil.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../stdlib/ktSrc/concurrent/Actors.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="2" column="43" selection-start="47" selection-end="47" vertical-scroll-proportion="0.0">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/org/jetbrains/examples/actors/Actors.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state line="2" column="37" selection-start="62" selection-end="62" vertical-scroll-proportion="-0.550152">
|
||||
<state line="130" column="0" selection-start="4054" selection-end="4054" vertical-scroll-proportion="0.9736434">
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
|
||||
@@ -7,6 +7,127 @@ import java.util.concurrent.*
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||
import java.util.Date
|
||||
|
||||
/*
|
||||
Message handling class which process only one message at any given moment
|
||||
|
||||
Three main ways to use it
|
||||
- post and forget
|
||||
- post and await result
|
||||
- post and assign callback to be called when message processed
|
||||
*/
|
||||
abstract class Actor(protected val executor: Executor) {
|
||||
// we can not do it private or protected
|
||||
// otherwise updater defined in class object will not be able to access it
|
||||
volatile var queue : FunctionalQueue<Any> = emptyQueue
|
||||
|
||||
/*
|
||||
Handle message and return result
|
||||
This method guaranteed to be executed only one per object at any given time
|
||||
*/
|
||||
protected abstract fun onMessage(message: Any) : Any?
|
||||
|
||||
/*
|
||||
Post message to the actor.
|
||||
The method returns immediately and the message itself will be processed later
|
||||
*/
|
||||
fun post(message: Any) {
|
||||
while(true) {
|
||||
val q = queue
|
||||
if(q.empty) {
|
||||
if(queueUpdater.compareAndSet(this, q, busyEmptyQueue)) {
|
||||
executor.execute { process(message) }
|
||||
break
|
||||
}
|
||||
}
|
||||
else {
|
||||
val newQueue = (if(q == busyEmptyQueue) emptyQueue else q) add message
|
||||
if(queueUpdater.compareAndSet(this, q, newQueue)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Post message to the actor and schedule callback to be executed on given executor when message processed
|
||||
*/
|
||||
fun post(message: Any, executor: Executor = this.executor, callback: (Any?)->Unit) =
|
||||
post(Callback(message, executor, callback))
|
||||
|
||||
/*
|
||||
Send message to the actor and await result
|
||||
*/
|
||||
fun send(message: Any) : Any? {
|
||||
val request = Request(message)
|
||||
post(request)
|
||||
request.await()
|
||||
return request.result
|
||||
}
|
||||
|
||||
private fun nextMessage() {
|
||||
while(true) {
|
||||
val q = queue
|
||||
if(q == busyEmptyQueue) {
|
||||
if(queueUpdater.compareAndSet(this, busyEmptyQueue, emptyQueue)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
val removed = q.removeFirst()
|
||||
val newQueue = if(removed._2.empty) busyEmptyQueue else removed._2
|
||||
if(queueUpdater.compareAndSet(this, q, newQueue)) {
|
||||
executor.execute { process(removed._1) }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun process(message: Any) {
|
||||
when(message) {
|
||||
is Request -> {
|
||||
message.result = onMessage(message.message)
|
||||
message.countDown()
|
||||
}
|
||||
is Callback -> {
|
||||
val result = onMessage(message.message)
|
||||
message.executor execute {
|
||||
val callback = message.callback;
|
||||
callback(result)
|
||||
}
|
||||
}
|
||||
else -> onMessage(message)
|
||||
}
|
||||
|
||||
nextMessage()
|
||||
}
|
||||
|
||||
/*
|
||||
Create actor on the same executor
|
||||
*/
|
||||
fun actor(handler: (Any)->Any?) = executor.actor(handler)
|
||||
|
||||
class object {
|
||||
val queueUpdater = AtomicReferenceFieldUpdater.newUpdater(typeinfo<Actor>.javaClassForType,typeinfo<FunctionalQueue<Any>>().javaClassForType, "queue").sure()
|
||||
val emptyQueue = FunctionalQueue<Any>()
|
||||
val busyEmptyQueue = FunctionalQueue<Any>() add "busy empty queue"
|
||||
|
||||
class Request(val message: Any) : java.util.concurrent.CountDownLatch(1) {
|
||||
var result: Any? = null
|
||||
}
|
||||
|
||||
class Callback(val message: Any, val executor: Executor, val callback: (Any?) -> Unit)
|
||||
}
|
||||
}
|
||||
|
||||
fun Executor.actor(handler: (Any)->Any?) : Actor = object: Actor(this) {
|
||||
override fun onMessage(message: Any) {
|
||||
handler(message)
|
||||
}
|
||||
}
|
||||
|
||||
fun singleThreadActor(handler: (Any)->Any?) : Actor = Executors.newSingleThreadExecutor().sure().actor(handler)
|
||||
|
||||
class App() : Actor(Executors.newFixedThreadPool(10).sure()) {
|
||||
private val logger = executor.actor { message ->
|
||||
println("${Date()}:\t\t$message")
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
package std.concurrent
|
||||
|
||||
import std.concurrent.*
|
||||
import std.util.*
|
||||
|
||||
import java.util.concurrent.*
|
||||
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
|
||||
import java.util.Date
|
||||
|
||||
/*
|
||||
Message handling class which process only one message at any given moment
|
||||
|
||||
Three main ways to use it
|
||||
- post and forget
|
||||
- post and await result
|
||||
- post and assign callback when message processed
|
||||
*/
|
||||
abstract class Actor(protected val executor: Executor) {
|
||||
// we can not do it private or protected
|
||||
// otherwise updater defined in class object will not be able to access it
|
||||
volatile var queue : FunctionalQueue<Any> = emptyQueue
|
||||
|
||||
/*
|
||||
Handle message and return result
|
||||
This method guaranteed to be executed only one per object at any given time
|
||||
*/
|
||||
protected abstract fun onMessage(message: Any) : Any?
|
||||
|
||||
/*
|
||||
Post message to the actor.
|
||||
The method returns immediately and the message itself will be processed later
|
||||
*/
|
||||
fun post(message: Any) {
|
||||
while(true) {
|
||||
val q = queue
|
||||
if(q.empty) {
|
||||
if(queueUpdater.compareAndSet(this, q, busyEmptyQueue)) {
|
||||
executor.execute { process(message) }
|
||||
break
|
||||
}
|
||||
}
|
||||
else {
|
||||
val newQueue = (if(q == busyEmptyQueue) emptyQueue else q) add message
|
||||
if(queueUpdater.compareAndSet(this, q, newQueue)) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Post message to the actor and schedule callback to be executed on given executor when message processed
|
||||
*/
|
||||
fun post(message: Any, executor: Executor = this.executor, callback: (Any?)->Unit) =
|
||||
post(Callback(message, executor, callback))
|
||||
|
||||
/*
|
||||
Send message to the actor and await result
|
||||
*/
|
||||
fun send(message: Any) : Any? {
|
||||
val request = Request(message)
|
||||
post(request)
|
||||
request.await()
|
||||
return request.result
|
||||
}
|
||||
|
||||
private fun nextMessage() {
|
||||
while(true) {
|
||||
val q = queue
|
||||
if(q == busyEmptyQueue) {
|
||||
if(queueUpdater.compareAndSet(this, busyEmptyQueue, emptyQueue)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
val removed = q.removeFirst()
|
||||
val newQueue = if(removed._2.empty) busyEmptyQueue else removed._2
|
||||
if(queueUpdater.compareAndSet(this, q, newQueue)) {
|
||||
executor.execute { process(removed._1) }
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun process(message: Any) {
|
||||
when(message) {
|
||||
is Request -> {
|
||||
message.result = onMessage(message.message)
|
||||
message.countDown()
|
||||
}
|
||||
is Callback -> {
|
||||
val result = onMessage(message.message)
|
||||
message.executor execute {
|
||||
val callback = message.callback;
|
||||
callback(result)
|
||||
}
|
||||
}
|
||||
else -> onMessage(message)
|
||||
}
|
||||
|
||||
nextMessage()
|
||||
}
|
||||
|
||||
/*
|
||||
Create actor on the same executor
|
||||
*/
|
||||
fun actor(handler: (Any)->Any?) = executor.actor(handler)
|
||||
|
||||
class object {
|
||||
val queueUpdater = AtomicReferenceFieldUpdater.newUpdater(typeinfo<Actor>.javaClassForType,typeinfo<FunctionalQueue<Any>>().javaClassForType, "queue").sure()
|
||||
val emptyQueue = FunctionalQueue<Any>()
|
||||
val busyEmptyQueue = FunctionalQueue<Any>() add "busy empty queue"
|
||||
|
||||
class Request(val message: Any) : java.util.concurrent.CountDownLatch(1) {
|
||||
var result: Any? = null
|
||||
}
|
||||
|
||||
class Callback(val message: Any, val executor: Executor, val callback: (Any?) -> Unit)
|
||||
}
|
||||
}
|
||||
|
||||
fun Executor.actor(handler: (Any)->Any?) : Actor = object: Actor(this) {
|
||||
override fun onMessage(message: Any) {
|
||||
handler(message)
|
||||
}
|
||||
}
|
||||
|
||||
fun singleThreadActor(handler: (Any)->Any?) : Actor = Executors.newSingleThreadExecutor().sure().actor(handler)
|
||||
|
||||
Reference in New Issue
Block a user