diff --git a/src/main/java/com/serliunx/statemanagement/machine/ConcurrentStateMachine.java b/src/main/java/com/serliunx/statemanagement/machine/ConcurrentStateMachine.java new file mode 100644 index 0000000..2c40e51 --- /dev/null +++ b/src/main/java/com/serliunx/statemanagement/machine/ConcurrentStateMachine.java @@ -0,0 +1,11 @@ +package com.serliunx.statemanagement.machine; + +/** + * @author SerLiunx + * @version 1.0.0 + * @since 2025/2/6 + */ +public interface ConcurrentStateMachine extends StateMachine { + + boolean compareAndSet(S expectedValue, S newValue); +} diff --git a/src/main/java/com/serliunx/statemanagement/machine/DefaultConcurrentStateMachine.java b/src/main/java/com/serliunx/statemanagement/machine/DefaultConcurrentStateMachine.java new file mode 100644 index 0000000..8e5bbcd --- /dev/null +++ b/src/main/java/com/serliunx/statemanagement/machine/DefaultConcurrentStateMachine.java @@ -0,0 +1,132 @@ +package com.serliunx.statemanagement.machine; + +import com.serliunx.statemanagement.machine.handler.StateHandlerWrapper; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; + +/** + * @author SerLiunx + * @version 1.0.0 + * @since 2025/2/6 + */ +public class DefaultConcurrentStateMachine extends AbstractStateMachine implements ConcurrentStateMachine { + + /** + * 当前状态 + */ + private final AtomicInteger index = new AtomicInteger(0); + + DefaultConcurrentStateMachine(List stateList, + Map>> entryHandlers, + Map>> leaveHandlers, + Map>> exchangeHandlers, + Map>>> eventRegistries, + Executor executor, + Boolean async) { + super(stateList, entryHandlers, leaveHandlers, exchangeHandlers, eventRegistries, executor, async); + } + + @Override + public boolean compareAndSet(S expectedValue, S newValue) { + int current = indexOf(expectedValue); + int newIndex = indexOf(newValue); + if (current == -1 || newIndex == -1) + return false; + return index.compareAndSet(current, newIndex); + } + + /** + * 使用CAS不断尝试将当前状态重置回默认值(0) + * + * @param invokeHandlers 是否唤醒状态处理器 + */ + @Override + public void reset(boolean invokeHandlers) { + if (isDefault()) + return; + exchangeToTarget(0); + // TODO invokeHandlers + } + + @Override + public boolean switchTo(S state, boolean invokeHandlers) { + int i = indexOf(state); + if (i == -1 || + i == index.get()) { + return false; + } + exchangeToTarget(i); + return true; + } + + @Override + public S switchPrevAndGet(boolean invokeHandlers) { + S oldState = get(index.get()); + + S newState = get(index.get()); + if (invokeHandlers) + invokeHandlers(oldState, newState); + return newState; + } + + @Override + public S getAndSwitchPrev(boolean invokeHandlers) { + return super.getAndSwitchPrev(invokeHandlers); + } + + @Override + public void switchPrev(boolean invokeHandlers) { + super.switchPrev(invokeHandlers); + } + + @Override + public S switchNextAndGet(boolean invokeHandlers) { + return super.switchNextAndGet(invokeHandlers); + } + + @Override + public S getAndSwitchNext(boolean invokeHandlers) { + return super.getAndSwitchNext(invokeHandlers); + } + + @Override + public void switchNext(boolean invokeHandlers) { + super.switchNext(invokeHandlers); + } + + @Override + public void publish(Object event) { + + } + + /** + * 是否为默认状态 + */ + private boolean isDefault() { + return index.get() == 0; + } + + /** + * 移动下标至上一个状态 + */ + public void exchangeToPrev() { + final int size = size(); + } + + /** + * 切换到指定状态值 + *
  • 使用CAS一直尝试, 直到成功 + * + * @param target 目标值 + */ + private void exchangeToTarget(int target) { + int currentValue; + do { + currentValue = index.get(); + } while (!index.compareAndSet(currentValue, target)); + } +} diff --git a/src/main/java/com/serliunx/statemanagement/machine/StateMachine.java b/src/main/java/com/serliunx/statemanagement/machine/StateMachine.java index 4f2fc1f..84a8c6a 100644 --- a/src/main/java/com/serliunx/statemanagement/machine/StateMachine.java +++ b/src/main/java/com/serliunx/statemanagement/machine/StateMachine.java @@ -100,4 +100,7 @@ public interface StateMachine extends BidirectionalStateManager, AutoClose * @return 切换成功返回真, 否则返回假 */ boolean switchTo(S state); + + @Override + default void close() throws Exception {} } diff --git a/src/main/java/com/serliunx/statemanagement/machine/StateMachineBuilder.java b/src/main/java/com/serliunx/statemanagement/machine/StateMachineBuilder.java index f64e2d0..087a4cf 100644 --- a/src/main/java/com/serliunx/statemanagement/machine/StateMachineBuilder.java +++ b/src/main/java/com/serliunx/statemanagement/machine/StateMachineBuilder.java @@ -253,6 +253,9 @@ public final class StateMachineBuilder { if (type.equals(StateMachineType.STANDARD)) { return (M)new StandardStateMachine<>(stateList, entryHandlers, leaveHandlers, exchangeHandlers, eventRegistries, executor, async); + } else if (type.equals(StateMachineType.CONCURRENT)) { + return (M)new DefaultConcurrentStateMachine<>(stateList, entryHandlers, + leaveHandlers, exchangeHandlers, eventRegistries, executor, async); } throw new IllegalArgumentException("未知的状态机类型: " + type); } diff --git a/src/main/java/com/serliunx/statemanagement/manager/AbstractStateManager.java b/src/main/java/com/serliunx/statemanagement/manager/AbstractStateManager.java index 0ced3a5..b96615c 100644 --- a/src/main/java/com/serliunx/statemanagement/manager/AbstractStateManager.java +++ b/src/main/java/com/serliunx/statemanagement/manager/AbstractStateManager.java @@ -100,6 +100,11 @@ public abstract class AbstractStateManager implements StateManager { } } + @Override + public int size() { + return stateList.size(); + } + @Override public boolean isSwitchable() { return stateList.size() > 1; @@ -140,6 +145,16 @@ public abstract class AbstractStateManager implements StateManager { return stateList.get(index); } + /** + * 获取指定下标的状态 + * + * @param index 下标 + * @return 状态 + */ + protected S get(int index) { + return stateList.get(index); + } + /** * 获取指定状态在状态列表中的序号 * diff --git a/src/main/java/com/serliunx/statemanagement/manager/StateManager.java b/src/main/java/com/serliunx/statemanagement/manager/StateManager.java index 9fc63aa..dcada0b 100644 --- a/src/main/java/com/serliunx/statemanagement/manager/StateManager.java +++ b/src/main/java/com/serliunx/statemanagement/manager/StateManager.java @@ -31,6 +31,12 @@ public interface StateManager { */ void reset(); + /** + * 获取当前状态数量 + * @return 数量 + */ + int size(); + /** * 是否可切换 * diff --git a/src/test/java/com/serliunx/statemanagement/MachineTest.java b/src/test/java/com/serliunx/statemanagement/MachineTest.java index 509ca06..1359ad8 100644 --- a/src/test/java/com/serliunx/statemanagement/MachineTest.java +++ b/src/test/java/com/serliunx/statemanagement/MachineTest.java @@ -1,5 +1,6 @@ package com.serliunx.statemanagement; +import com.serliunx.statemanagement.machine.ConcurrentStateMachine; import com.serliunx.statemanagement.machine.StateMachine; import com.serliunx.statemanagement.machine.StateMachineBuilder; import com.serliunx.statemanagement.support.PrinterEvent;