mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
[+] 接入ET8服务端
[+] 接入ET8服务端
This commit is contained in:
313
Assets/GameScripts/ThirdParty/ETTask/ETTask.cs
vendored
Normal file
313
Assets/GameScripts/ThirdParty/ETTask/ETTask.cs
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.ExceptionServices;
|
||||
|
||||
namespace ET
|
||||
{
|
||||
[AsyncMethodBuilder(typeof (ETAsyncTaskMethodBuilder))]
|
||||
public class ETTask: ICriticalNotifyCompletion
|
||||
{
|
||||
public static Action<Exception> ExceptionHandler;
|
||||
|
||||
public static ETTaskCompleted CompletedTask
|
||||
{
|
||||
get
|
||||
{
|
||||
return new ETTaskCompleted();
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ConcurrentQueue<ETTask> queue = new();
|
||||
|
||||
/// <summary>
|
||||
/// 请不要随便使用ETTask的对象池,除非你完全搞懂了ETTask!!!
|
||||
/// 假如开启了池,await之后不能再操作ETTask,否则可能操作到再次从池中分配出来的ETTask,产生灾难性的后果
|
||||
/// SetResult的时候请现将tcs置空,避免多次对同一个ETTask SetResult
|
||||
/// </summary>
|
||||
public static ETTask Create(bool fromPool = false)
|
||||
{
|
||||
if (!fromPool)
|
||||
{
|
||||
return new ETTask();
|
||||
}
|
||||
if (!queue.TryDequeue(out ETTask task))
|
||||
{
|
||||
return new ETTask() {fromPool = true};
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
private void Recycle()
|
||||
{
|
||||
if (!this.fromPool)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.state = AwaiterStatus.Pending;
|
||||
this.callback = null;
|
||||
// 太多了
|
||||
if (queue.Count > 1000)
|
||||
{
|
||||
return;
|
||||
}
|
||||
queue.Enqueue(this);
|
||||
}
|
||||
|
||||
private bool fromPool;
|
||||
private AwaiterStatus state;
|
||||
private object callback; // Action or ExceptionDispatchInfo
|
||||
|
||||
private ETTask()
|
||||
{
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
private async ETVoid InnerCoroutine()
|
||||
{
|
||||
await this;
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void Coroutine()
|
||||
{
|
||||
InnerCoroutine().Coroutine();
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public ETTask GetAwaiter()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public bool IsCompleted
|
||||
{
|
||||
[DebuggerHidden]
|
||||
get
|
||||
{
|
||||
return this.state != AwaiterStatus.Pending;
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void UnsafeOnCompleted(Action action)
|
||||
{
|
||||
if (this.state != AwaiterStatus.Pending)
|
||||
{
|
||||
action?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
this.callback = action;
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void OnCompleted(Action action)
|
||||
{
|
||||
this.UnsafeOnCompleted(action);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void GetResult()
|
||||
{
|
||||
switch (this.state)
|
||||
{
|
||||
case AwaiterStatus.Succeeded:
|
||||
this.Recycle();
|
||||
break;
|
||||
case AwaiterStatus.Faulted:
|
||||
ExceptionDispatchInfo c = this.callback as ExceptionDispatchInfo;
|
||||
this.callback = null;
|
||||
this.Recycle();
|
||||
c?.Throw();
|
||||
break;
|
||||
default:
|
||||
throw new NotSupportedException("ETTask does not allow call GetResult directly when task not completed. Please use 'await'.");
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void SetResult()
|
||||
{
|
||||
if (this.state != AwaiterStatus.Pending)
|
||||
{
|
||||
throw new InvalidOperationException("TaskT_TransitionToFinal_AlreadyCompleted");
|
||||
}
|
||||
|
||||
this.state = AwaiterStatus.Succeeded;
|
||||
|
||||
Action c = this.callback as Action;
|
||||
this.callback = null;
|
||||
c?.Invoke();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[DebuggerHidden]
|
||||
public void SetException(Exception e)
|
||||
{
|
||||
if (this.state != AwaiterStatus.Pending)
|
||||
{
|
||||
throw new InvalidOperationException("TaskT_TransitionToFinal_AlreadyCompleted");
|
||||
}
|
||||
|
||||
this.state = AwaiterStatus.Faulted;
|
||||
|
||||
Action c = this.callback as Action;
|
||||
this.callback = ExceptionDispatchInfo.Capture(e);
|
||||
c?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
[AsyncMethodBuilder(typeof (ETAsyncTaskMethodBuilder<>))]
|
||||
public class ETTask<T>: ICriticalNotifyCompletion
|
||||
{
|
||||
private static readonly ConcurrentQueue<ETTask<T>> queue = new();
|
||||
|
||||
/// <summary>
|
||||
/// 请不要随便使用ETTask的对象池,除非你完全搞懂了ETTask!!!
|
||||
/// 假如开启了池,await之后不能再操作ETTask,否则可能操作到再次从池中分配出来的ETTask,产生灾难性的后果
|
||||
/// SetResult的时候请现将tcs置空,避免多次对同一个ETTask SetResult
|
||||
/// </summary>
|
||||
public static ETTask<T> Create(bool fromPool = false)
|
||||
{
|
||||
if (!fromPool)
|
||||
{
|
||||
return new ETTask<T>();
|
||||
}
|
||||
|
||||
if (!queue.TryDequeue(out ETTask<T> task))
|
||||
{
|
||||
return new ETTask<T>() {fromPool = true};
|
||||
}
|
||||
return task;
|
||||
}
|
||||
|
||||
private void Recycle()
|
||||
{
|
||||
if (!this.fromPool)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.callback = null;
|
||||
this.value = default;
|
||||
this.state = AwaiterStatus.Pending;
|
||||
// 太多了
|
||||
if (queue.Count > 1000)
|
||||
{
|
||||
return;
|
||||
}
|
||||
queue.Enqueue(this);
|
||||
}
|
||||
|
||||
private bool fromPool;
|
||||
private AwaiterStatus state;
|
||||
private T value;
|
||||
private object callback; // Action or ExceptionDispatchInfo
|
||||
|
||||
private ETTask()
|
||||
{
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
private async ETVoid InnerCoroutine()
|
||||
{
|
||||
await this;
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void Coroutine()
|
||||
{
|
||||
InnerCoroutine().Coroutine();
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public ETTask<T> GetAwaiter()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public T GetResult()
|
||||
{
|
||||
switch (this.state)
|
||||
{
|
||||
case AwaiterStatus.Succeeded:
|
||||
T v = this.value;
|
||||
this.Recycle();
|
||||
return v;
|
||||
case AwaiterStatus.Faulted:
|
||||
ExceptionDispatchInfo c = this.callback as ExceptionDispatchInfo;
|
||||
this.callback = null;
|
||||
this.Recycle();
|
||||
c?.Throw();
|
||||
return default;
|
||||
default:
|
||||
throw new NotSupportedException("ETask does not allow call GetResult directly when task not completed. Please use 'await'.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool IsCompleted
|
||||
{
|
||||
[DebuggerHidden]
|
||||
get
|
||||
{
|
||||
return state != AwaiterStatus.Pending;
|
||||
}
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void UnsafeOnCompleted(Action action)
|
||||
{
|
||||
if (this.state != AwaiterStatus.Pending)
|
||||
{
|
||||
action?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
this.callback = action;
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void OnCompleted(Action action)
|
||||
{
|
||||
this.UnsafeOnCompleted(action);
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void SetResult(T result)
|
||||
{
|
||||
if (this.state != AwaiterStatus.Pending)
|
||||
{
|
||||
throw new InvalidOperationException("TaskT_TransitionToFinal_AlreadyCompleted");
|
||||
}
|
||||
|
||||
this.state = AwaiterStatus.Succeeded;
|
||||
|
||||
this.value = result;
|
||||
|
||||
Action c = this.callback as Action;
|
||||
this.callback = null;
|
||||
c?.Invoke();
|
||||
}
|
||||
|
||||
[DebuggerHidden]
|
||||
public void SetException(Exception e)
|
||||
{
|
||||
if (this.state != AwaiterStatus.Pending)
|
||||
{
|
||||
throw new InvalidOperationException("TaskT_TransitionToFinal_AlreadyCompleted");
|
||||
}
|
||||
|
||||
this.state = AwaiterStatus.Faulted;
|
||||
|
||||
Action c = this.callback as Action;
|
||||
this.callback = ExceptionDispatchInfo.Capture(e);
|
||||
c?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user