备份CatanBuilding瘦身独立工程
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
namespace com.fpnn
|
||||
{
|
||||
public static partial class ClientEngine
|
||||
{
|
||||
private static volatile bool inited;
|
||||
private static volatile bool stopped;
|
||||
private static object interLocker;
|
||||
private static Thread routineThread;
|
||||
private static Semaphore quitSemaphore;
|
||||
private static bool forbiddenRegisterConnection; //-- Unity iOS only.
|
||||
private static Dictionary<TCPConnection, Int64> connectingConnections;
|
||||
private static HashSet<TCPConnection> allConnections;
|
||||
private static common.TaskThreadPool taskPool;
|
||||
private static bool dropAllTaskWhenQuit;
|
||||
|
||||
internal static DateTime originDateTime;
|
||||
internal static int globalConnectTimeoutSeconds;
|
||||
internal static int globalQuestTimeoutSeconds;
|
||||
internal static int maxPayloadSize;
|
||||
internal static bool closeConnectionsWhenBackground;
|
||||
internal static common.ErrorRecorder errorRecorder;
|
||||
|
||||
static partial void PlatformInit(); //-- In lock (interLocker) {...}
|
||||
static partial void PlatformUninit();
|
||||
|
||||
static ClientEngine()
|
||||
{
|
||||
inited = false;
|
||||
interLocker = new object();
|
||||
}
|
||||
|
||||
/*
|
||||
* Is NOT necessary, just uniform the interfaces with Unity version.
|
||||
*/
|
||||
public static void Init()
|
||||
{
|
||||
Init(null);
|
||||
}
|
||||
|
||||
/*
|
||||
* Customized Init.
|
||||
*/
|
||||
public static void Init(Config config)
|
||||
{
|
||||
if (inited)
|
||||
return;
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
if (inited)
|
||||
return;
|
||||
|
||||
if (config == null)
|
||||
config = new Config();
|
||||
|
||||
//---------------------
|
||||
|
||||
stopped = false;
|
||||
forbiddenRegisterConnection = false;
|
||||
connectingConnections = new Dictionary<TCPConnection, long>();
|
||||
allConnections = new HashSet<TCPConnection>();
|
||||
originDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
dropAllTaskWhenQuit = config.dropAllUnexecutedTaskWhenExiting;
|
||||
globalConnectTimeoutSeconds = config.globalConnectTimeoutSeconds;
|
||||
globalQuestTimeoutSeconds = config.globalQuestTimeoutSeconds;
|
||||
maxPayloadSize = config.maxPayloadSize;
|
||||
closeConnectionsWhenBackground = config.closeConnectionsWhenBackground;
|
||||
errorRecorder = config.errorRecorder;
|
||||
|
||||
taskPool = new common.TaskThreadPool(config.taskThreadPoolConfig.initThreadCount,
|
||||
config.taskThreadPoolConfig.perfectThreadCount,
|
||||
config.taskThreadPoolConfig.maxThreadCount,
|
||||
config.taskThreadPoolConfig.maxQueueLengthLimitation,
|
||||
config.taskThreadPoolConfig.tempLatencySeconds,
|
||||
dropAllTaskWhenQuit
|
||||
);
|
||||
|
||||
taskPool.SetErrorRecorder(config.errorRecorder);
|
||||
|
||||
routineThread = new Thread(RoutineFunc)
|
||||
{
|
||||
Name = "FPNN.ClientEngine.RoutineThread",
|
||||
IsBackground = true
|
||||
};
|
||||
routineThread.Start();
|
||||
|
||||
//---------------------
|
||||
|
||||
PlatformInit();
|
||||
|
||||
inited = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckInitStatus()
|
||||
{
|
||||
Init(null);
|
||||
}
|
||||
|
||||
private static void RoutineFunc()
|
||||
{
|
||||
while (!stopped)
|
||||
{
|
||||
Thread.Sleep(1000);
|
||||
|
||||
Int64 currentSeconds = GetCurrentSeconds();
|
||||
HashSet<TCPConnection> checkingConnections;
|
||||
HashSet<TCPConnection> connectingTimeoutedConnections;
|
||||
|
||||
try
|
||||
{
|
||||
checkingConnections = new HashSet<TCPConnection>();
|
||||
connectingTimeoutedConnections = new HashSet<TCPConnection>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
errorRecorder?.RecordError(e);
|
||||
continue;
|
||||
}
|
||||
|
||||
lock (interLocker)
|
||||
{
|
||||
foreach (TCPConnection conn in allConnections)
|
||||
checkingConnections.Add(conn);
|
||||
|
||||
foreach (KeyValuePair<TCPConnection, Int64> kvp in connectingConnections)
|
||||
{
|
||||
if (kvp.Value <= currentSeconds)
|
||||
connectingTimeoutedConnections.Add(kvp.Key);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (TCPConnection conn in connectingTimeoutedConnections)
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
|
||||
currentSeconds = GetCurrentSeconds();
|
||||
foreach (TCPConnection conn in checkingConnections)
|
||||
{
|
||||
conn.CleanTimeoutedCallbacks(currentSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
StopAllConnections();
|
||||
quitSemaphore.Release();
|
||||
}
|
||||
|
||||
/*
|
||||
* Only for Unity on iOS devices when apps is going to background.
|
||||
*/
|
||||
internal static void StopAllConnections()
|
||||
{
|
||||
if (inited == false)
|
||||
return;
|
||||
|
||||
CheckInitStatus();
|
||||
|
||||
HashSet<TCPConnection> currentConnections = new HashSet<TCPConnection>();
|
||||
lock (interLocker)
|
||||
{
|
||||
foreach (TCPConnection conn in allConnections)
|
||||
currentConnections.Add(conn);
|
||||
}
|
||||
|
||||
foreach (TCPConnection conn in currentConnections)
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Only for Unity on iOS devices when apps is going to background.
|
||||
*/
|
||||
internal static void ChangeForbiddenRegisterConnection(bool forbidden)
|
||||
{
|
||||
lock (interLocker)
|
||||
{
|
||||
forbiddenRegisterConnection = forbidden;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool RegisterConnectingConnection(TCPConnection conn, int connectTimeout)
|
||||
{
|
||||
CheckInitStatus();
|
||||
lock (interLocker)
|
||||
{
|
||||
if (forbiddenRegisterConnection) //-- Unity iOS only.
|
||||
return false;
|
||||
|
||||
if (connectTimeout <= 0)
|
||||
connectTimeout = globalQuestTimeoutSeconds;
|
||||
|
||||
connectingConnections.Add(conn, GetCurrentSeconds() + connectTimeout);
|
||||
allConnections.Add(conn);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static bool RegisterConnectedConnection(TCPConnection conn)
|
||||
{
|
||||
CheckInitStatus();
|
||||
lock (interLocker)
|
||||
{
|
||||
if (forbiddenRegisterConnection) //-- Unity iOS only.
|
||||
return false;
|
||||
|
||||
connectingConnections.Remove(conn);
|
||||
allConnections.Add(conn);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal static void UnregisterConnection(TCPConnection conn)
|
||||
{
|
||||
CheckInitStatus();
|
||||
lock (interLocker)
|
||||
{
|
||||
connectingConnections.Remove(conn);
|
||||
allConnections.Remove(conn);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool RunTask(common.TaskThreadPool.ITask task)
|
||||
{
|
||||
CheckInitStatus();
|
||||
return taskPool.Wakeup(task);
|
||||
}
|
||||
|
||||
public static bool RunTask(Action action)
|
||||
{
|
||||
CheckInitStatus();
|
||||
return taskPool.Wakeup(action);
|
||||
}
|
||||
|
||||
public static Int64 GetCurrentSeconds()
|
||||
{
|
||||
TimeSpan span = DateTime.UtcNow - originDateTime;
|
||||
return (Int64)Math.Floor(span.TotalSeconds);
|
||||
}
|
||||
|
||||
public static Int64 GetCurrentMilliseconds()
|
||||
{
|
||||
TimeSpan span = DateTime.UtcNow - originDateTime;
|
||||
return (Int64)Math.Floor(span.TotalMilliseconds);
|
||||
}
|
||||
|
||||
public static Int64 GetCurrentMicroseconds()
|
||||
{
|
||||
TimeSpan span = DateTime.UtcNow - originDateTime;
|
||||
return (Int64)Math.Floor(span.TotalMilliseconds * 1000);
|
||||
}
|
||||
|
||||
public static void Close()
|
||||
{
|
||||
lock (interLocker)
|
||||
{
|
||||
if (inited == false)
|
||||
return;
|
||||
if (stopped)
|
||||
return;
|
||||
|
||||
quitSemaphore = new Semaphore(0, 1);
|
||||
stopped = true;
|
||||
}
|
||||
quitSemaphore.WaitOne();
|
||||
quitSemaphore.Close();
|
||||
quitSemaphore = null;
|
||||
inited = false;
|
||||
|
||||
PlatformUninit();
|
||||
taskPool.Close(dropAllTaskWhenQuit);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user