actors moved from stdlib to example

This commit is contained in:
Alex Tkachman
2012-02-02 13:00:39 +02:00
parent 38817014d5
commit b63fbccba6
3 changed files with 183 additions and 208 deletions
+62 -78
View File
@@ -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")
-130
View File
@@ -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)