using System;
using System.Collections.Concurrent;
using TBL.CSharp.Game.Server.Message;
using TBL.CSharp.Game.Server.Process;
namespace TBL.CSharp.Game.Server;
///
/// 服务容器
///
public class ServiceContainer
{
///
/// 下一个候选服务句柄
///
private int _nextServiceHandle;
///
/// 活跃中的服务队列
///
public readonly ConcurrentQueue ActiveSignalQueues;
///
/// 服务句柄映射
///
public readonly ConcurrentDictionary ServicesHandleMap;
///
/// 工作线程封装组
///
public readonly ConcurrentBag Workers;
public ServiceContainer(
Func workerProvider,
int workerCount
)
{
workerCount = Math.Max(workerCount, 1);
_nextServiceHandle = 0;
ActiveSignalQueues = new ConcurrentQueue();
ServicesHandleMap = new ConcurrentDictionary();
Workers = new ConcurrentBag();
for (var i = 0; i < workerCount; i++)
{
var worker = workerProvider(this);
Workers.Add(worker);
worker.WorkingThread.Start();
}
}
///
/// 添加服务
///
public void AddService(Service service)
{
if (service.Container != null)
{
throw new Exception($"service {service} already added");
}
for (;;)
{
if (ServicesHandleMap.TryAdd(_nextServiceHandle, service))
{
service.Handle = _nextServiceHandle;
service.Container = this;
break;
}
if (_nextServiceHandle == int.MaxValue)
_nextServiceHandle = 0;
else
_nextServiceHandle += 1;
}
}
///
/// 解析出服务句柄
///
public int ResolveServiceHandle(string name)
{
lock (ServicesHandleMap)
{
foreach (var pair in ServicesHandleMap)
{
if (name == pair.Value.GetType().FullName)
return pair.Key;
}
}
return -1;
}
///
/// 向指定服务传递信号
///
public void Send(Signal signal)
{
if (ServicesHandleMap.TryGetValue(signal.TargetAddress.ServiceHandle, out var targetService))
{
var queue = targetService.SignalQueue;
queue.Enqueue(signal);
// 对队列加锁
lock (queue)
{
// 非活跃的情况下,使其进入活跃序列
if (!queue.ActiveLock)
{
queue.ActiveLock = true;
ActiveSignalQueues.Enqueue(queue);
}
}
}
}
///
/// 清空
///
public void Clear(bool forceStop = false)
{
// 工作线程关闭
while (Workers.TryTake(out var worker))
{
if (forceStop)
worker.WorkingThread.Abort();
else
worker.RequestStop();
}
}
}