mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
[+] TEngineServer
[+] TEngineServer
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine.Core
|
||||
{
|
||||
public sealed class CoroutineLockQueue : IDisposable
|
||||
{
|
||||
public long Key { get; private set; }
|
||||
public CoroutineLockQueueType CoroutineLockQueueType { get; private set; }
|
||||
private readonly Queue<WaitCoroutineLock> _waitCoroutineLocks = new Queue<WaitCoroutineLock>();
|
||||
|
||||
public static CoroutineLockQueue Create(long key, int time, CoroutineLockQueueType coroutineLockQueueType)
|
||||
{
|
||||
var coroutineLockQueue = Pool<CoroutineLockQueue>.Rent();
|
||||
coroutineLockQueue.Key = key;
|
||||
coroutineLockQueue.CoroutineLockQueueType = coroutineLockQueueType;
|
||||
return coroutineLockQueue;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Key = 0;
|
||||
CoroutineLockQueueType = null;
|
||||
Pool<CoroutineLockQueue>.Return(this);
|
||||
}
|
||||
|
||||
public async FTask<WaitCoroutineLock> Lock(string tag, int time)
|
||||
{
|
||||
#if TENGINE_DEVELOP
|
||||
if (_waitCoroutineLocks.Count >= 100)
|
||||
{
|
||||
// 当等待队列超过100个、表示这个协程锁可能有问题、打印一个警告方便排查错误
|
||||
Log.Warning($"too much waitCoroutineLock CoroutineLockQueueType:{CoroutineLockQueueType.Name} Key:{Key} Count: {_waitCoroutineLocks.Count} ");
|
||||
}
|
||||
#endif
|
||||
var waitCoroutineLock = WaitCoroutineLock.Create(this, tag, time);
|
||||
_waitCoroutineLocks.Enqueue(waitCoroutineLock);
|
||||
return await waitCoroutineLock.Tcs;
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
if (_waitCoroutineLocks.Count == 0)
|
||||
{
|
||||
CoroutineLockQueueType.Remove(Key);
|
||||
return;
|
||||
}
|
||||
|
||||
while (_waitCoroutineLocks.TryDequeue(out var waitCoroutineLock))
|
||||
{
|
||||
if (waitCoroutineLock.IsDisposed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
waitCoroutineLock.SetResult();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f07b80619d455d4499aefbc3eab9f65
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TEngine.Core
|
||||
{
|
||||
public sealed class CoroutineLockQueueType
|
||||
{
|
||||
public readonly string Name;
|
||||
private readonly Dictionary<long, CoroutineLockQueue> _coroutineLockQueues = new Dictionary<long, CoroutineLockQueue>();
|
||||
|
||||
private CoroutineLockQueueType() { }
|
||||
public CoroutineLockQueueType(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public async FTask<WaitCoroutineLock> Lock(long key, string tag = null, int time = 10000)
|
||||
{
|
||||
if (_coroutineLockQueues.TryGetValue(key, out var coroutineLockQueue))
|
||||
{
|
||||
return await coroutineLockQueue.Lock(tag,time);
|
||||
}
|
||||
|
||||
coroutineLockQueue = CoroutineLockQueue.Create(key, time, this);
|
||||
_coroutineLockQueues.Add(key, coroutineLockQueue);
|
||||
return WaitCoroutineLock.Create(coroutineLockQueue, tag, time);
|
||||
}
|
||||
|
||||
public void Remove(long key)
|
||||
{
|
||||
if (_coroutineLockQueues.Remove(key, out var coroutineLockQueue))
|
||||
{
|
||||
coroutineLockQueue.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2067a4304a800324bbe9c547eefac9fa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using TEngine.Core;
|
||||
|
||||
namespace TEngine.Core
|
||||
{
|
||||
public struct CoroutineLockTimeout
|
||||
{
|
||||
public long LockId;
|
||||
public WaitCoroutineLock WaitCoroutineLock;
|
||||
}
|
||||
|
||||
public sealed class OnCoroutineLockTimeout : EventSystem<CoroutineLockTimeout>
|
||||
{
|
||||
public override void Handler(CoroutineLockTimeout self)
|
||||
{
|
||||
if (self.LockId != self.WaitCoroutineLock.LockId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var coroutineLockQueue = self.WaitCoroutineLock.CoroutineLockQueue;
|
||||
var coroutineLockQueueType = coroutineLockQueue.CoroutineLockQueueType;
|
||||
var key = coroutineLockQueue.Key;
|
||||
Log.Error($"coroutine lock timeout CoroutineLockQueueType:{coroutineLockQueueType.Name} Key:{key} Tag:{self.WaitCoroutineLock.Tag}");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class WaitCoroutineLock : IDisposable
|
||||
{
|
||||
private long _timerId;
|
||||
public bool IsDisposed => LockId == 0;
|
||||
public string Tag { get; private set; }
|
||||
public long LockId { get; private set; }
|
||||
public FTask<WaitCoroutineLock> Tcs { get; private set; }
|
||||
public CoroutineLockQueue CoroutineLockQueue{ get; private set; }
|
||||
|
||||
public static WaitCoroutineLock Create(CoroutineLockQueue coroutineLockQueue, string tag, int timeOut)
|
||||
{
|
||||
var lockId = IdFactory.NextRunTimeId();
|
||||
var waitCoroutineLock = Pool<WaitCoroutineLock>.Rent();
|
||||
|
||||
waitCoroutineLock.Tag = tag;
|
||||
waitCoroutineLock.LockId = lockId;
|
||||
waitCoroutineLock.CoroutineLockQueue = coroutineLockQueue;
|
||||
waitCoroutineLock.Tcs = FTask<WaitCoroutineLock>.Create();
|
||||
waitCoroutineLock._timerId = TimerScheduler.Instance.Core.OnceTimer(timeOut, new CoroutineLockTimeout()
|
||||
{
|
||||
LockId = lockId, WaitCoroutineLock = waitCoroutineLock
|
||||
});
|
||||
|
||||
return waitCoroutineLock;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (IsDisposed)
|
||||
{
|
||||
Log.Error("WaitCoroutineLock is Dispose");
|
||||
return;
|
||||
}
|
||||
|
||||
Release(CoroutineLockQueue);
|
||||
|
||||
LockId = 0;
|
||||
Tcs = null;
|
||||
Tag = null;
|
||||
CoroutineLockQueue = null;
|
||||
|
||||
if (_timerId != 0)
|
||||
{
|
||||
TimerScheduler.Instance.Core.RemoveByRef(ref _timerId);
|
||||
}
|
||||
|
||||
Pool<WaitCoroutineLock>.Return(this);
|
||||
}
|
||||
|
||||
private static void Release(CoroutineLockQueue coroutineLockQueue)
|
||||
{
|
||||
// 放到下一帧执行释放锁、如果不这样、会导致逻辑的顺序不正常
|
||||
ThreadSynchronizationContext.Main.Post(coroutineLockQueue.Release);
|
||||
}
|
||||
|
||||
public void SetResult()
|
||||
{
|
||||
if (Tcs == null)
|
||||
{
|
||||
throw new NullReferenceException("SetResult tcs is null");
|
||||
}
|
||||
|
||||
Tcs.SetResult(this);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ee0d61ec53909c4695fe2ecc97f42bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user