Skip to content

Instantly share code, notes, and snippets.

@dyguests
Last active October 17, 2022 14:05
Show Gist options
  • Save dyguests/726a77aea36ebd2c4a9a51217159ac71 to your computer and use it in GitHub Desktop.
Save dyguests/726a77aea36ebd2c4a9a51217159ac71 to your computer and use it in GitHub Desktop.
BufferHandler, BufferedHandler, SpoolHandler, 缓存处理, 多个操作连续处理
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using JetBrains.Annotations;
namespace Plugins.FanhlCores.Tools
{
public class BufferHandler<T>
{
private readonly Queue<T> items = new();
private readonly Func<T, UniTask> handleAction;
private readonly int bufferSize;
private bool handling;
private bool Handling
{
get => handling;
set
{
var oldHandling = handling;
handling = value;
if (oldHandling != handling)
{
onHandlingChanged?.Invoke(handling);
}
}
}
public delegate void OnHandlingChanged(bool handling);
public OnHandlingChanged onHandlingChanged;
public BufferHandler([NotNull] Func<T, UniTask> handleAction, int bufferSize = -1)
{
this.bufferSize = bufferSize;
this.handleAction = handleAction;
}
public void Handle(T t)
{
lock (items)
{
if (Handling)
{
Enqueue(t);
}
else
{
Handling = true;
HandleInternal(t);
}
}
}
private async void HandleInternal(T t)
{
await handleAction(t);
OnHandleActionCompleted();
}
private void OnHandleActionCompleted()
{
lock (items)
{
if (items.Count > 0)
{
HandleInternal(Dequeue());
}
else
{
Handling = false;
}
}
}
private void Enqueue(T t)
{
if (bufferSize >= 0 && items.Count + 1 > bufferSize)
{
// TODO remove last?
items.Dequeue();
}
items.Enqueue(t);
}
private T Dequeue()
{
return items.Dequeue();
}
}
}
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using JetBrains.Annotations;
using UnityEngine;
namespace Plugins.FanhlCores.Tools
{
public class SpoolHandler<T>
{
private readonly Queue<SpoolItem> items = new();
private readonly Func<T, UniTask> handleAction;
private readonly int bufferSize;
private readonly float bufferTime;
private bool handling;
public SpoolHandler([NotNull] Func<T, UniTask> handleAction, int bufferSize = -1, float bufferTime = -1f)
{
this.bufferSize = bufferSize;
this.bufferTime = bufferTime;
this.handleAction = handleAction;
}
public void Handle(T t)
{
lock (items)
{
if (handling)
{
Enqueue(new SpoolItem
{
item = t,
time = Time.fixedTime,
});
}
else
{
handling = true;
HandleInternal(t);
}
}
}
private async void HandleInternal(T t)
{
await handleAction(t);
OnHandleActionCompleted();
}
private void OnHandleActionCompleted()
{
lock (items)
{
if (items.Count > 0)
{
var spoolItem = Dequeue();
if (bufferTime < 0f || Time.fixedTime - spoolItem.time < bufferTime + float.Epsilon)
{
// Debug.Log("OnHandleActionCompleted in buffer");
// handleAction(spoolItem.item, OnHandleActionCompleted);
HandleInternal(spoolItem.item);
}
else
{
// Debug.Log("OnHandleActionCompleted out buffer");
OnHandleActionCompleted();
}
}
else
{
// Debug.Log("OnHandleActionCompleted handling = false");
handling = false;
}
}
}
private void Enqueue(SpoolItem spoolItem)
{
if (bufferSize >= 0 && items.Count + 1 > bufferSize)
{
// TODO remove last?
items.Dequeue();
}
items.Enqueue(spoolItem);
}
private SpoolItem Dequeue()
{
return items.Dequeue();
}
private struct SpoolItem
{
public T item;
public float time;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment