fixed TX Vector and TX Ref plus added tests + rewrote Reactor impl + added custom Actor impl(currently not used though)
This commit is contained in:
parent
74bd8dea6d
commit
167b724671
15 changed files with 1148 additions and 274 deletions
485
akka.iws
485
akka.iws
|
|
@ -2,12 +2,14 @@
|
||||||
<project relativePaths="false" version="4">
|
<project relativePaths="false" version="4">
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" name="Default" comment=" # Brief commit desciption here # Full commit description here (comment lines starting with '#' will not be included) ">
|
<list default="true" name="Default" comment=" # Brief commit desciption here # Full commit description here (comment lines starting with '#' will not be included) ">
|
||||||
<change type="DELETED" beforePath="$PROJECT_DIR$/api-java/akka-funtest-java.iml" afterPath="" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java" />
|
||||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka.iml" afterPath="$PROJECT_DIR$/akka.iml" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStateful.java" afterPath="$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStateful.java" />
|
||||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/EventDrivenDispatcher.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/EventDrivenDispatcher.scala" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Future.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Future.scala" />
|
||||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka.ipr" afterPath="$PROJECT_DIR$/akka.ipr" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala" />
|
||||||
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala" />
|
||||||
|
<change type="DELETED" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/EventDrivenDispatcher.scala" afterPath="" />
|
||||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka.iws" afterPath="$PROJECT_DIR$/akka.iws" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/akka.iws" afterPath="$PROJECT_DIR$/akka.iws" />
|
||||||
<change type="DELETED" beforePath="$PROJECT_DIR$/fun-test-java/api-java.iml" afterPath="" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/ThreadBasedDispatcher.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/ThreadBasedDispatcher.scala" />
|
||||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala" />
|
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala" afterPath="$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala" />
|
||||||
</list>
|
</list>
|
||||||
<ignored path="akka.iws" />
|
<ignored path="akka.iws" />
|
||||||
|
|
@ -27,6 +29,73 @@
|
||||||
<disable_hints />
|
<disable_hints />
|
||||||
</component>
|
</component>
|
||||||
<component name="DebuggerManager">
|
<component name="DebuggerManager">
|
||||||
|
<line_breakpoints>
|
||||||
|
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="152" class="Class at State.scala:152" package="">
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
<option name="LOG_ENABLED" value="false" />
|
||||||
|
<option name="LOG_EXPRESSION_ENABLED" value="false" />
|
||||||
|
<option name="SUSPEND_POLICY" value="SuspendAll" />
|
||||||
|
<option name="COUNT_FILTER_ENABLED" value="false" />
|
||||||
|
<option name="COUNT_FILTER" value="0" />
|
||||||
|
<option name="CONDITION_ENABLED" value="false" />
|
||||||
|
<option name="CLASS_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="CONDITION" value="" />
|
||||||
|
<option name="LOG_MESSAGE" value="" />
|
||||||
|
</breakpoint>
|
||||||
|
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="153" class="Class at State.scala:153" package="">
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
<option name="LOG_ENABLED" value="false" />
|
||||||
|
<option name="LOG_EXPRESSION_ENABLED" value="false" />
|
||||||
|
<option name="SUSPEND_POLICY" value="SuspendAll" />
|
||||||
|
<option name="COUNT_FILTER_ENABLED" value="false" />
|
||||||
|
<option name="COUNT_FILTER" value="0" />
|
||||||
|
<option name="CONDITION_ENABLED" value="false" />
|
||||||
|
<option name="CLASS_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="CONDITION" value="" />
|
||||||
|
<option name="LOG_MESSAGE" value="" />
|
||||||
|
</breakpoint>
|
||||||
|
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="157" class="Class at State.scala:157" package="">
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
<option name="LOG_ENABLED" value="false" />
|
||||||
|
<option name="LOG_EXPRESSION_ENABLED" value="false" />
|
||||||
|
<option name="SUSPEND_POLICY" value="SuspendAll" />
|
||||||
|
<option name="COUNT_FILTER_ENABLED" value="false" />
|
||||||
|
<option name="COUNT_FILTER" value="0" />
|
||||||
|
<option name="CONDITION_ENABLED" value="false" />
|
||||||
|
<option name="CLASS_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="CONDITION" value="" />
|
||||||
|
<option name="LOG_MESSAGE" value="" />
|
||||||
|
</breakpoint>
|
||||||
|
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="158" class="Class at State.scala:158" package="">
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
<option name="LOG_ENABLED" value="false" />
|
||||||
|
<option name="LOG_EXPRESSION_ENABLED" value="false" />
|
||||||
|
<option name="SUSPEND_POLICY" value="SuspendAll" />
|
||||||
|
<option name="COUNT_FILTER_ENABLED" value="false" />
|
||||||
|
<option name="COUNT_FILTER" value="0" />
|
||||||
|
<option name="CONDITION_ENABLED" value="false" />
|
||||||
|
<option name="CLASS_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="CONDITION" value="" />
|
||||||
|
<option name="LOG_MESSAGE" value="" />
|
||||||
|
</breakpoint>
|
||||||
|
<breakpoint url="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala" line="155" class="Class at State.scala:155" package="">
|
||||||
|
<option name="ENABLED" value="true" />
|
||||||
|
<option name="LOG_ENABLED" value="false" />
|
||||||
|
<option name="LOG_EXPRESSION_ENABLED" value="false" />
|
||||||
|
<option name="SUSPEND_POLICY" value="SuspendAll" />
|
||||||
|
<option name="COUNT_FILTER_ENABLED" value="false" />
|
||||||
|
<option name="COUNT_FILTER" value="0" />
|
||||||
|
<option name="CONDITION_ENABLED" value="false" />
|
||||||
|
<option name="CLASS_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="INSTANCE_FILTERS_ENABLED" value="false" />
|
||||||
|
<option name="CONDITION" value="" />
|
||||||
|
<option name="LOG_MESSAGE" value="" />
|
||||||
|
</breakpoint>
|
||||||
|
</line_breakpoints>
|
||||||
<breakpoint_any>
|
<breakpoint_any>
|
||||||
<breakpoint>
|
<breakpoint>
|
||||||
<option name="NOTIFY_CAUGHT" value="true" />
|
<option name="NOTIFY_CAUGHT" value="true" />
|
||||||
|
|
@ -87,16 +156,16 @@
|
||||||
<file leaf-file-name="ActiveObject.scala" pinned="false" current="false" current-in-tab="false">
|
<file leaf-file-name="ActiveObject.scala" pinned="false" current="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala">
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state line="222" column="132" selection-start="8013" selection-end="8013" vertical-scroll-proportion="0.0">
|
<state line="112" column="52" selection-start="4116" selection-end="4116" vertical-scroll-proportion="-13.5">
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
<file leaf-file-name="EventDrivenDispatcher.scala" pinned="false" current="false" current-in-tab="false">
|
<file leaf-file-name="ResultOrFailure.scala" pinned="false" current="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/EventDrivenDispatcher.scala">
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ResultOrFailure.scala">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state line="15" column="6" selection-start="502" selection-end="502" vertical-scroll-proportion="0.0">
|
<state line="56" column="6" selection-start="1411" selection-end="1411" vertical-scroll-proportion="0.0">
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
@ -105,21 +174,50 @@
|
||||||
<file leaf-file-name="GenericServer.scala" pinned="false" current="false" current-in-tab="false">
|
<file leaf-file-name="GenericServer.scala" pinned="false" current="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/GenericServer.scala">
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/GenericServer.scala">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state line="25" column="0" selection-start="800" selection-end="800" vertical-scroll-proportion="0.0">
|
<state line="188" column="6" selection-start="6146" selection-end="6146" vertical-scroll-proportion="0.0">
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
<file leaf-file-name="Reactor.scala" pinned="false" current="true" current-in-tab="true">
|
<file leaf-file-name="InMemStateful.java" pinned="false" current="false" current-in-tab="false">
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala">
|
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStateful.java">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state line="13" column="0" selection-start="432" selection-end="432" vertical-scroll-proportion="0.21701603">
|
<state line="52" column="17" selection-start="1441" selection-end="1441" vertical-scroll-proportion="0.0">
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
</file>
|
</file>
|
||||||
|
<file leaf-file-name="State.scala" pinned="false" current="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="158" column="0" selection-start="5462" selection-end="5462" vertical-scroll-proportion="0.0">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="Transaction.scala" pinned="false" current="false" current-in-tab="false">
|
||||||
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="43" column="0" selection-start="1313" selection-end="1313" vertical-scroll-proportion="0.0">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
|
<file leaf-file-name="InMemoryStateTest.java" pinned="false" current="true" current-in-tab="true">
|
||||||
|
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="88" column="46" selection-start="4602" selection-end="4602" vertical-scroll-proportion="0.7783933">
|
||||||
|
<folding>
|
||||||
|
<element signature="imports" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
</file>
|
||||||
</leaf>
|
</leaf>
|
||||||
</component>
|
</component>
|
||||||
<component name="FindManager">
|
<component name="FindManager">
|
||||||
|
|
@ -175,6 +273,32 @@
|
||||||
<option name="myItemId" value="akka-kernel" />
|
<option name="myItemId" value="akka-kernel" />
|
||||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
||||||
</PATH_ELEMENT>
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="Libraries" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.LibraryGroupNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
</PATH>
|
||||||
|
<PATH>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka-kernel" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="Libraries" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.LibraryGroupNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="Maven: org.scala-lang:scala-library:2.7.3" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.NamedLibraryElementNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="scala-library-2.7.3.jar" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
</PATH>
|
</PATH>
|
||||||
<PATH>
|
<PATH>
|
||||||
<PATH_ELEMENT>
|
<PATH_ELEMENT>
|
||||||
|
|
@ -207,6 +331,14 @@
|
||||||
<option name="myItemId" value="src" />
|
<option name="myItemId" value="src" />
|
||||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
</PATH_ELEMENT>
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="test" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="scala" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
</PATH>
|
</PATH>
|
||||||
<PATH>
|
<PATH>
|
||||||
<PATH_ELEMENT>
|
<PATH_ELEMENT>
|
||||||
|
|
@ -285,6 +417,158 @@
|
||||||
<option name="myItemId" value="main" />
|
<option name="myItemId" value="main" />
|
||||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
</PATH_ELEMENT>
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="scala" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="config" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
</PATH>
|
||||||
|
<PATH>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka-kernel" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="kernel" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="src" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="main" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
</PATH>
|
||||||
|
<PATH>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka-funtest-java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
</PATH>
|
||||||
|
<PATH>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka-funtest-java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="fun-test-java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
</PATH>
|
||||||
|
<PATH>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka-funtest-java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="fun-test-java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="src" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="test" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="api" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
</PATH>
|
||||||
|
<PATH>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka-funtest-java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="fun-test-java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="src" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="test" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="api" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="InMemoryStateTest" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ClassTreeNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
</PATH>
|
||||||
|
<PATH>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="akka-funtest-java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewModuleNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="fun-test-java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="src" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="test" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="java" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="api" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
|
<PATH_ELEMENT>
|
||||||
|
<option name="myItemId" value="InMemStateful" />
|
||||||
|
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ClassTreeNode" />
|
||||||
|
</PATH_ELEMENT>
|
||||||
</PATH>
|
</PATH>
|
||||||
</subPane>
|
</subPane>
|
||||||
</component>
|
</component>
|
||||||
|
|
@ -306,19 +590,19 @@
|
||||||
</navigator>
|
</navigator>
|
||||||
</component>
|
</component>
|
||||||
<component name="PropertiesComponent">
|
<component name="PropertiesComponent">
|
||||||
<property name="GoToClass.includeJavaFiles" value="false" />
|
|
||||||
<property name="project.structure.proportion" value="0.15" />
|
<property name="project.structure.proportion" value="0.15" />
|
||||||
|
<property name="GoToClass.includeJavaFiles" value="false" />
|
||||||
<property name="MemberChooser.copyJavadoc" value="false" />
|
<property name="MemberChooser.copyJavadoc" value="false" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatOrder2" value="2" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatOrder2" value="2" />
|
||||||
<property name="options.splitter.main.proportions" value="0.3" />
|
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeOrder2" value="2" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeOrder2" value="2" />
|
||||||
|
<property name="options.splitter.main.proportions" value="0.3" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeWidth3" value="697" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeWidth3" value="697" />
|
||||||
<property name="GoToFile.includeJavaFiles" value="false" />
|
<property name="GoToFile.includeJavaFiles" value="false" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatWidth0" value="200" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatWidth0" value="200" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeWidth2" value="210" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeWidth2" value="210" />
|
||||||
<property name="options.splitter.details.proportions" value="0.2" />
|
|
||||||
<property name="GoToClass.includeLibraries" value="false" />
|
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatWidth2" value="217" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatWidth2" value="217" />
|
||||||
|
<property name="GoToClass.includeLibraries" value="false" />
|
||||||
|
<property name="options.splitter.details.proportions" value="0.2" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatOrder0" value="0" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatOrder0" value="0" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatOrder3" value="3" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatOrder3" value="3" />
|
||||||
<property name="MemberChooser.showClasses" value="true" />
|
<property name="MemberChooser.showClasses" value="true" />
|
||||||
|
|
@ -330,12 +614,12 @@
|
||||||
<property name="RunManagerConfig.showSettingsBeforeRunnig" value="false" />
|
<property name="RunManagerConfig.showSettingsBeforeRunnig" value="false" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeOrder0" value="0" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeOrder0" value="0" />
|
||||||
<property name="project.structure.last.edited" value="Libraries" />
|
<property name="project.structure.last.edited" value="Libraries" />
|
||||||
<property name="MemberChooser.sorted" value="false" />
|
|
||||||
<property name="options.searchVisible" value="true" />
|
<property name="options.searchVisible" value="true" />
|
||||||
|
<property name="MemberChooser.sorted" value="false" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeOrder1" value="1" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeOrder1" value="1" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeWidth1" value="221" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_treeWidth1" value="221" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatWidth3" value="711" />
|
|
||||||
<property name="dynamic.classpath" value="false" />
|
<property name="dynamic.classpath" value="false" />
|
||||||
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatWidth3" value="711" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatWidth1" value="228" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatWidth1" value="228" />
|
||||||
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatOrder1" value="1" />
|
<property name="FileHistory.git4idea.history.GitHistoryProvider_flatOrder1" value="1" />
|
||||||
</component>
|
</component>
|
||||||
|
|
@ -344,7 +628,7 @@
|
||||||
<recent name="se.scalablesolutions.akka.api" />
|
<recent name="se.scalablesolutions.akka.api" />
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="JUnit.ActiveObjectGuiceConfiguratorTest">
|
<component name="RunManager" selected="JUnit.InMemoryStateTest">
|
||||||
<tempConfiguration default="false" name="Scala Console" type="ScalaScriptConsoleRunConfiguration" factoryName="Scala Console">
|
<tempConfiguration default="false" name="Scala Console" type="ScalaScriptConsoleRunConfiguration" factoryName="Scala Console">
|
||||||
<module name="" />
|
<module name="" />
|
||||||
<setting name="vmparams" value="" />
|
<setting name="vmparams" value="" />
|
||||||
|
|
@ -677,7 +961,7 @@
|
||||||
</todo-panel>
|
</todo-panel>
|
||||||
</component>
|
</component>
|
||||||
<component name="ToolWindowManager">
|
<component name="ToolWindowManager">
|
||||||
<frame x="1" y="22" width="1916" height="1178" extended-state="0" />
|
<frame x="4" y="22" width="1435" height="878" extended-state="0" />
|
||||||
<editor active="true" />
|
<editor active="true" />
|
||||||
<layout>
|
<layout>
|
||||||
<window_info id="Web Preview" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32908162" sideWeight="0.5" order="14" side_tool="false" />
|
<window_info id="Web Preview" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32908162" sideWeight="0.5" order="14" side_tool="false" />
|
||||||
|
|
@ -686,18 +970,18 @@
|
||||||
<window_info id="Data Sources" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3294881" sideWeight="0.6875" order="3" side_tool="false" />
|
<window_info id="Data Sources" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3294881" sideWeight="0.6875" order="3" side_tool="false" />
|
||||||
<window_info id="IDEtalk" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3294881" sideWeight="0.59183675" order="4" side_tool="false" />
|
<window_info id="IDEtalk" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3294881" sideWeight="0.59183675" order="4" side_tool="false" />
|
||||||
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32780612" sideWeight="0.5" order="6" side_tool="false" />
|
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32780612" sideWeight="0.5" order="6" side_tool="false" />
|
||||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.3299411" sideWeight="0.77398527" order="1" side_tool="false" />
|
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.32972583" sideWeight="0.20663266" order="1" side_tool="false" />
|
||||||
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32564574" sideWeight="0.5" order="1" side_tool="false" />
|
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.3252551" sideWeight="0.5" order="1" side_tool="false" />
|
||||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24873829" sideWeight="0.74165636" order="0" side_tool="false" />
|
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24873829" sideWeight="0.74165636" order="0" side_tool="false" />
|
||||||
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" />
|
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" />
|
||||||
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.2195572" sideWeight="0.5" order="12" side_tool="false" />
|
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.21811225" sideWeight="0.5" order="12" side_tool="false" />
|
||||||
<window_info id="Dependency Viewer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="13" side_tool="false" />
|
<window_info id="Dependency Viewer" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="13" side_tool="false" />
|
||||||
<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="6" side_tool="false" />
|
<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="6" side_tool="false" />
|
||||||
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24945927" sideWeight="0.6875" order="1" side_tool="false" />
|
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.24945927" sideWeight="0.6875" order="1" side_tool="false" />
|
||||||
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32780612" sideWeight="0.5" order="7" side_tool="false" />
|
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32780612" sideWeight="0.5" order="7" side_tool="false" />
|
||||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="true" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.78505534" sideWeight="0.5" order="2" side_tool="false" x="4" y="22" width="1436" height="878" />
|
<window_info id="Run" active="false" anchor="bottom" auto_hide="true" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.7844388" sideWeight="0.5" order="2" side_tool="false" x="4" y="22" width="1436" height="878" />
|
||||||
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.39989322" sideWeight="0.75" order="0" side_tool="false" />
|
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.39989322" sideWeight="0.75" order="0" side_tool="false" />
|
||||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.2698556" sideWeight="0.5" order="3" side_tool="false" />
|
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33418366" sideWeight="0.5" order="3" side_tool="false" />
|
||||||
<window_info id="IDEtalk Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="9" side_tool="false" />
|
<window_info id="IDEtalk Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="9" side_tool="false" />
|
||||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32780612" sideWeight="0.5" order="11" side_tool="false" />
|
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32780612" sideWeight="0.5" order="11" side_tool="false" />
|
||||||
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" />
|
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" />
|
||||||
|
|
@ -748,69 +1032,6 @@
|
||||||
</buildFile>
|
</buildFile>
|
||||||
</component>
|
</component>
|
||||||
<component name="editorHistoryManager">
|
<component name="editorHistoryManager">
|
||||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStateful.java">
|
|
||||||
<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$/../../java/aspectwerkz4/src/main/org/codehaus/aspectwerkz/intercept/AdvisableImpl.java">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state line="114" column="0" selection-start="5095" selection-end="5095" vertical-scroll-proportion="0.0">
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/Logging.scala">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state line="5" column="42" selection-start="0" selection-end="92" vertical-scroll-proportion="0.0">
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/DataFlowVariable.scala">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state line="95" column="1" selection-start="2947" selection-end="2947" vertical-scroll-proportion="0.0">
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/Future.scala">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state line="26" column="85" selection-start="719" selection-end="719" vertical-scroll-proportion="0.0">
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/ThreadBasedDispatcher.scala">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state line="68" column="16" selection-start="2395" selection-end="2395" vertical-scroll-proportion="0.0">
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/GenericServerContainerSuite.scala">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state line="95" column="123" selection-start="1873" selection-end="1873" vertical-scroll-proportion="0.0">
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state line="7" column="66" selection-start="207" selection-end="207" vertical-scroll-proportion="0.0">
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ResultOrFailure.scala">
|
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
|
||||||
<state line="32" column="47" selection-start="663" selection-end="663" vertical-scroll-proportion="0.0">
|
|
||||||
<folding />
|
|
||||||
</state>
|
|
||||||
</provider>
|
|
||||||
</entry>
|
|
||||||
<entry file="file://$PROJECT_DIR$/fun-test-java/pom.xml">
|
<entry file="file://$PROJECT_DIR$/fun-test-java/pom.xml">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state line="6" column="27" selection-start="330" selection-end="330" vertical-scroll-proportion="0.0">
|
<state line="6" column="27" selection-start="330" selection-end="330" vertical-scroll-proportion="0.0">
|
||||||
|
|
@ -825,34 +1046,106 @@
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala">
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/Future.scala">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state line="222" column="132" selection-start="8013" selection-end="8013" vertical-scroll-proportion="0.0">
|
<state line="36" column="12" selection-start="1060" selection-end="1060" vertical-scroll-proportion="0.0">
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/GenericServer.scala">
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ManagedActorScheduler.scala">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state line="25" column="0" selection-start="800" selection-end="800" vertical-scroll-proportion="0.0">
|
<state line="10" column="0" selection-start="163" selection-end="163" vertical-scroll-proportion="0.0">
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/EventDrivenDispatcher.scala">
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/Actor.scala">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state line="15" column="6" selection-start="502" selection-end="502" vertical-scroll-proportion="0.0">
|
<state line="4" column="46" selection-start="97" selection-end="97" vertical-scroll-proportion="0.0">
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala">
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/reactor/Reactor.scala">
|
||||||
<provider selected="true" editor-type-id="text-editor">
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
<state line="13" column="0" selection-start="432" selection-end="432" vertical-scroll-proportion="0.21701603">
|
<state line="75" column="0" selection-start="2051" selection-end="2051" vertical-scroll-proportion="0.0">
|
||||||
<folding />
|
<folding />
|
||||||
</state>
|
</state>
|
||||||
</provider>
|
</provider>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/kernel/src/test/scala/ActorTest.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="0" column="46" selection-start="46" selection-end="46" vertical-scroll-proportion="0.0">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="jar://$MAVEN_REPOSITORY$/org/scala-lang/scala-library/2.7.3/scala-library-2.7.3-sources.jar!/scala/List.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="804" column="0" selection-start="24740" selection-end="24740" vertical-scroll-proportion="0.3482906">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/config/ActiveObjectGuiceConfigurator.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="91" column="0" selection-start="3931" selection-end="3931" vertical-scroll-proportion="0.0">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/Transaction.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="43" column="0" selection-start="1313" selection-end="1313" vertical-scroll-proportion="0.0">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemStateful.java">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="52" column="17" selection-start="1441" selection-end="1441" vertical-scroll-proportion="0.0">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/State.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="158" column="0" selection-start="5462" selection-end="5462" vertical-scroll-proportion="0.0">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/GenericServer.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="188" column="6" selection-start="6146" selection-end="6146" vertical-scroll-proportion="0.0">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ResultOrFailure.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="56" column="6" selection-start="1411" selection-end="1411" vertical-scroll-proportion="0.0">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/kernel/src/main/scala/ActiveObject.scala">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="112" column="52" selection-start="4116" selection-end="4116" vertical-scroll-proportion="-13.5">
|
||||||
|
<folding />
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
|
<entry file="file://$PROJECT_DIR$/fun-test-java/src/test/java/se/scalablesolutions/akka/api/InMemoryStateTest.java">
|
||||||
|
<provider selected="true" editor-type-id="text-editor">
|
||||||
|
<state line="88" column="46" selection-start="4602" selection-end="4602" vertical-scroll-proportion="0.7783933">
|
||||||
|
<folding>
|
||||||
|
<element signature="imports" expanded="true" />
|
||||||
|
</folding>
|
||||||
|
</state>
|
||||||
|
</provider>
|
||||||
|
</entry>
|
||||||
</component>
|
</component>
|
||||||
<component name="masterDetails">
|
<component name="masterDetails">
|
||||||
<option name="states">
|
<option name="states">
|
||||||
|
|
|
||||||
|
|
@ -36,15 +36,15 @@ public class InMemStateful {
|
||||||
@transactional
|
@transactional
|
||||||
public void success(String key, String msg) {
|
public void success(String key, String msg) {
|
||||||
mapState.put(key, msg);
|
mapState.put(key, msg);
|
||||||
//vectorState.add(msg);
|
vectorState.add(msg);
|
||||||
//refState.swap(msg);
|
refState.swap(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@transactional
|
@transactional
|
||||||
public void failure(String key, String msg, InMemFailer failer) {
|
public void failure(String key, String msg, InMemFailer failer) {
|
||||||
mapState.put(key, msg);
|
mapState.put(key, msg);
|
||||||
//vectorState.add(msg);
|
vectorState.add(msg);
|
||||||
//refState.swap(msg);
|
refState.swap(msg);
|
||||||
failer.fail();
|
failer.fail();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,27 @@ public class InMemoryStateTest extends TestCase {
|
||||||
assertEquals("init", stateful.getVectorState()); // check that state is == init state
|
assertEquals("init", stateful.getVectorState()); // check that state is == init state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testRefShouldNotRollbackStateForStatefulServerInCaseOfSuccess() {
|
||||||
|
InMemStateful stateful = conf.getActiveObject(InMemStateful.class);
|
||||||
|
stateful.setRefState("init"); // set init state
|
||||||
|
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // transactional
|
||||||
|
stateful.success("testShouldNotRollbackStateForStatefulServerInCaseOfSuccess", "new state"); // to trigger commit
|
||||||
|
assertEquals("new state", stateful.getRefState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRefShouldRollbackStateForStatefulServerInCaseOfFailure() {
|
||||||
|
InMemStateful stateful = conf.getActiveObject(InMemStateful.class);
|
||||||
|
stateful.setRefState("init"); // set init state
|
||||||
|
InMemFailer failer = conf.getActiveObject(InMemFailer.class);
|
||||||
|
try {
|
||||||
|
stateful.failure("testShouldRollbackStateForStatefulServerInCaseOfFailure", "new state", failer); // call failing transactional method
|
||||||
|
fail("should have thrown an exception");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
} // expected
|
||||||
|
assertEquals("init", stateful.getRefState()); // check that state is == init state
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
public void testNestedNonTransactionalMethodHangs() {
|
public void testNestedNonTransactionalMethodHangs() {
|
||||||
InMemStateful stateful = conf.getActiveObject(InMemStateful.class);
|
InMemStateful stateful = conf.getActiveObject(InMemStateful.class);
|
||||||
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state
|
stateful.setMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure", "init"); // set init state
|
||||||
|
|
@ -80,8 +101,6 @@ public class InMemoryStateTest extends TestCase {
|
||||||
} // expected
|
} // expected
|
||||||
assertEquals("init", stateful.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure")); // check that state is == init state
|
assertEquals("init", stateful.getMapState("testShouldRollbackStateForStatefulServerInCaseOfFailure")); // check that state is == init state
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
*/
|
||||||
// public void testShouldRollbackStateForStatefulServerInCaseOfMessageClash()
|
// public void testShouldRollbackStateForStatefulServerInCaseOfMessageClash()
|
||||||
// {
|
// {
|
||||||
|
|
|
||||||
|
|
@ -102,19 +102,31 @@ sealed class TransactionalAroundAdvice(target: Class[_],
|
||||||
def invoke(joinpoint: JoinPoint): AnyRef = {
|
def invoke(joinpoint: JoinPoint): AnyRef = {
|
||||||
val rtti = joinpoint.getRtti.asInstanceOf[MethodRtti]
|
val rtti = joinpoint.getRtti.asInstanceOf[MethodRtti]
|
||||||
val method = rtti.getMethod
|
val method = rtti.getMethod
|
||||||
|
|
||||||
if (method.isAnnotationPresent(Annotations.transactional)) {
|
if (method.isAnnotationPresent(Annotations.transactional)) {
|
||||||
tryToCommitTransaction
|
tryToCommitTransaction
|
||||||
startNewTransaction
|
startNewTransaction
|
||||||
}
|
}
|
||||||
joinExistingTransaction
|
joinExistingTransaction
|
||||||
|
incrementTransaction
|
||||||
val result: AnyRef = if (rtti.getMethod.isAnnotationPresent(Annotations.oneway)) sendOneWay(joinpoint)
|
val result: AnyRef = try {
|
||||||
|
if (rtti.getMethod.isAnnotationPresent(Annotations.oneway)) sendOneWay(joinpoint)
|
||||||
else handleResult(sendAndReceiveEventually(joinpoint))
|
else handleResult(sendAndReceiveEventually(joinpoint))
|
||||||
|
} finally {
|
||||||
|
decrementTransaction
|
||||||
tryToPrecommitTransaction
|
tryToPrecommitTransaction
|
||||||
|
removeTransactionIfTopLevel
|
||||||
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def incrementTransaction = if (activeTx.isDefined) activeTx.get.increment
|
||||||
|
private def decrementTransaction = if (activeTx.isDefined) activeTx.get.decrement
|
||||||
|
private def removeTransactionIfTopLevel =
|
||||||
|
if (activeTx.isDefined && activeTx.get.topLevel_?) {
|
||||||
|
activeTx = None
|
||||||
|
threadBoundTx.set(None)
|
||||||
|
}
|
||||||
|
|
||||||
private def startNewTransaction = {
|
private def startNewTransaction = {
|
||||||
val newTx = new Transaction
|
val newTx = new Transaction
|
||||||
newTx.begin(server)
|
newTx.begin(server)
|
||||||
|
|
@ -131,10 +143,7 @@ sealed class TransactionalAroundAdvice(target: Class[_],
|
||||||
activeTx = threadBoundTx.get
|
activeTx = threadBoundTx.get
|
||||||
}
|
}
|
||||||
|
|
||||||
private def tryToPrecommitTransaction = {
|
private def tryToPrecommitTransaction = if (activeTx.isDefined) activeTx.get.precommit(server)
|
||||||
// FIXME: clear threadBoundTx on successful commit
|
|
||||||
if (activeTx.isDefined) activeTx.get.precommit(server)
|
|
||||||
}
|
|
||||||
|
|
||||||
private def tryToCommitTransaction = if (activeTx.isDefined) {
|
private def tryToCommitTransaction = if (activeTx.isDefined) {
|
||||||
val tx = activeTx.get
|
val tx = activeTx.get
|
||||||
|
|
|
||||||
202
kernel/src/main/scala/Actor.scala
Normal file
202
kernel/src/main/scala/Actor.scala
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2009 Scalable Solutions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.scalablesolutions.akka.kernel.actor
|
||||||
|
|
||||||
|
import java.util.concurrent.{ConcurrentSkipListSet, TimeUnit}
|
||||||
|
import kernel.reactor._
|
||||||
|
|
||||||
|
sealed abstract class LifecycleMessage
|
||||||
|
//case class Init(config: AnyRef) extends LifecycleMessage
|
||||||
|
//case class Shutdown(reason: AnyRef) extends LifecycleMessage
|
||||||
|
case class Stop(reason: AnyRef) extends LifecycleMessage
|
||||||
|
//case class HotSwap(code: Option[PartialFunction[Any, Unit]]) extends LifecycleMessage
|
||||||
|
case class Exit(dead: Actor, killer: Throwable) extends LifecycleMessage
|
||||||
|
case object Restart extends LifecycleMessage
|
||||||
|
|
||||||
|
sealed abstract class DispatcherType
|
||||||
|
case object EventBased extends DispatcherType
|
||||||
|
case object ThreadBased extends DispatcherType
|
||||||
|
|
||||||
|
class ActorMessageHandler(val actor: Actor) extends MessageHandler {
|
||||||
|
def handle(handle: MessageHandle) = actor.handle(handle.message, handle.future)
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Actor {
|
||||||
|
private[this] val linkedActors = new ConcurrentSkipListSet[Actor]
|
||||||
|
|
||||||
|
private[this] var mailbox: MessageQueue = _
|
||||||
|
private[this] var senderFuture: Option[CompletableFutureResult] = None
|
||||||
|
@volatile private var isRunning: Boolean = false
|
||||||
|
|
||||||
|
private var hotswap: Option[PartialFunction[Any, Unit]] = None
|
||||||
|
private var config: Option[AnyRef] = None
|
||||||
|
|
||||||
|
// ====================================
|
||||||
|
// ==== USER CALLBACKS TO OVERRIDE ====
|
||||||
|
// ====================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set dispatcher type to either EventBased or ThreadBased.
|
||||||
|
* Default is EventBased.
|
||||||
|
*/
|
||||||
|
protected[this] var dispatcherType: DispatcherType = EventBased
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set trapExit to true if actor should be able to trap linked actors exit messages.
|
||||||
|
*/
|
||||||
|
@volatile protected[this] var trapExit: Boolean = false
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Partial function implementing the server logic.
|
||||||
|
* To be implemented by subclassing server.
|
||||||
|
* <p/>
|
||||||
|
* Example code:
|
||||||
|
* <pre>
|
||||||
|
* def receive: PartialFunction[Any, Unit] = {
|
||||||
|
* case Ping =>
|
||||||
|
* println("got a ping")
|
||||||
|
* reply("pong")
|
||||||
|
*
|
||||||
|
* case OneWay =>
|
||||||
|
* println("got a oneway")
|
||||||
|
*
|
||||||
|
* case _ =>
|
||||||
|
* println("unknown message, ignoring")
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
protected def receive: PartialFunction[Any, Unit]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mandatory callback method that is called during restart and reinitialization after a server crash.
|
||||||
|
* To be implemented by subclassing actor.
|
||||||
|
*/
|
||||||
|
protected def restart(config: Option[AnyRef])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional callback method that is called during initialization.
|
||||||
|
* To be implemented by subclassing actor.
|
||||||
|
*/
|
||||||
|
protected def init(config: AnyRef) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional callback method that is called during termination.
|
||||||
|
* To be implemented by subclassing actor.
|
||||||
|
*/
|
||||||
|
protected def shutdown(reason: AnyRef) {}
|
||||||
|
|
||||||
|
// =============
|
||||||
|
// ==== API ====
|
||||||
|
// =============
|
||||||
|
|
||||||
|
def !(message: AnyRef) =
|
||||||
|
if (isRunning) mailbox.append(new MessageHandle(this, message, new NullFutureResult))
|
||||||
|
else throw new IllegalStateException("Actor has not been started, you need to invoke 'actor.start' before using it")
|
||||||
|
|
||||||
|
def !(implicit timeout: Long): Option[T] = if (isRunning) {
|
||||||
|
val future = postMessageToMailboxAndCreateFutureResultWithTimeout(message, timeout)
|
||||||
|
future.await_?
|
||||||
|
getResultOrThrowException(future)
|
||||||
|
} else throw new IllegalStateException("Actor has not been started, you need to invoke 'actor.start' before using it")
|
||||||
|
|
||||||
|
def !?[T](message: AnyRef): Option[T] = if (isRunning) {
|
||||||
|
val future = postMessageToMailboxAndCreateFutureResultWithTimeout(message, 0)
|
||||||
|
future.await_!
|
||||||
|
getResultOrThrowException(future)
|
||||||
|
} else throw new IllegalStateException("Actor has not been started, you need to invoke 'actor.start' before using it")
|
||||||
|
|
||||||
|
def link(actor: Actor) =
|
||||||
|
if (isRunning) linkedActors.add(actor)
|
||||||
|
else throw new IllegalStateException("Actor has not been started, you need to invoke 'actor.start' before using it")
|
||||||
|
|
||||||
|
def unlink(actor: Actor) =
|
||||||
|
if (isRunning) linkedActors.remove(actor)
|
||||||
|
else throw new IllegalStateException("Actor has not been started, you need to invoke 'actor.start' before using it")
|
||||||
|
|
||||||
|
def start = synchronized {
|
||||||
|
if (!isRunning) {
|
||||||
|
dispatcherType match {
|
||||||
|
case EventBased =>
|
||||||
|
mailbox = EventBasedDispatcher.messageQueue
|
||||||
|
EventBasedDispatcher.registerHandler(this, new ActorMessageHandler(this))
|
||||||
|
case ThreadBased =>
|
||||||
|
mailbox = ThreadBasedDispatcher.messageQueue
|
||||||
|
ThreadBasedDispatcher.registerHandler(this, new ActorMessageHandler(this))
|
||||||
|
}
|
||||||
|
isRunning = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def stop =
|
||||||
|
if (isRunning) {
|
||||||
|
this ! Stop("Actor gracefully stopped")
|
||||||
|
dispatcherType match {
|
||||||
|
case EventBased => EventBasedDispatcher.unregisterHandler(this)
|
||||||
|
case ThreadBased => ThreadBasedDispatcher.unregisterHandler(this)
|
||||||
|
}
|
||||||
|
isRunning = false
|
||||||
|
} else throw new IllegalStateException("Actor has not been started, you need to invoke 'actor.start' before using it")
|
||||||
|
|
||||||
|
protected def reply(message: AnyRef) = senderFuture match {
|
||||||
|
case None => throw new IllegalStateException("No sender future in scope, can't reply")
|
||||||
|
case Some(future) => future.completeWithResult(message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================================
|
||||||
|
// ==== IMPLEMENTATION DETAILS ====
|
||||||
|
// ================================
|
||||||
|
|
||||||
|
private def postMessageToMailboxAndCreateFutureResultWithTimeout(
|
||||||
|
message: AnyRef, timeout: Long): CompletableFutureResult = {
|
||||||
|
val future = new DefaultCompletableFutureResult(timeout)
|
||||||
|
mailbox.append(new MessageHandle(this, message, future))
|
||||||
|
future
|
||||||
|
}
|
||||||
|
|
||||||
|
private def getResultOrThrowException[T](future: FutureResult): Option[T] =
|
||||||
|
if (future.exception.isDefined) throw future.exception.get
|
||||||
|
else future.result.asInstanceOf[Option[T]]
|
||||||
|
|
||||||
|
private[kernel] def handle(message: AnyRef, future: CompletableFutureResult) = {
|
||||||
|
try {
|
||||||
|
senderFuture = Some(future)
|
||||||
|
if (base.isDefinedAt(message)) base(message)
|
||||||
|
else throw new IllegalArgumentException("No handler matching message [" + message + "] in actor [" + this.getClass.getName + "]")
|
||||||
|
} catch {
|
||||||
|
case e =>
|
||||||
|
future.completeWithException(e)
|
||||||
|
handleFailure(this, e)
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
try {
|
||||||
|
val result = message.asInstanceOf[Invocation].joinpoint.proceed
|
||||||
|
future.completeWithResult(result)
|
||||||
|
} catch {
|
||||||
|
case e: Exception => future.completeWithException(e)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private def base: PartialFunction[Any, Unit] = lifeCycle orElse (hotswap getOrElse receive)
|
||||||
|
|
||||||
|
private val lifeCycle: PartialFunction[Any, Unit] = {
|
||||||
|
case Init(config) => init(config)
|
||||||
|
case HotSwap(code) => hotswap = code
|
||||||
|
case Restart => restart(config)
|
||||||
|
case Stop(reason) => shutdown(reason); exit
|
||||||
|
case Exit(dead, reason) => handleFailure(dead, reason)
|
||||||
|
}
|
||||||
|
|
||||||
|
private[this] def handleFailure(dead: Actor, e: Throwable) = {
|
||||||
|
if (trapExit) {
|
||||||
|
restartLinkedActors
|
||||||
|
scheduleRestart
|
||||||
|
} else linkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach(_ ! Exit(this, e))
|
||||||
|
}
|
||||||
|
|
||||||
|
private[this] def restartLinkedActors = linkedActors.toArray.toList.asInstanceOf[List[Actor]].foreach(_.scheduleRestart)
|
||||||
|
|
||||||
|
private[Actor] def scheduleRestart = mailbox.prepend(new MessageHandle(this, Restart, new NullFutureResult))
|
||||||
|
}
|
||||||
|
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
package se.scalablesolutions.akka.kernel
|
package se.scalablesolutions.akka.kernel
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicLong
|
import java.util.concurrent.atomic.{AtomicInteger, AtomicLong}
|
||||||
import scala.collection.mutable.{HashSet, HashMap}
|
import scala.collection.mutable.{HashSet, HashMap}
|
||||||
|
|
||||||
sealed abstract class TransactionStatus
|
sealed abstract class TransactionStatus
|
||||||
object TransactionStatus {
|
object TransactionStatus {
|
||||||
case object New extends TransactionStatus
|
case object New extends TransactionStatus
|
||||||
|
|
@ -39,8 +40,13 @@ class Transaction extends Logging {
|
||||||
private[this] var parent: Option[Transaction] = None
|
private[this] var parent: Option[Transaction] = None
|
||||||
private[this] val participants = new HashSet[GenericServerContainer]
|
private[this] val participants = new HashSet[GenericServerContainer]
|
||||||
private[this] val precommitted = new HashSet[GenericServerContainer]
|
private[this] val precommitted = new HashSet[GenericServerContainer]
|
||||||
|
private[this] val depth = new AtomicInteger(0)
|
||||||
@volatile private[this] var status: TransactionStatus = TransactionStatus.New
|
@volatile private[this] var status: TransactionStatus = TransactionStatus.New
|
||||||
|
|
||||||
|
def increment = depth.incrementAndGet
|
||||||
|
def decrement = depth.decrementAndGet
|
||||||
|
def topLevel_? = depth.get == 0
|
||||||
|
|
||||||
def begin(server: GenericServerContainer) = synchronized {
|
def begin(server: GenericServerContainer) = synchronized {
|
||||||
ensureIsActiveOrNew
|
ensureIsActiveOrNew
|
||||||
if (status == TransactionStatus.New) log.info("Server [%s] is starting NEW transaction [%s]", server.id, this)
|
if (status == TransactionStatus.New) log.info("Server [%s] is starting NEW transaction [%s]", server.id, this)
|
||||||
|
|
|
||||||
53
kernel/src/main/scala/reactor/EventBasedDispatcher.scala
Normal file
53
kernel/src/main/scala/reactor/EventBasedDispatcher.scala
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2009 Scalable Solutions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the Reactor pattern as defined in: [http://www.cs.wustl.edu/~schmidt/PDF/reactor-siemens.pdf].
|
||||||
|
* See also this article: [http://today.java.net/cs/user/print/a/350].
|
||||||
|
*
|
||||||
|
* Based on code from the actorom actor framework by Sergio Bossa [http://code.google.com/p/actorom/].
|
||||||
|
*/
|
||||||
|
package se.scalablesolutions.akka.kernel.reactor
|
||||||
|
|
||||||
|
object EventBasedDispatcher extends MessageDispatcherBase {
|
||||||
|
|
||||||
|
start
|
||||||
|
|
||||||
|
//def dispatch(messageQueue: MessageQueue) = if (!active) {
|
||||||
|
def start = if (!active) {
|
||||||
|
active = true
|
||||||
|
val messageDemultiplexer = new EventBasedDemultiplexer(messageQueue)
|
||||||
|
selectorThread = new Thread {
|
||||||
|
override def run = {
|
||||||
|
while (active) {
|
||||||
|
guard.synchronized { /* empty */ } // prevents risk for deadlock as described in [http://developers.sun.com/learning/javaoneonline/2006/coreplatform/TS-1315.pdf]
|
||||||
|
try {
|
||||||
|
messageDemultiplexer.select
|
||||||
|
} catch { case e: InterruptedException => active = false }
|
||||||
|
val queue = messageDemultiplexer.acquireSelectedQueue
|
||||||
|
for (index <- 0 until queue.size) {
|
||||||
|
val handle = queue.remove
|
||||||
|
val handler = messageHandlers.get(handle.sender)
|
||||||
|
if (handler != null) handler.handle(handle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectorThread.start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EventBasedDemultiplexer(private val messageQueue: MessageQueue) extends MessageDemultiplexer {
|
||||||
|
import java.util.{LinkedList, Queue}
|
||||||
|
|
||||||
|
private val selectedQueue: Queue[MessageHandle] = new LinkedList[MessageHandle]
|
||||||
|
|
||||||
|
def select = messageQueue.read(selectedQueue)
|
||||||
|
|
||||||
|
def acquireSelectedQueue: Queue[MessageHandle] = selectedQueue
|
||||||
|
|
||||||
|
def releaseSelectedQueue = throw new UnsupportedOperationException("EventBasedDemultiplexer can't release its queue")
|
||||||
|
|
||||||
|
def wakeUp = throw new UnsupportedOperationException("EventBasedDemultiplexer can't be woken up")
|
||||||
|
}
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2009 Scalable Solutions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implements the Reactor pattern as defined in: [http://www.cs.wustl.edu/~schmidt/PDF/reactor-siemens.pdf].
|
|
||||||
* See also this article: [http://today.java.net/cs/user/print/a/350].
|
|
||||||
*
|
|
||||||
* Based on code from the actorom actor framework by Sergio Bossa [http://code.google.com/p/actorom/].
|
|
||||||
*/
|
|
||||||
package se.scalablesolutions.akka.kernel.reactor
|
|
||||||
|
|
||||||
import java.util.concurrent.{ConcurrentMap, ConcurrentHashMap}
|
|
||||||
import java.util.{LinkedList, Queue}
|
|
||||||
|
|
||||||
class EventDrivenDispatcher extends MessageDispatcher {
|
|
||||||
private val handlers = new ConcurrentHashMap[AnyRef, MessageHandler]
|
|
||||||
private var selectorThread: Thread = _
|
|
||||||
@volatile private var active: Boolean = false
|
|
||||||
private val guard = new Object
|
|
||||||
|
|
||||||
def registerHandler(key: AnyRef, handler: MessageHandler) = handlers.put(key, handler)
|
|
||||||
|
|
||||||
def unregisterHandler(key: AnyRef) = handlers.remove(key)
|
|
||||||
|
|
||||||
def dispatch(messageQueue: MessageQueue) = if (!active) {
|
|
||||||
active = true
|
|
||||||
val messageDemultiplexer = new EventDrivenDemultiplexer(messageQueue)
|
|
||||||
selectorThread = new Thread {
|
|
||||||
override def run = {
|
|
||||||
while (active) {
|
|
||||||
guard.synchronized { /* empty */ }
|
|
||||||
messageDemultiplexer.select
|
|
||||||
val handles = messageDemultiplexer.acquireSelectedQueue
|
|
||||||
val handlesList = handles.toArray.toList.asInstanceOf[List[MessageHandle]]
|
|
||||||
for (index <- 0 to handles.size) {
|
|
||||||
val handle = handles.remove
|
|
||||||
val handler = handlers.get(handle.key)
|
|
||||||
if (handler != null) handler.handle(handle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
selectorThread.start
|
|
||||||
}
|
|
||||||
|
|
||||||
def shutdown = if (active) {
|
|
||||||
active = false
|
|
||||||
selectorThread.interrupt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class EventDrivenDemultiplexer(private val messageQueue: MessageQueue) extends MessageDemultiplexer {
|
|
||||||
private val selectedQueue: Queue[MessageHandle] = new LinkedList[MessageHandle]
|
|
||||||
|
|
||||||
def select = messageQueue.read(selectedQueue)
|
|
||||||
|
|
||||||
def acquireSelectedQueue: Queue[MessageHandle] = selectedQueue
|
|
||||||
|
|
||||||
def releaseSelectedQueue = {
|
|
||||||
throw new UnsupportedOperationException
|
|
||||||
}
|
|
||||||
|
|
||||||
def wakeUp = {
|
|
||||||
throw new UnsupportedOperationException
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -11,43 +11,57 @@ import java.util.concurrent.locks.{Lock, Condition, ReentrantLock}
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
sealed trait FutureResult {
|
sealed trait FutureResult {
|
||||||
def await
|
def await_?
|
||||||
|
def await_!
|
||||||
def isCompleted: Boolean
|
def isCompleted: Boolean
|
||||||
def isExpired: Boolean
|
def isExpired: Boolean
|
||||||
def timeoutInNanos: Long
|
def timeoutInNanos: Long
|
||||||
def result: AnyRef
|
def result: Option[AnyRef]
|
||||||
def exception: Exception
|
def exception: Option[Throwable]
|
||||||
}
|
}
|
||||||
|
|
||||||
trait CompletableFutureResult extends FutureResult {
|
trait CompletableFutureResult extends FutureResult {
|
||||||
def completeWithResult(result: AnyRef)
|
def completeWithResult(result: AnyRef)
|
||||||
def completeWithException(exception: Exception)
|
def completeWithException(exception: Throwable)
|
||||||
}
|
}
|
||||||
|
|
||||||
class GenericFutureResult(val timeoutInNanos: Long) extends CompletableFutureResult {
|
class DefaultCompletableFutureResult(timeout: Long) extends CompletableFutureResult {
|
||||||
|
private val TIME_UNIT = TimeUnit.MILLISECONDS
|
||||||
|
def this() = this(0)
|
||||||
|
|
||||||
|
val timeoutInNanos = TIME_UNIT.toNanos(timeout)
|
||||||
private val _startTimeInNanos = currentTimeInNanos
|
private val _startTimeInNanos = currentTimeInNanos
|
||||||
private val _lock = new ReentrantLock
|
private val _lock = new ReentrantLock
|
||||||
private val _signal = _lock.newCondition
|
private val _signal = _lock.newCondition
|
||||||
private var _completed: Boolean = _
|
private var _completed: Boolean = _
|
||||||
private var _result: AnyRef = _
|
private var _result: Option[AnyRef] = None
|
||||||
private var _exception: Exception = _
|
private var _exception: Option[Throwable] = None
|
||||||
|
|
||||||
override def await = try {
|
override def await_? = try {
|
||||||
_lock.lock
|
_lock.lock
|
||||||
var wait = timeoutInNanos - currentTimeInNanos - _startTimeInNanos
|
var wait = timeoutInNanos - (currentTimeInNanos - _startTimeInNanos)
|
||||||
while (!_completed && wait > 0) {
|
while (!_completed && wait > 0) {
|
||||||
var start = currentTimeInNanos
|
var start = currentTimeInNanos
|
||||||
try {
|
try {
|
||||||
wait = _signal.awaitNanos(wait)
|
wait = _signal.awaitNanos(wait)
|
||||||
} catch {
|
} catch {
|
||||||
case e: InterruptedException =>
|
case e: InterruptedException =>
|
||||||
wait = wait - currentTimeInNanos - start
|
wait = wait - (currentTimeInNanos - start)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
_lock.unlock
|
_lock.unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def await_! = try {
|
||||||
|
_lock.lock
|
||||||
|
while (!_completed) {
|
||||||
|
_signal.await
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_lock.unlock
|
||||||
|
}
|
||||||
|
|
||||||
override def isCompleted: Boolean = try {
|
override def isCompleted: Boolean = try {
|
||||||
_lock.lock
|
_lock.lock
|
||||||
_completed
|
_completed
|
||||||
|
|
@ -57,19 +71,19 @@ class GenericFutureResult(val timeoutInNanos: Long) extends CompletableFutureRes
|
||||||
|
|
||||||
override def isExpired: Boolean = try {
|
override def isExpired: Boolean = try {
|
||||||
_lock.lock
|
_lock.lock
|
||||||
timeoutInNanos - currentTimeInNanos - _startTimeInNanos <= 0
|
timeoutInNanos - (currentTimeInNanos - _startTimeInNanos) <= 0
|
||||||
} finally {
|
} finally {
|
||||||
_lock.unlock
|
_lock.unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
override def result: AnyRef = try {
|
override def result: Option[AnyRef] = try {
|
||||||
_lock.lock
|
_lock.lock
|
||||||
_result
|
_result
|
||||||
} finally {
|
} finally {
|
||||||
_lock.unlock
|
_lock.unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
override def exception: Exception = try {
|
override def exception: Option[Throwable] = try {
|
||||||
_lock.lock
|
_lock.lock
|
||||||
_exception
|
_exception
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -80,19 +94,18 @@ class GenericFutureResult(val timeoutInNanos: Long) extends CompletableFutureRes
|
||||||
_lock.lock
|
_lock.lock
|
||||||
if (!_completed) {
|
if (!_completed) {
|
||||||
_completed = true
|
_completed = true
|
||||||
_result = result
|
_result = Some(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
_signal.signalAll
|
_signal.signalAll
|
||||||
_lock.unlock
|
_lock.unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
override def completeWithException(exception: Exception) = try {
|
override def completeWithException(exception: Throwable) = try {
|
||||||
_lock.lock
|
_lock.lock
|
||||||
if (!_completed) {
|
if (!_completed) {
|
||||||
_completed = true
|
_completed = true
|
||||||
_exception = exception
|
_exception = Some(exception)
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -100,16 +113,17 @@ class GenericFutureResult(val timeoutInNanos: Long) extends CompletableFutureRes
|
||||||
_lock.unlock
|
_lock.unlock
|
||||||
}
|
}
|
||||||
|
|
||||||
private def currentTimeInNanos: Long = TimeUnit.MILLISECONDS.toNanos(System.currentTimeMillis)
|
private def currentTimeInNanos: Long = TIME_UNIT.toNanos(System.currentTimeMillis)
|
||||||
}
|
}
|
||||||
|
|
||||||
class NullFutureResult extends CompletableFutureResult {
|
class NullFutureResult extends CompletableFutureResult {
|
||||||
override def completeWithResult(result: AnyRef) = {}
|
override def completeWithResult(result: AnyRef) = {}
|
||||||
override def completeWithException(exception: Exception) = {}
|
override def completeWithException(exception: Throwable) = {}
|
||||||
override def await: Unit = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
override def await_? = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
||||||
|
override def await_! = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
||||||
override def isCompleted: Boolean = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
override def isCompleted: Boolean = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
||||||
override def isExpired: Boolean = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
override def isExpired: Boolean = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
||||||
override def timeoutInNanos: Long = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
override def timeoutInNanos: Long = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
||||||
override def result: AnyRef = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
override def result: Option[AnyRef] = None
|
||||||
override def exception: Exception = throw new UnsupportedOperationException("Not implemented for NullFutureResult")
|
override def exception: Option[Throwable] = None
|
||||||
}
|
}
|
||||||
|
|
|
||||||
35
kernel/src/main/scala/reactor/MessageDispatcherBase.scala
Normal file
35
kernel/src/main/scala/reactor/MessageDispatcherBase.scala
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
/**
|
||||||
|
* Copyright (C) 2009 Scalable Solutions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package se.scalablesolutions.akka.kernel.reactor
|
||||||
|
|
||||||
|
import java.util.concurrent.{ConcurrentMap, ConcurrentHashMap}
|
||||||
|
|
||||||
|
trait MessageDispatcherBase extends MessageDispatcher {
|
||||||
|
val messageQueue = new MessageQueue
|
||||||
|
|
||||||
|
protected val messageHandlers = new ConcurrentHashMap[AnyRef, MessageHandler]
|
||||||
|
protected var selectorThread: Thread = _
|
||||||
|
@volatile protected var active: Boolean = false
|
||||||
|
protected val guard = new Object
|
||||||
|
|
||||||
|
def registerHandler(key: AnyRef, handler: MessageHandler) = guard.synchronized {
|
||||||
|
messageHandlers.put(key, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
def unregisterHandler(key: AnyRef) = guard.synchronized {
|
||||||
|
messageHandlers.remove(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
def shutdown = if (active) {
|
||||||
|
active = false
|
||||||
|
selectorThread.interrupt
|
||||||
|
doShutdown
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclass callback. Override if additional shutdown behavior is needed.
|
||||||
|
*/
|
||||||
|
protected def doShutdown = {}
|
||||||
|
}
|
||||||
|
|
@ -12,10 +12,14 @@ package se.scalablesolutions.akka.kernel.reactor
|
||||||
|
|
||||||
import java.util.{LinkedList, Queue}
|
import java.util.{LinkedList, Queue}
|
||||||
|
|
||||||
|
trait MessageHandler {
|
||||||
|
def handle(message: MessageHandle)
|
||||||
|
}
|
||||||
|
|
||||||
trait MessageDispatcher {
|
trait MessageDispatcher {
|
||||||
def registerHandler(key: AnyRef, handler: MessageHandler)
|
def registerHandler(key: AnyRef, handler: MessageHandler)
|
||||||
def unregisterHandler(key: AnyRef)
|
def unregisterHandler(key: AnyRef)
|
||||||
def dispatch(messageQueue: MessageQueue)
|
def start
|
||||||
def shutdown
|
def shutdown
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -26,11 +30,11 @@ trait MessageDemultiplexer {
|
||||||
def wakeUp
|
def wakeUp
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageHandle(val key: AnyRef, val message: AnyRef, val future: CompletableFutureResult) {
|
class MessageHandle(val sender: AnyRef, val message: AnyRef, val future: CompletableFutureResult) {
|
||||||
|
|
||||||
override def hashCode(): Int = {
|
override def hashCode(): Int = {
|
||||||
var result = HashCode.SEED
|
var result = HashCode.SEED
|
||||||
result = HashCode.hash(result, key)
|
result = HashCode.hash(result, sender)
|
||||||
result = HashCode.hash(result, message)
|
result = HashCode.hash(result, message)
|
||||||
result = HashCode.hash(result, future)
|
result = HashCode.hash(result, future)
|
||||||
result
|
result
|
||||||
|
|
@ -39,40 +43,33 @@ class MessageHandle(val key: AnyRef, val message: AnyRef, val future: Completabl
|
||||||
override def equals(that: Any): Boolean =
|
override def equals(that: Any): Boolean =
|
||||||
that != null &&
|
that != null &&
|
||||||
that.isInstanceOf[MessageHandle] &&
|
that.isInstanceOf[MessageHandle] &&
|
||||||
that.asInstanceOf[MessageHandle].key == key &&
|
that.asInstanceOf[MessageHandle].sender == sender &&
|
||||||
that.asInstanceOf[MessageHandle].message == message &&
|
that.asInstanceOf[MessageHandle].message == message &&
|
||||||
that.asInstanceOf[MessageHandle].future == future
|
that.asInstanceOf[MessageHandle].future == future
|
||||||
}
|
}
|
||||||
|
|
||||||
trait MessageHandler {
|
|
||||||
def handle(message: MessageHandle)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class MessageQueue {
|
class MessageQueue {
|
||||||
private val handles: Queue[MessageHandle] = new LinkedList[MessageHandle]
|
private val queue: Queue[MessageHandle] = new LinkedList[MessageHandle]
|
||||||
@volatile private var interrupted = false
|
@volatile private var interrupted = false
|
||||||
|
|
||||||
def put(handle: MessageHandle) = handles.synchronized {
|
def append(handle: MessageHandle) = queue.synchronized {
|
||||||
handles.offer(handle)
|
queue.offer(handle)
|
||||||
handles.notifyAll
|
queue.notifyAll
|
||||||
}
|
}
|
||||||
|
|
||||||
def read(destination: Queue[MessageHandle]) = handles.synchronized {
|
def prepend(handle: MessageHandle) = queue.synchronized {
|
||||||
while (handles.isEmpty && !interrupted) {
|
queue.add(handle)
|
||||||
handles.wait
|
queue.notifyAll
|
||||||
}
|
|
||||||
if (!interrupted) {
|
|
||||||
while (!handles.isEmpty) {
|
|
||||||
destination.offer(handles.remove)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
interrupted = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def interrupt = handles.synchronized {
|
def read(destination: Queue[MessageHandle]) = queue.synchronized {
|
||||||
|
while (queue.isEmpty && !interrupted) queue.wait
|
||||||
|
if (!interrupted) while (!queue.isEmpty) destination.offer(queue.remove)
|
||||||
|
else interrupted = false
|
||||||
|
}
|
||||||
|
|
||||||
|
def interrupt = queue.synchronized {
|
||||||
interrupted = true
|
interrupted = true
|
||||||
handles.notifyAll
|
queue.notifyAll
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,43 +10,42 @@
|
||||||
*/
|
*/
|
||||||
package se.scalablesolutions.akka.kernel.reactor
|
package se.scalablesolutions.akka.kernel.reactor
|
||||||
|
|
||||||
import java.util.concurrent.{ConcurrentHashMap, Executors}
|
object ThreadBasedDispatcher extends MessageDispatcherBase {
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.Executors
|
||||||
import java.util.{HashSet, LinkedList, Queue}
|
import java.util.HashSet
|
||||||
|
|
||||||
class ThreadBasedDispatcher(val threadPoolSize: Int) extends MessageDispatcher {
|
// FIXME: make configurable using configgy + JMX
|
||||||
private val handlers = new ConcurrentHashMap[AnyRef, MessageHandler]
|
// FIXME: create one executor per invocation to dispatch(..), grab config settings for specific actor (set in registerHandler)
|
||||||
|
private val threadPoolSize: Int = 10
|
||||||
private val busyHandlers = new HashSet[AnyRef]
|
private val busyHandlers = new HashSet[AnyRef]
|
||||||
private val handlerExecutor = Executors.newFixedThreadPool(threadPoolSize)
|
private val handlerExecutor = Executors.newFixedThreadPool(threadPoolSize)
|
||||||
@volatile private var selectorThread: Thread = null
|
|
||||||
@volatile private var active: Boolean = false
|
|
||||||
|
|
||||||
def registerHandler(key: AnyRef, handler: MessageHandler) = handlers.put(key, handler)
|
start
|
||||||
|
|
||||||
def unregisterHandler(key: AnyRef) = handlers.remove(key)
|
def start = if (!active) {
|
||||||
|
|
||||||
def dispatch(messageQueue: MessageQueue) = {
|
|
||||||
if (!active) {
|
|
||||||
active = true
|
active = true
|
||||||
val messageDemultiplexer = new ThreadBasedDemultiplexer(messageQueue)
|
val messageDemultiplexer = new ThreadBasedDemultiplexer(messageQueue)
|
||||||
selectorThread = new Thread {
|
selectorThread = new Thread {
|
||||||
override def run = {
|
override def run = {
|
||||||
while (active) {
|
while (active) {
|
||||||
|
try {
|
||||||
|
guard.synchronized { /* empty */ } // prevents risk for deadlock as described in [http://developers.sun.com/learning/javaoneonline/2006/coreplatform/TS-1315.pdf]
|
||||||
try {
|
try {
|
||||||
messageDemultiplexer.select
|
messageDemultiplexer.select
|
||||||
val handles = messageDemultiplexer.acquireSelectedQueue
|
} catch {case e: InterruptedException => active = false}
|
||||||
for (index <- 0 to handles.size) {
|
val queue = messageDemultiplexer.acquireSelectedQueue
|
||||||
val handle = handles.peek
|
for (index <- 0 until queue.size) {
|
||||||
val handler = checkIfNotBusyThenGet(handle.key)
|
val message = queue.peek
|
||||||
if (handler.isDefined) {
|
val messageHandler = getIfNotBusy(message.sender)
|
||||||
|
if (messageHandler.isDefined) {
|
||||||
handlerExecutor.execute(new Runnable {
|
handlerExecutor.execute(new Runnable {
|
||||||
override def run = {
|
override def run = {
|
||||||
handler.get.handle(handle)
|
messageHandler.get.handle(message)
|
||||||
free(handle.key)
|
free(message.sender)
|
||||||
messageDemultiplexer.wakeUp
|
messageDemultiplexer.wakeUp
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
handles.remove
|
queue.remove
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
@ -55,20 +54,15 @@ class ThreadBasedDispatcher(val threadPoolSize: Int) extends MessageDispatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
selectorThread.start();
|
selectorThread.start
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def shutdown = if (active) {
|
override protected def doShutdown = handlerExecutor.shutdownNow
|
||||||
active = false
|
|
||||||
selectorThread.interrupt
|
|
||||||
handlerExecutor.shutdownNow
|
|
||||||
}
|
|
||||||
|
|
||||||
private def checkIfNotBusyThenGet(key: AnyRef): Option[MessageHandler] = synchronized {
|
private def getIfNotBusy(key: AnyRef): Option[MessageHandler] = synchronized {
|
||||||
if (!busyHandlers.contains(key) && handlers.containsKey(key)) {
|
if (!busyHandlers.contains(key) && messageHandlers.containsKey(key)) {
|
||||||
busyHandlers.add(key)
|
busyHandlers.add(key)
|
||||||
Some(handlers.get(key))
|
Some(messageHandlers.get(key))
|
||||||
} else None
|
} else None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,6 +70,9 @@ class ThreadBasedDispatcher(val threadPoolSize: Int) extends MessageDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ThreadBasedDemultiplexer(private val messageQueue: MessageQueue) extends MessageDemultiplexer {
|
class ThreadBasedDemultiplexer(private val messageQueue: MessageQueue) extends MessageDemultiplexer {
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import java.util.{LinkedList, Queue}
|
||||||
|
|
||||||
private val selectedQueue: Queue[MessageHandle] = new LinkedList[MessageHandle]
|
private val selectedQueue: Queue[MessageHandle] = new LinkedList[MessageHandle]
|
||||||
private val selectedQueueLock = new ReentrantLock
|
private val selectedQueueLock = new ReentrantLock
|
||||||
|
|
||||||
|
|
|
||||||
76
kernel/src/test/scala/ActorTest.scala
Normal file
76
kernel/src/test/scala/ActorTest.scala
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
package se.scalablesolutions.akka.kernel.actor
|
||||||
|
|
||||||
|
import concurrent.Lock
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import reactor._
|
||||||
|
|
||||||
|
import org.junit.{Test, Before}
|
||||||
|
import org.junit.Assert._
|
||||||
|
|
||||||
|
class ActorTest {
|
||||||
|
private val unit = TimeUnit.MILLISECONDS
|
||||||
|
|
||||||
|
class TestActor extends Actor {
|
||||||
|
def receive: PartialFunction[Any, Unit] = {
|
||||||
|
case "Hello" =>
|
||||||
|
println("Hello")
|
||||||
|
reply("World")
|
||||||
|
case "Failure" =>
|
||||||
|
throw new RuntimeException("expected")
|
||||||
|
}
|
||||||
|
def restart(config: Option[AnyRef]) = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def sendOneWay = {
|
||||||
|
implicit val timeout = 5000L
|
||||||
|
var oneWay = "nada"
|
||||||
|
val actor = new Actor {
|
||||||
|
def receive: PartialFunction[Any, Unit] = {
|
||||||
|
case "OneWay" => oneWay = "received"
|
||||||
|
}
|
||||||
|
def restart(config: Option[AnyRef]) = {}
|
||||||
|
}
|
||||||
|
actor.start
|
||||||
|
val result = actor ! "OneWay"
|
||||||
|
Thread.sleep(100)
|
||||||
|
assertEquals("received", oneWay)
|
||||||
|
//actor.stop
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def sendReplySync = {
|
||||||
|
implicit val timeout = 5000L
|
||||||
|
val actor = new TestActor
|
||||||
|
actor.start
|
||||||
|
val result = actor !? "Hello"
|
||||||
|
assertEquals("World", result.get.asInstanceOf[String])
|
||||||
|
//actor.stop
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def sendReplyAsync = {
|
||||||
|
implicit val timeout = 5000L
|
||||||
|
val actor = new TestActor
|
||||||
|
actor.start
|
||||||
|
val result = actor !! "Hello"
|
||||||
|
assertEquals("World", result.get.asInstanceOf[String])
|
||||||
|
//actor.stop
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def sendReceiveException = {
|
||||||
|
implicit val timeout = 5000L
|
||||||
|
val actor = new TestActor
|
||||||
|
actor.start
|
||||||
|
try {
|
||||||
|
actor !! "Failure"
|
||||||
|
fail("Should have thrown an exception")
|
||||||
|
} catch {
|
||||||
|
case e =>
|
||||||
|
assertEquals("expected", e.getMessage())
|
||||||
|
}
|
||||||
|
//actor.stop
|
||||||
|
}
|
||||||
|
}
|
||||||
116
kernel/src/test/scala/EventBasedDispatcherTest.scala
Normal file
116
kernel/src/test/scala/EventBasedDispatcherTest.scala
Normal file
|
|
@ -0,0 +1,116 @@
|
||||||
|
package se.scalablesolutions.akka.kernel.reactor
|
||||||
|
|
||||||
|
import java.util.concurrent.BrokenBarrierException
|
||||||
|
import java.util.concurrent.CountDownLatch
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import java.util.concurrent.TimeoutException
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import java.util.concurrent.locks.Lock
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import org.junit.{Test, Before}
|
||||||
|
import org.junit.Assert._
|
||||||
|
|
||||||
|
class EventBasedDispatcherTest {
|
||||||
|
private var threadingIssueDetected: AtomicBoolean = null
|
||||||
|
|
||||||
|
class TestMessageHandle(handleLatch: CountDownLatch) extends MessageHandler {
|
||||||
|
val guardLock: Lock = new ReentrantLock
|
||||||
|
|
||||||
|
def handle(message: MessageHandle) {
|
||||||
|
try {
|
||||||
|
if (threadingIssueDetected.get) return
|
||||||
|
if (guardLock.tryLock) {
|
||||||
|
Thread.sleep(100)
|
||||||
|
handleLatch.countDown
|
||||||
|
} else {
|
||||||
|
threadingIssueDetected.set(true)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
case e: Exception => threadingIssueDetected.set(true)
|
||||||
|
} finally {
|
||||||
|
guardLock.unlock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
def setUp = {
|
||||||
|
threadingIssueDetected = new AtomicBoolean(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def testMessagesDispatchedToTheSameHandlerAreExecutedSequentially = {
|
||||||
|
internalTestMessagesDispatchedToTheSameHandlerAreExecutedSequentially
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def testMessagesDispatchedToDifferentHandlersAreExecutedSequentially = {
|
||||||
|
internalTestMessagesDispatchedToDifferentHandlersAreExecutedSequentially
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def testMessagesDispatchedToHandlersAreExecutedInFIFOOrder = {
|
||||||
|
internalTestMessagesDispatchedToHandlersAreExecutedInFIFOOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
private def internalTestMessagesDispatchedToTheSameHandlerAreExecutedSequentially: Unit = {
|
||||||
|
val guardLock = new ReentrantLock
|
||||||
|
val handleLatch = new CountDownLatch(10)
|
||||||
|
val key = "key"
|
||||||
|
EventBasedDispatcher.registerHandler(key, new TestMessageHandle(handleLatch))
|
||||||
|
EventBasedDispatcher.start
|
||||||
|
for (i <- 0 until 10) {
|
||||||
|
EventBasedDispatcher.messageQueue.append(new MessageHandle(key, new Object, new NullFutureResult))
|
||||||
|
}
|
||||||
|
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
|
||||||
|
assertFalse(threadingIssueDetected.get)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def internalTestMessagesDispatchedToDifferentHandlersAreExecutedSequentially: Unit = {
|
||||||
|
val handleLatch = new CountDownLatch(2)
|
||||||
|
val key1 = "key1"
|
||||||
|
val key2 = "key2"
|
||||||
|
EventBasedDispatcher.registerHandler(key1, new TestMessageHandle(handleLatch))
|
||||||
|
EventBasedDispatcher.registerHandler(key2, new TestMessageHandle(handleLatch))
|
||||||
|
EventBasedDispatcher.start
|
||||||
|
EventBasedDispatcher.messageQueue.append(new MessageHandle(key1, new Object, new NullFutureResult))
|
||||||
|
EventBasedDispatcher.messageQueue.append(new MessageHandle(key2, new Object, new NullFutureResult))
|
||||||
|
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
|
||||||
|
assertFalse(threadingIssueDetected.get)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def internalTestMessagesDispatchedToHandlersAreExecutedInFIFOOrder: Unit = {
|
||||||
|
val handleLatch = new CountDownLatch(200)
|
||||||
|
val key1 = "key1"
|
||||||
|
val key2 = "key2"
|
||||||
|
EventBasedDispatcher.registerHandler(key1, new MessageHandler {
|
||||||
|
var currentValue = -1;
|
||||||
|
def handle(message: MessageHandle) {
|
||||||
|
if (threadingIssueDetected.get) return
|
||||||
|
val messageValue = message.message.asInstanceOf[Int]
|
||||||
|
if (messageValue.intValue == currentValue + 1) {
|
||||||
|
currentValue = messageValue.intValue
|
||||||
|
handleLatch.countDown
|
||||||
|
} else threadingIssueDetected.set(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
EventBasedDispatcher.registerHandler(key2, new MessageHandler {
|
||||||
|
var currentValue = -1;
|
||||||
|
def handle(message: MessageHandle) {
|
||||||
|
if (threadingIssueDetected.get) return
|
||||||
|
val messageValue = message.message.asInstanceOf[Int]
|
||||||
|
if (messageValue.intValue == currentValue + 1) {
|
||||||
|
currentValue = messageValue.intValue
|
||||||
|
handleLatch.countDown
|
||||||
|
} else threadingIssueDetected.set(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
EventBasedDispatcher.start
|
||||||
|
for (i <- 0 until 100) {
|
||||||
|
EventBasedDispatcher.messageQueue.append(new MessageHandle(key1, new Integer(i), new NullFutureResult))
|
||||||
|
EventBasedDispatcher.messageQueue.append(new MessageHandle(key2, new Integer(i), new NullFutureResult))
|
||||||
|
}
|
||||||
|
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
|
||||||
|
assertFalse(threadingIssueDetected.get)
|
||||||
|
}
|
||||||
|
}
|
||||||
124
kernel/src/test/scala/ThreadBasedDispatcherTest.scala
Normal file
124
kernel/src/test/scala/ThreadBasedDispatcherTest.scala
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
package se.scalablesolutions.akka.kernel.reactor
|
||||||
|
|
||||||
|
import java.util.concurrent.BrokenBarrierException
|
||||||
|
import java.util.concurrent.CountDownLatch
|
||||||
|
import java.util.concurrent.CyclicBarrier
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import java.util.concurrent.TimeoutException
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import java.util.concurrent.locks.Lock
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.Assert._
|
||||||
|
|
||||||
|
class ThreadBasedDispatcherTest {
|
||||||
|
private var threadingIssueDetected: AtomicBoolean = null
|
||||||
|
|
||||||
|
@Before
|
||||||
|
def setUp = {
|
||||||
|
threadingIssueDetected = new AtomicBoolean(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def testMessagesDispatchedToTheSameHandlerAreExecutedSequentially = {
|
||||||
|
internalTestMessagesDispatchedToTheSameHandlerAreExecutedSequentially
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def testMessagesDispatchedToDifferentHandlersAreExecutedConcurrently = {
|
||||||
|
internalTestMessagesDispatchedToDifferentHandlersAreExecutedConcurrently
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
def testMessagesDispatchedToHandlersAreExecutedInFIFOOrder = {
|
||||||
|
internalTestMessagesDispatchedToHandlersAreExecutedInFIFOOrder
|
||||||
|
}
|
||||||
|
|
||||||
|
private def internalTestMessagesDispatchedToTheSameHandlerAreExecutedSequentially: Unit = {
|
||||||
|
val guardLock = new ReentrantLock
|
||||||
|
val handleLatch = new CountDownLatch(10)
|
||||||
|
val key = "key"
|
||||||
|
ThreadBasedDispatcher.registerHandler(key, new MessageHandler {
|
||||||
|
def handle(message: MessageHandle) {
|
||||||
|
try {
|
||||||
|
if (threadingIssueDetected.get) return
|
||||||
|
if (guardLock.tryLock) {
|
||||||
|
Thread.sleep(100)
|
||||||
|
handleLatch.countDown
|
||||||
|
} else {
|
||||||
|
threadingIssueDetected.set(true)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
case e: Exception => threadingIssueDetected.set(true)
|
||||||
|
} finally {
|
||||||
|
guardLock.unlock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ThreadBasedDispatcher.start
|
||||||
|
for (i <- 0 until 100) {
|
||||||
|
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key, new Object, new NullFutureResult))
|
||||||
|
}
|
||||||
|
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
|
||||||
|
assertFalse(threadingIssueDetected.get)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def internalTestMessagesDispatchedToDifferentHandlersAreExecutedConcurrently: Unit = {
|
||||||
|
val handlersBarrier = new CyclicBarrier(3)
|
||||||
|
val key1 = "key1"
|
||||||
|
val key2 = "key2"
|
||||||
|
ThreadBasedDispatcher.registerHandler(key1, new MessageHandler {
|
||||||
|
def handle(message: MessageHandle) = synchronized {
|
||||||
|
try {handlersBarrier.await(1, TimeUnit.SECONDS)}
|
||||||
|
catch {case e: Exception => threadingIssueDetected.set(true)}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ThreadBasedDispatcher.registerHandler(key2, new MessageHandler {
|
||||||
|
def handle(message: MessageHandle) = synchronized {
|
||||||
|
try {handlersBarrier.await(1, TimeUnit.SECONDS)}
|
||||||
|
catch {case e: Exception => threadingIssueDetected.set(true)}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ThreadBasedDispatcher.start
|
||||||
|
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key1, new Object, new NullFutureResult))
|
||||||
|
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key2, new Object, new NullFutureResult))
|
||||||
|
handlersBarrier.await(1, TimeUnit.SECONDS)
|
||||||
|
assertFalse(threadingIssueDetected.get)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def internalTestMessagesDispatchedToHandlersAreExecutedInFIFOOrder: Unit = {
|
||||||
|
val handleLatch = new CountDownLatch(200)
|
||||||
|
val key1 = "key1"
|
||||||
|
val key2 = "key2"
|
||||||
|
ThreadBasedDispatcher.registerHandler(key1, new MessageHandler {
|
||||||
|
var currentValue = -1;
|
||||||
|
def handle(message: MessageHandle) {
|
||||||
|
if (threadingIssueDetected.get) return
|
||||||
|
val messageValue = message.message.asInstanceOf[Int]
|
||||||
|
if (messageValue.intValue == currentValue + 1) {
|
||||||
|
currentValue = messageValue.intValue
|
||||||
|
handleLatch.countDown
|
||||||
|
} else threadingIssueDetected.set(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ThreadBasedDispatcher.registerHandler(key2, new MessageHandler {
|
||||||
|
var currentValue = -1;
|
||||||
|
def handle(message: MessageHandle) {
|
||||||
|
if (threadingIssueDetected.get) return
|
||||||
|
val messageValue = message.message.asInstanceOf[Int]
|
||||||
|
if (messageValue.intValue == currentValue + 1) {
|
||||||
|
currentValue = messageValue.intValue
|
||||||
|
handleLatch.countDown
|
||||||
|
} else threadingIssueDetected.set(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
ThreadBasedDispatcher.start
|
||||||
|
for (i <- 0 until 100) {
|
||||||
|
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key1, new Integer(i), new NullFutureResult))
|
||||||
|
ThreadBasedDispatcher.messageQueue.append(new MessageHandle(key2, new Integer(i), new NullFutureResult))
|
||||||
|
}
|
||||||
|
assertTrue(handleLatch.await(5, TimeUnit.SECONDS))
|
||||||
|
assertFalse(threadingIssueDetected.get)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue