Files
BITKit/Src/Core/Utility/ValidHandle.cs

207 lines
5.8 KiB
C#
Raw Normal View History

2023-06-05 19:57:17 +08:00
using System;
2025-01-12 11:13:19 +08:00
using System.Collections.Concurrent;
2023-06-05 19:57:17 +08:00
using System.Collections.Generic;
2024-11-08 17:28:07 +08:00
using Cysharp.Threading.Tasks;
2023-06-05 19:57:17 +08:00
namespace BITKit
{
2023-11-15 23:55:06 +08:00
public interface IValidHandle
{
bool Allow { get; }
void AddElement(object obj);
void RemoveElement(object obj);
void AddDisableElements(object obj);
void RemoveDisableElements(object obj);
void SetElements(object obj, bool add = true);
void SetDisableElements(object obj, bool add = true);
void Invoke();
void Invoke(bool value);
void AddListener(Action<bool> action);
void RemoveListener(Action<bool> action);
void Clear();
}
[CustomType(typeof(IValidHandle))]
2024-12-25 11:35:30 +08:00
public sealed class ValidHandle: IValidHandle,IDisposable
2023-06-05 19:57:17 +08:00
{
2024-11-08 17:28:07 +08:00
public class MyHandle:IDisposable
{
private readonly ValidHandle _validHandle;
2025-03-09 13:38:23 +08:00
private readonly bool _isDisable;
2024-11-20 11:36:51 +08:00
public MyHandle(ValidHandle validHandle,bool isDisable = false)
2024-11-08 17:28:07 +08:00
{
_validHandle = validHandle;
2024-11-20 11:36:51 +08:00
_isDisable = isDisable;
if (isDisable)
{
_validHandle.AddDisableElements(this);
}
else
{
_validHandle.AddElement(this);
}
2024-11-08 17:28:07 +08:00
}
public void Dispose()
{
2024-11-20 11:36:51 +08:00
if (_isDisable)
{
_validHandle.RemoveDisableElements(this);
}
else
{
_validHandle.RemoveElement(this);
}
2024-11-08 17:28:07 +08:00
}
}
public MyHandle GetHandle() => new MyHandle(this);
2024-11-20 11:36:51 +08:00
public MyHandle GetDisableHandle()=> new MyHandle(this,true);
2024-11-08 17:28:07 +08:00
2024-03-31 23:31:00 +08:00
public override string ToString()
{
2025-03-09 13:38:23 +08:00
return $"Allow:{_enableHandle}\nElements:{string.Join("\n",_objs)}\nDisableElements:{string.Join("\n",_disableObjs)}";
2024-03-31 23:31:00 +08:00
}
2023-10-06 23:43:19 +08:00
public ValidHandle() {}
2023-06-05 19:57:17 +08:00
public ValidHandle(Action<bool> boolDelegate)
{
AddListener(boolDelegate);
2025-03-09 13:38:23 +08:00
_eventOnEnableChanged?.Invoke(_enableHandle);
2023-06-05 19:57:17 +08:00
}
public static implicit operator bool(ValidHandle validHandle)
{
2025-03-09 13:38:23 +08:00
return !validHandle._isDisposed && validHandle._enableHandle;
2023-06-05 19:57:17 +08:00
}
2023-08-11 23:57:37 +08:00
public bool Allow => this;
2025-03-09 13:38:23 +08:00
private bool _enableHandle;
2024-03-31 23:31:00 +08:00
/// <summary>
/// ⚠Dont operate this field directly
/// </summary>
2025-03-09 13:38:23 +08:00
private readonly HashSet<object> _objs = new();
2024-03-31 23:31:00 +08:00
/// <summary>
/// ⚠Dont operate this field directly
/// </summary>
2025-03-09 13:38:23 +08:00
private readonly HashSet<object> _disableObjs = new();
private bool _tempEnable;
2025-04-05 09:49:01 +08:00
private event Action<bool> _eventOnEnableChanged;
2025-01-12 11:13:19 +08:00
private readonly ConcurrentQueue<UniTaskCompletionSource> _completionSources = new();
2024-12-25 11:35:30 +08:00
private bool _isDisposed;
2024-03-31 23:31:00 +08:00
2023-11-15 23:55:06 +08:00
public void AddElement(object obj)
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
_objs.Add(obj);
2023-06-05 19:57:17 +08:00
CheckEnable();
}
2023-11-15 23:55:06 +08:00
private void CheckEnable()
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
_tempEnable = _objs.Count > 0 && _disableObjs.Count == 0;
if (_tempEnable == _enableHandle) return;
_enableHandle = _tempEnable;
_eventOnEnableChanged?.Invoke(_enableHandle);
if (_tempEnable) return;
if (_completionSources.TryDequeue(out var cs))
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
cs.TrySetResult();
2023-06-05 19:57:17 +08:00
}
}
2023-11-15 23:55:06 +08:00
public void RemoveElement(object obj)
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
if (_objs.Contains(obj))
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
_objs.Remove(obj);
2023-06-05 19:57:17 +08:00
}
CheckEnable();
}
2025-03-09 13:38:23 +08:00
public int Lenght => _objs.Count;
public bool Contains(object obj) => _objs.Contains(obj);
2023-11-15 23:55:06 +08:00
public void AddDisableElements(object obj)
2023-06-05 19:57:17 +08:00
{
2025-04-05 09:49:01 +08:00
if (_disableObjs.Add(obj))
{
CheckEnable();
}
2023-06-05 19:57:17 +08:00
}
2023-10-06 23:43:19 +08:00
public void RemoveDisableElements(object obj)
2023-06-05 19:57:17 +08:00
{
2025-04-05 09:49:01 +08:00
if (_disableObjs.Remove(obj))
2023-06-05 19:57:17 +08:00
{
2025-04-05 09:49:01 +08:00
CheckEnable();
2023-06-05 19:57:17 +08:00
}
}
2023-10-06 23:43:19 +08:00
public void SetElements(object obj, bool add = true)
2023-06-05 19:57:17 +08:00
{
if (add)
{
AddElement(obj);
}
else
{
RemoveElement(obj);
}
}
2023-11-15 23:55:06 +08:00
public void SetDisableElements(object obj, bool add = true)
2023-06-05 19:57:17 +08:00
{
if (add)
{
AddDisableElements(obj);
}
else
{
RemoveDisableElements(obj);
}
}
2023-10-06 23:43:19 +08:00
public void Invoke()
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
var enable = _disableObjs.Count == 0 && _objs.Count > 0;
2025-04-05 09:49:01 +08:00
Invoke(enable);
2023-06-05 19:57:17 +08:00
}
2023-10-06 23:43:19 +08:00
public void Invoke(bool value)
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
_eventOnEnableChanged?.Invoke(value);
2023-06-05 19:57:17 +08:00
}
2023-10-06 23:43:19 +08:00
public void AddListener(Action<bool> action)
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
_eventOnEnableChanged+= action;
2023-06-05 19:57:17 +08:00
}
2023-10-06 23:43:19 +08:00
public void RemoveListener(Action<bool> action)
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
if(_eventOnEnableChanged is not null && action is not null)
2023-06-05 19:57:17 +08:00
{
2025-03-09 13:38:23 +08:00
_eventOnEnableChanged -= action;
2023-06-05 19:57:17 +08:00
}
}
2024-11-08 17:28:07 +08:00
public UniTask.Awaiter GetAwaiter()
{
if (Allow is false)
{
return UniTask.CompletedTask.GetAwaiter();
}
var cs = new UniTaskCompletionSource();
2024-11-20 11:36:51 +08:00
_completionSources.Enqueue(cs);
2024-11-08 17:28:07 +08:00
return cs.Task.GetAwaiter();
}
2023-10-06 23:43:19 +08:00
public void Clear()
{
2025-03-09 13:38:23 +08:00
_objs.Clear();
_disableObjs.Clear();
2023-10-06 23:43:19 +08:00
Invoke();
}
2024-12-25 11:35:30 +08:00
public void Dispose()
{
_isDisposed = true;
2025-03-09 13:38:23 +08:00
_objs.Clear();
_disableObjs.Clear();
_eventOnEnableChanged = null;
2024-12-25 11:35:30 +08:00
}
2023-06-05 19:57:17 +08:00
}
2023-10-06 23:43:19 +08:00
2023-06-05 19:57:17 +08:00
}