Parcourir la source

多线程功能开始开发

tanghai il y a 2 ans
Parent
commit
f66f6970e5

+ 60 - 16
Unity/Assets/Scripts/Core/Singleton/Game.cs

@@ -1,29 +1,58 @@
 using System;
 using System.Collections.Generic;
+using System.Threading;
 
 namespace ET
 {
-    public static class Game
+    public class Game: IDisposable
     {
+        public int Id { get; private set; }
+        
+        public Barrier Barrier { get; set; }
+
+        public Game(int id)
+        {
+            this.Id = id;
+
+            this.loop = new WaitCallback((_) =>
+            {
+                this.Init();
+                this.Update();
+                this.LateUpdate();
+                this.FrameFinishUpdate();
+                this.Barrier.RemoveParticipant();
+            });
+        }
+        
         [StaticField]
-        private static readonly Stack<ISingleton> singletons = new();
+        private readonly Stack<ISingleton> singletons = new();
         [StaticField]
-        private static readonly Queue<ISingleton> updates = new();
+        private readonly Queue<ISingleton> updates = new();
         [StaticField]
-        private static readonly Queue<ISingleton> lateUpdates = new();
+        private readonly Queue<ISingleton> lateUpdates = new();
         [StaticField]
-        private static readonly Queue<ISingleton> loads = new();
+        private readonly Queue<ISingleton> loads = new();
         [StaticField]
-        private static readonly Queue<ETTask> frameFinishTask = new();
+        private readonly Queue<ETTask> frameFinishTask = new();
 
-        public static T AddSingleton<T>() where T: Singleton<T>, new()
+        private readonly WaitCallback loop;
+
+        private void Init()
+        {
+            foreach (ISingleton singleton in this.singletons)
+            {
+                singleton.Register();
+            }
+        }
+        
+        public T AddSingleton<T>() where T: Singleton<T>, new()
         {
             T singleton = new T();
             AddSingleton(singleton);
             return singleton;
         }
-        
-        public static void AddSingleton(ISingleton singleton)
+
+        public void AddSingleton(ISingleton singleton)
         {
             singleton.Register();
             
@@ -50,14 +79,14 @@ namespace ET
             }
         }
 
-        public static async ETTask WaitFrameFinish()
+        public async ETTask WaitFrameFinish()
         {
             ETTask task = ETTask.Create(true);
             frameFinishTask.Enqueue(task);
             await task;
         }
-
-        public static void Update()
+        
+        public void Update()
         {
             int count = updates.Count;
             while (count-- > 0)
@@ -86,7 +115,7 @@ namespace ET
             }
         }
         
-        public static void LateUpdate()
+        public void LateUpdate()
         {
             int count = lateUpdates.Count;
             while (count-- > 0)
@@ -114,8 +143,16 @@ namespace ET
                 }
             }
         }
+
+        public WaitCallback Loop
+        {
+            get
+            {
+                return this.loop;
+            }
+        }
         
-        public static void Load()
+        public void Load()
         {
             int count = loads.Count;
             while (count-- > 0)
@@ -144,7 +181,7 @@ namespace ET
             }
         }
 
-        public static void FrameFinishUpdate()
+        public void FrameFinishUpdate()
         {
             while (frameFinishTask.Count > 0)
             {
@@ -153,8 +190,15 @@ namespace ET
             }
         }
 
-        public static void Close()
+        public void Dispose()
         {
+            if (this.Id == 0)
+            {
+                return;
+            }
+            
+            this.Id = 0;
+            
             // 顺序反过来清理
             while (singletons.Count > 0)
             {

+ 2 - 5
Unity/Assets/Scripts/Core/Singleton/Singleton.cs

@@ -11,7 +11,8 @@ namespace ET
     
     public abstract class Singleton<T>: ISingleton where T: Singleton<T>, new()
     {
-        private bool isDisposed;
+        private bool isDisposed; 
+        [ThreadStatic]
         [StaticField]
         private static T instance;
 
@@ -25,10 +26,6 @@ namespace ET
 
         void ISingleton.Register()
         {
-            if (instance != null)
-            {
-                throw new Exception($"singleton register twice! {typeof (T).Name}");
-            }
             instance = (T)this;
         }
 

+ 7 - 0
Unity/Assets/Scripts/Core/World/IWorldSingletonAwake.cs

@@ -0,0 +1,7 @@
+namespace ET
+{
+    public interface IWorldSingletonAwake
+    {
+        void Awake();
+    }
+}

+ 7 - 0
Unity/Assets/Scripts/Core/World/IWorldSingletonLateUpdate.cs

@@ -0,0 +1,7 @@
+namespace ET
+{
+    public interface IWorldSingletonLateUpdate
+    {
+        void LateUpdate();
+    }
+}

+ 7 - 0
Unity/Assets/Scripts/Core/World/IWorldSingletonLoad.cs

@@ -0,0 +1,7 @@
+namespace ET
+{
+    public interface IWorldSingletonLoad
+    {
+        void Load();
+    }
+}

+ 7 - 0
Unity/Assets/Scripts/Core/World/IWorldSingletonUpdate.cs

@@ -0,0 +1,7 @@
+namespace ET
+{
+    public interface IWorldSingletonUpdate
+    {
+        void Update();
+    }
+}

+ 57 - 0
Unity/Assets/Scripts/Core/World/Singleton.cs

@@ -0,0 +1,57 @@
+using System;
+
+namespace ET
+{
+    public interface IWorldSingleton: IDisposable
+    {
+        void Register();
+        void Destroy();
+        bool IsDisposed();
+    }
+    
+    public abstract class WorldSingleton<T>: IWorldSingleton where T: WorldSingleton<T>, new()
+    {
+        private bool isDisposed;
+        [ThreadStatic]
+        [StaticField]
+        private static T instance;
+
+        public static T Instance
+        {
+            get
+            {
+                return instance;
+            }
+        }
+
+        void IWorldSingleton.Register()
+        {
+            if (instance != null)
+            {
+                throw new Exception($"singleton register twice! {typeof (T).Name}");
+            }
+            instance = (T)this;
+        }
+
+        void IWorldSingleton.Destroy()
+        {
+            if (this.isDisposed)
+            {
+                return;
+            }
+            this.isDisposed = true;
+            
+            instance.Dispose();
+            instance = null;
+        }
+
+        bool IWorldSingleton.IsDisposed()
+        {
+            return this.isDisposed;
+        }
+
+        public virtual void Dispose()
+        {
+        }
+    }
+}

+ 73 - 0
Unity/Assets/Scripts/Core/World/World.cs

@@ -0,0 +1,73 @@
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace ET
+{
+    public class World
+    {
+        [StaticField]
+        public static World Instance = new World();
+        
+        private World()
+        {
+        }
+        
+        private Stack<IWorldSingleton> singletons = new();
+
+        private Queue<IWorldSingleton> updates = new();
+
+        private Queue<IWorldSingleton> lateUpdates = new();
+
+        private Queue<IWorldSingleton> loads = new();
+
+        private readonly Queue<Game> loops = new Queue<Game>();
+
+        private readonly Dictionary<int, Game> games = new Dictionary<int, Game>();
+
+        private int idGenerate;
+
+        public Game Create(bool loop = true)
+        {
+            Game game = new(++this.idGenerate);
+            this.games.Add(game.Id, game);
+            if (loop)
+            {
+                this.loops.Enqueue(game);
+            }
+            return game;
+        }
+
+        public void Remove(int id)
+        {
+            if (this.games.Remove(id, out Game game))
+            {
+                game.Dispose();    
+            }
+        }
+        
+        // 简单线程调度,每次Loop会把所有Game Loop一遍
+        public void Loop()
+        {
+            int count = this.loops.Count;
+
+            using Barrier barrier = new Barrier(1);
+            
+            while (count-- > 0)
+            {
+                Game game = this.loops.Dequeue();
+                barrier.AddParticipant();
+                game.Barrier = barrier;
+                if (game.Id == 0)
+                {
+                    continue;
+                }
+                this.loops.Enqueue(game);
+                ThreadPool.QueueUserWorkItem(game.Loop);
+            }
+
+            barrier.SignalAndWait();
+        }
+    }
+}

+ 1 - 0
Unity/Assets/Scripts/Model/Server/Module/Actor/ActorMessageDispatcherComponent.cs

@@ -22,6 +22,7 @@ namespace ET.Server
     [ComponentOf(typeof(Scene))]
     public class ActorMessageDispatcherComponent: Entity, IAwake, IDestroy, ILoad
     {
+        [ThreadStatic]
         [StaticField]
         public static ActorMessageDispatcherComponent Instance;
 

+ 4 - 1
Unity/Assets/Scripts/Model/Server/Module/ActorLocation/LocationProxyComponent.cs

@@ -1,8 +1,11 @@
-namespace ET.Server
+using System;
+
+namespace ET.Server
 {
     [ComponentOf(typeof(Scene))]
     public class LocationProxyComponent: Entity, IAwake, IDestroy
     {
+        [ThreadStatic]
         [StaticField]
         public static LocationProxyComponent Instance;
     }

+ 4 - 1
Unity/Assets/Scripts/Model/Server/Module/DB/DBManagerComponent.cs

@@ -1,8 +1,11 @@
-namespace ET.Server
+using System;
+
+namespace ET.Server
 {
     
     public class DBManagerComponent: Entity, IAwake, IDestroy
     {
+        [ThreadStatic]
         [StaticField]
         public static DBManagerComponent Instance;
         

+ 3 - 1
Unity/Assets/Scripts/Model/Server/Module/Message/NetInnerComponent.cs

@@ -1,4 +1,5 @@
-using System.Net;
+using System;
+using System.Net;
 
 namespace ET.Server
 {
@@ -29,6 +30,7 @@ namespace ET.Server
         
         public NetworkProtocol InnerProtocol = NetworkProtocol.KCP;
 
+        [ThreadStatic]
         [StaticField]
         public static NetInnerComponent Instance;
     }

+ 3 - 1
Unity/Assets/Scripts/Model/Server/Module/RobotCase/RobotCaseComponent.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 
 namespace ET.Server
 {
@@ -6,6 +7,7 @@ namespace ET.Server
     [ComponentOf(typeof(Scene))]
     public class RobotCaseComponent: Entity, IAwake, IDestroy
     {
+        [ThreadStatic]
         [StaticField]
         public static RobotCaseComponent Instance;
         public Dictionary<int, RobotCase> RobotCases = new Dictionary<int, RobotCase>();

+ 1 - 0
Unity/Assets/Scripts/Model/Share/Module/Message/OpcodeTypeComponent.cs

@@ -83,6 +83,7 @@ namespace ET
     [ComponentOf(typeof (Scene))]
     public class OpcodeTypeComponent: Entity, IAwake, IDestroy
     {
+        [ThreadStatic]
         [StaticField]
         public static OpcodeTypeComponent Instance;
 

+ 1 - 0
Unity/Assets/Scripts/Model/Share/Module/Recast/NavmeshComponent.cs

@@ -6,6 +6,7 @@ namespace ET
     [ComponentOf(typeof(Scene))]
     public class NavmeshComponent: Entity, IAwake
     {
+        [ThreadStatic]
         [StaticField]
         public static NavmeshComponent Instance;
         

+ 1 - 0
Unity/Assets/Scripts/Model/Share/Module/Recast/PathfindingComponent.cs

@@ -10,6 +10,7 @@ namespace ET
     {
         public const int FindRandomNavPosMaxRadius = 15000;  // 随机找寻路点的最大半径
         
+        [ThreadStatic]
         [StaticField]
         public static float[] extents = {15, 10, 15};
         

+ 3 - 0
Unity/Assets/Scripts/Model/Share/Module/Scene/ClientSceneManagerComponent.cs

@@ -1,8 +1,11 @@
+using System;
+
 namespace ET
 {
     [ComponentOf(typeof(Scene))]
     public class ClientSceneManagerComponent: Entity, IAwake, IDestroy
     {
+        [ThreadStatic]
         [StaticField]
         public static ClientSceneManagerComponent Instance;
     }

+ 3 - 0
Unity/Assets/Scripts/Model/Share/Module/Scene/ServerSceneManagerComponent.cs

@@ -1,8 +1,11 @@
+using System;
+
 namespace ET
 {
     [ComponentOf(typeof(Scene))]
     public class ServerSceneManagerComponent: Entity, IAwake, IDestroy
     {
+        [ThreadStatic]
         [StaticField]
         public static ServerSceneManagerComponent Instance;
     }

+ 1 - 0
Unity/Assets/Scripts/ModelView/Client/Module/UI/UIEventComponent.cs

@@ -10,6 +10,7 @@ namespace ET.Client
 	[ComponentOf(typeof(Scene))]
 	public class UIEventComponent: Entity, IAwake
 	{
+		[ThreadStatic]
 		[StaticField]
 		public static UIEventComponent Instance;