blob: 3942a3a1bc198826de2945b24cae3bdda2fe761e [file] [log] [blame]
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace DotPulsar.Internal;
using Abstractions;
using System.Threading;
using System.Threading.Tasks;
public sealed class StateManager<TState> : IStateManager<TState> where TState : notnull
{
private readonly object _lock;
private readonly StateTaskCollection<TState> _stateTasks;
private readonly TState[] _finalStates;
public StateManager(TState initialState, params TState[] finalStates)
{
_lock = new object();
_stateTasks = new StateTaskCollection<TState>();
_finalStates = finalStates;
CurrentState = initialState;
}
public TState CurrentState { get; private set; }
public TState SetState(TState state)
{
lock (_lock)
{
if (IsFinalState(CurrentState) || CurrentState.Equals(state))
return CurrentState;
var formerState = CurrentState;
CurrentState = state;
if (IsFinalState(CurrentState))
_stateTasks.CompleteAllTasks(CurrentState);
else
_stateTasks.CompleteTasksAwaiting(CurrentState);
return formerState;
}
}
public ValueTask<TState> StateChangedTo(TState state, CancellationToken cancellationToken)
{
lock (_lock)
{
if (IsFinalState(CurrentState) || CurrentState.Equals(state))
return new ValueTask<TState>(CurrentState);
return new ValueTask<TState>(_stateTasks.CreateTaskFor(state, StateChanged.To, cancellationToken));
}
}
public ValueTask<TState> StateChangedFrom(TState state, CancellationToken cancellationToken)
{
lock (_lock)
{
if (IsFinalState(CurrentState) || !CurrentState.Equals(state))
return new ValueTask<TState>(CurrentState);
return new ValueTask<TState>(_stateTasks.CreateTaskFor(state, StateChanged.From, cancellationToken));
}
}
public bool IsFinalState(TState state)
{
for (var i = 0; i < _finalStates.Length; ++i)
{
if (_finalStates[i].Equals(state))
return true;
}
return false;
}
public bool IsFinalState()
=> IsFinalState(CurrentState);
}