summaryrefslogtreecommitdiff
path: root/Runtime
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-10-25 23:29:21 +0800
committerchai <chaifix@163.com>2021-10-25 23:29:21 +0800
commit7ecf913256fb396e3027aac3318d996a716a52ef (patch)
tree4540835c881a63b665e2a692bf30115fd29e8bb0 /Runtime
parent0816cd70ca1a213b6ed872bcf3c0bf0912473722 (diff)
+ job system
Diffstat (limited to 'Runtime')
-rw-r--r--Runtime/Common/DataBuffer.cpp (renamed from Runtime/Threads/Mutex.cpp)0
-rw-r--r--Runtime/Common/DataBuffer.h14
-rw-r--r--Runtime/Debug/Log.cpp45
-rw-r--r--Runtime/FileSystem/File.cpp (renamed from Runtime/Threads/Mutex.h)0
-rw-r--r--Runtime/FileSystem/File.h9
-rw-r--r--Runtime/FileSystem/FileJobs.cpp27
-rw-r--r--Runtime/FileSystem/FileJobs.h22
-rw-r--r--Runtime/FileSystem/FileSystem.cpp9
-rw-r--r--Runtime/FileSystem/FileSystem.h24
-rw-r--r--Runtime/FileSystem/Unzip.h3
-rw-r--r--Runtime/Graphics/ImageData.h17
-rw-r--r--Runtime/Lua/LuaBind/LuaBindClass.hpp4
-rw-r--r--Runtime/Lua/LuaBind/LuaBindState.cpp11
-rw-r--r--Runtime/Lua/LuaBind/LuaBindState.h1
-rw-r--r--Runtime/Scripting/FileSystem/FileSystem.bind.cpp10
-rw-r--r--Runtime/Scripting/GL/GL.bind.cpp184
-rw-r--r--Runtime/Scripting/IO/IO.bind.cpp51
-rw-r--r--Runtime/Threading/Job.cpp13
-rw-r--r--Runtime/Threading/Job.h17
-rw-r--r--Runtime/Threading/JobSystem.cpp43
-rw-r--r--Runtime/Threading/JobSystem.h22
-rw-r--r--Runtime/Threading/Mutex.cpp25
-rw-r--r--Runtime/Threading/Mutex.h39
-rw-r--r--Runtime/Threading/Semaphore.cpp (renamed from Runtime/Threads/Semaphore.cpp)0
-rw-r--r--Runtime/Threading/Semaphore.h (renamed from Runtime/Threads/Semaphore.h)0
-rw-r--r--Runtime/Threading/Thread.cpp69
-rw-r--r--Runtime/Threading/Thread.h70
-rw-r--r--Runtime/Threading/WorkThread.cpp48
-rw-r--r--Runtime/Threads/Thread.h0
29 files changed, 709 insertions, 68 deletions
diff --git a/Runtime/Threads/Mutex.cpp b/Runtime/Common/DataBuffer.cpp
index e69de29..e69de29 100644
--- a/Runtime/Threads/Mutex.cpp
+++ b/Runtime/Common/DataBuffer.cpp
diff --git a/Runtime/Common/DataBuffer.h b/Runtime/Common/DataBuffer.h
new file mode 100644
index 0000000..330128f
--- /dev/null
+++ b/Runtime/Common/DataBuffer.h
@@ -0,0 +1,14 @@
+#pragma once
+#include "Runtime/Lua/LuaHelper.h"
+
+// 描述内存对象,会作为
+// 1. 多线程读取文件的返回
+class DataBuffer : public LuaBind::NativeClass<DataBuffer>
+{
+public:
+ DataBuffer(LuaBind::VM* vm);
+ ~DataBuffer();
+
+ char* data;
+ int length;
+}; \ No newline at end of file
diff --git a/Runtime/Debug/Log.cpp b/Runtime/Debug/Log.cpp
index cc5b2e3..a84337b 100644
--- a/Runtime/Debug/Log.cpp
+++ b/Runtime/Debug/Log.cpp
@@ -1,3 +1,4 @@
+#include "Runtime/Threading/Mutex.h"
#include "log.h"
#include <iostream>
#include <ctime>
@@ -12,6 +13,8 @@ static HANDLE s_ConsoleHandle = 0;
unordered_set<string> s_OpenTags;
+Mutex s_Mutex;
+
#ifdef GAMELAB_DEBUG
// https://stackoverflow.com/questions/997946/how-to-get-current-time-and-date-in-c
// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
@@ -39,41 +42,47 @@ void log_open_tag(std::string tag)
void log_info(std::string log)
{
+ _lock(s_Mutex) {
#ifdef GAMELAB_WIN
- if (s_ConsoleHandle == 0) {
- s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
- }
- SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
- cout << currentDateTime() << " [Info] " << log << endl;
+ if (s_ConsoleHandle == 0) {
+ s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ }
+ SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
+ cout << currentDateTime() << " [Info] " << log << endl;
#else
- cout << "\x1B[97m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl;
+ cout << "\x1B[97m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl;
#endif
+ }
}
void log_warning(std::string log)
{
+ _lock(s_Mutex) {
#ifdef GAMELAB_WIN
- if (s_ConsoleHandle == 0) {
- s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
- }
- SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
- cout << currentDateTime() << " [Info] " << log << endl;
+ if (s_ConsoleHandle == 0) {
+ s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ }
+ SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
+ cout << currentDateTime() << " [Info] " << log << endl;
#else
- cout << "\x1B[93m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl;
+ cout << "\x1B[93m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl;
#endif
+ }
}
void log_error(std::string log)
{
+ _lock(s_Mutex) {
#ifdef GAMELAB_WIN
- if (s_ConsoleHandle == 0) {
- s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
- }
- SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_INTENSITY);
- cout << currentDateTime() << " [Info] " << log << endl;
+ if (s_ConsoleHandle == 0) {
+ s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
+ }
+ SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_INTENSITY);
+ cout << currentDateTime() << " [Info] " << log << endl;
#else
- cout << "\x1B[91m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl;
+ cout << "\x1B[91m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl;
#endif
+ }
}
void log_error_null_param(std::string funcName, std::string param)
diff --git a/Runtime/Threads/Mutex.h b/Runtime/FileSystem/File.cpp
index e69de29..e69de29 100644
--- a/Runtime/Threads/Mutex.h
+++ b/Runtime/FileSystem/File.cpp
diff --git a/Runtime/FileSystem/File.h b/Runtime/FileSystem/File.h
new file mode 100644
index 0000000..19e780d
--- /dev/null
+++ b/Runtime/FileSystem/File.h
@@ -0,0 +1,9 @@
+#pragma once
+#include "Runtime/Lua/LuaHelper.h"
+
+class File
+{
+public:
+
+
+};
diff --git a/Runtime/FileSystem/FileJobs.cpp b/Runtime/FileSystem/FileJobs.cpp
new file mode 100644
index 0000000..29e99a4
--- /dev/null
+++ b/Runtime/FileSystem/FileJobs.cpp
@@ -0,0 +1,27 @@
+#include <fstream>
+#include "FileJobs.h"
+
+using namespace std;
+
+void ReadFilesJob::Dispacth(void* param)
+{
+ LUA_BIND_STATE((lua_State*)param);
+ if (!callback)
+ return;
+ callback.PushRef(state);
+ state.Call(0, 0);
+}
+
+void ReadFilesJob::Process()
+{
+ if (IsFinished())
+ return;
+ ifstream infile;
+ infile.open(files[cur]);
+ ++cur;
+}
+
+bool ReadFilesJob::IsFinished()
+{
+ return cur >= files.size();
+} \ No newline at end of file
diff --git a/Runtime/FileSystem/FileJobs.h b/Runtime/FileSystem/FileJobs.h
new file mode 100644
index 0000000..2e53a39
--- /dev/null
+++ b/Runtime/FileSystem/FileJobs.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <vector>
+#include "Runtime/Threading/Job.h"
+#include "Runtime/Lua/LuaHelper.h"
+#include "Runtime/Threading/JobSystem.h"
+
+class ReadFilesJob : public Job
+{
+public:
+ ReadFilesJob(LuaBind::VM* vm) : callback(vm), cur(0) {}
+ ~ReadFilesJob() {}
+
+ void Dispacth(void* param) override;
+ void Process() override;
+ bool IsFinished() override;
+
+ int cur = 0; //当前处理的文件
+ std::vector<std::string> files; // 文件路径
+ LuaBind::StrongRef callback; // 完成后的回调函数
+
+};
diff --git a/Runtime/FileSystem/FileSystem.cpp b/Runtime/FileSystem/FileSystem.cpp
deleted file mode 100644
index 8816f78..0000000
--- a/Runtime/FileSystem/FileSystem.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include "FileSystem.h"
-
-FileSystem& GetFileSystem() {
- if (!FileSystem::m_Instance)
- {
- FileSystem::m_Instance = new FileSystem();
- }
- return *FileSystem::m_Instance;
-}
diff --git a/Runtime/FileSystem/FileSystem.h b/Runtime/FileSystem/FileSystem.h
deleted file mode 100644
index aae39c1..0000000
--- a/Runtime/FileSystem/FileSystem.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef FILESYSTEM_H
-#define FILESYSTEM_H
-
-#include <string>
-
-class FileSystem
-{
-public:
- std::string GetDataPath();
- std::string GetPersistentPath();
- std::string GetTempPath();
-
-private:
- FileSystem();
-
- static FileSystem* m_Instance;
-
- friend FileSystem& GetFileSystem();
-
-};
-
-FileSystem& GetFileSystem();
-
-#endif \ No newline at end of file
diff --git a/Runtime/FileSystem/Unzip.h b/Runtime/FileSystem/Unzip.h
index e69de29..45dcbb0 100644
--- a/Runtime/FileSystem/Unzip.h
+++ b/Runtime/FileSystem/Unzip.h
@@ -0,0 +1,3 @@
+#pragma once
+
+
diff --git a/Runtime/Graphics/ImageData.h b/Runtime/Graphics/ImageData.h
index a3162bc..af44f11 100644
--- a/Runtime/Graphics/ImageData.h
+++ b/Runtime/Graphics/ImageData.h
@@ -2,14 +2,15 @@
#define IMAGE_DATA_H
#include <vector>
+#include "Runtime/Threading/Job.h"
// 图片像素数据
class ImageData
{
-public:
+public:
enum ImageFormat
{
- ImageFormat_Rgba_Int,
+ ImageFormat_Rgba_Int,
ImageFormat_Rgba_Float,
};
@@ -30,7 +31,7 @@ struct ImageDataRequest
bool isDone, hasError;
int error;
int progress, all;
- ImageData* result;
+ ImageData* result;
std::vector<ImageData*> results;
};
@@ -41,4 +42,14 @@ namespace ImageDataUtil
ImageDataRequest* LoadAsync(std::vector<const char*> paths);
}
+class ReadImageFilesJob : public Job
+{
+
+};
+
+class DecodeImageFilesJob : public Job
+{
+
+};
+
#endif \ No newline at end of file
diff --git a/Runtime/Lua/LuaBind/LuaBindClass.hpp b/Runtime/Lua/LuaBind/LuaBindClass.hpp
index eb028c2..7fb4529 100644
--- a/Runtime/Lua/LuaBind/LuaBindClass.hpp
+++ b/Runtime/Lua/LuaBind/LuaBindClass.hpp
@@ -414,7 +414,7 @@ namespace LuaBind
PushMemberRef(state, script);
state.GetField(-1, method);
PushMemberRef(state, script);
- state.Call(1, 0);
+ state.Call(1, 0, onErrorOccured);
state.SetTop(top);
}
@@ -512,7 +512,7 @@ namespace LuaBind
if (state.IsType(-1, LUA_TFUNCTION))
{
lua_pushvalue(L, 1); // userdata
- state.Call(1, 1); // 派生类的GetClassName函数
+ state.Call(1, 1, onErrorOccured); // 派生类的GetClassName函数
classname = state.GetValue<cc8*>(-1, "");
}
else
diff --git a/Runtime/Lua/LuaBind/LuaBindState.cpp b/Runtime/Lua/LuaBind/LuaBindState.cpp
index 7c5f043..137acbf 100644
--- a/Runtime/Lua/LuaBind/LuaBindState.cpp
+++ b/Runtime/Lua/LuaBind/LuaBindState.cpp
@@ -8,7 +8,8 @@
namespace LuaBind
{
- OnRegisterClassHandler onRegisterNativeClass;
+ OnRegisterClassHandler onRegisterNativeClass = NULL;
+ ErrorHandler onErrorOccured = NULL;
std::string g_NameSpace = "";
@@ -114,6 +115,10 @@ namespace LuaBind
{
//luaL_dofile(mState, path.c_str());
LoadFile(path);
+ if (handler == NULL)
+ {
+ handler = onErrorOccured;
+ }
Call(0, 0, handler);
}
@@ -161,6 +166,10 @@ namespace LuaBind
void State::Call(int nArgs, int nResults, ErrorHandler handler)
{
+ if (handler == NULL)
+ {
+ handler = onErrorOccured;
+ }
int oldTop = GetTop() - nArgs - 1;
int func = 0;
if (handler != NULL)
diff --git a/Runtime/Lua/LuaBind/LuaBindState.h b/Runtime/Lua/LuaBind/LuaBindState.h
index e7e2807..071287f 100644
--- a/Runtime/Lua/LuaBind/LuaBindState.h
+++ b/Runtime/Lua/LuaBind/LuaBindState.h
@@ -17,6 +17,7 @@ namespace LuaBind
typedef void (*ErrorHandler) (cc8 * msg);
typedef void(*OnRegisterClassHandler)(State&, int clsIdx, std::string clsName, std::string pkgName);
+ extern ErrorHandler onErrorOccured;
extern OnRegisterClassHandler onRegisterNativeClass;
extern std::string g_NameSpace;
diff --git a/Runtime/Scripting/FileSystem/FileSystem.bind.cpp b/Runtime/Scripting/FileSystem/FileSystem.bind.cpp
deleted file mode 100644
index fea8b57..0000000
--- a/Runtime/Scripting/FileSystem/FileSystem.bind.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include <iostream>
-
-#include "Runtime/Lua/LuaBind/LuaBind.h"
-
-int luaopen_GameLab_FileSystem(lua_State* L)
-{
-
- return 1;
-}
-
diff --git a/Runtime/Scripting/GL/GL.bind.cpp b/Runtime/Scripting/GL/GL.bind.cpp
index f167237..f4c9f50 100644
--- a/Runtime/Scripting/GL/GL.bind.cpp
+++ b/Runtime/Scripting/GL/GL.bind.cpp
@@ -212,11 +212,187 @@ int MatrixMode(lua_State* L)
return 0;
}
-// GL.LoadMatrix([Matrix4x4, mat44ColumnMajorTable])
+// GL.LoadMatrix([Matrix44, mat44ColumnMajorTable])
int LoadMatrix(lua_State* L)
{
LUA_BIND_STATE(L);
+ if (LuaHelper::IsType(state, "GameLab.Engine.Math.Matrix44", 1))
+ {
+ float m[16];
+ m[0] = state.GetField(1, "m00", 0.f);
+ m[1] = state.GetField(1, "m10", 0.f);
+ m[2] = state.GetField(1, "m20", 0.f);
+ m[3] = state.GetField(1, "m30", 0.f);
+
+ m[4] = state.GetField(1, "m01", 0.f);
+ m[5] = state.GetField(1, "m11", 0.f);
+ m[6] = state.GetField(1, "m21", 0.f);
+ m[7] = state.GetField(1, "m31", 0.f);
+
+ m[8] = state.GetField(1, "m02", 0.f);
+ m[9] = state.GetField(1, "m12", 0.f);
+ m[10] = state.GetField(1, "m22", 0.f);
+ m[11] = state.GetField(1, "m32", 0.f);
+
+ m[12] = state.GetField(1, "m03", 0.f);
+ m[13] = state.GetField(1, "m13", 0.f);
+ m[14] = state.GetField(1, "m23", 0.f);
+ m[15] = state.GetField(1, "m33", 0.f);
+
+ glLoadMatrixf(m);
+ }
+ else if (LuaHelper::IsType(state, "table", 1))
+ {
+ float m[16];
+ m[0] = state.GetField(1, 1, 0.f);
+ m[1] = state.GetField(1, 2, 0.f);
+ m[2] = state.GetField(1, 3, 0.f);
+ m[3] = state.GetField(1, 4, 0.f);
+
+ m[4] = state.GetField(1, 5, 0.f);
+ m[5] = state.GetField(1, 6, 0.f);
+ m[6] = state.GetField(1, 7, 0.f);
+ m[7] = state.GetField(1, 8, 0.f);
+
+ m[8] = state.GetField(1, 9, 0.f);
+ m[9] = state.GetField(1, 10, 0.f);
+ m[10] = state.GetField(1, 11, 0.f);
+ m[11] = state.GetField(1, 12, 0.f);
+
+ m[12] = state.GetField(1, 13, 0.f);
+ m[13] = state.GetField(1, 14, 0.f);
+ m[14] = state.GetField(1, 15, 0.f);
+ m[15] = state.GetField(1, 16, 0.f);
+
+ glLoadMatrixf(m);
+ }
+ else
+ {
+ state.ErrorType(1, "Matrix44 or mat44ColumnMajorTable");
+ }
+
+ return 0;
+}
+
+// GL.Ortho(l,r,b,t,n,f)
+int OrthoMatrix(lua_State* L)
+{
+ LUA_BIND_STATE(L);
+ double l = state.GetValue<double>(1, 0);
+ double r = state.GetValue<double>(2, 0);
+ double b = state.GetValue<double>(3, 0);
+ double t = state.GetValue<double>(4, 0);
+ double n = state.GetValue<double>(5, 0);
+ double f = state.GetValue<double>(6, 0);
+ glOrtho(l, r, b, t, n, f);
+ return 0;
+}
+
+// GL.Ortho(l,r,b,t,n,f)
+int FrustumMatrix(lua_State* L)
+{
+ LUA_BIND_STATE(L);
+ double l = state.GetValue<double>(1, 0);
+ double r = state.GetValue<double>(2, 0);
+ double b = state.GetValue<double>(3, 0);
+ double t = state.GetValue<double>(4, 0);
+ double n = state.GetValue<double>(5, 0);
+ double f = state.GetValue<double>(6, 0);
+ glFrustum(l, r, b, t, n, f);
+ return 0;
+}
+
+int MultMatrix(lua_State* L)
+{
+ LUA_BIND_STATE(L);
+
+ if (LuaHelper::IsType(state, "GameLab.Engine.Math.Matrix44", 1))
+ {
+ float m[16];
+ m[0] = state.GetField(1, "m00", 0);
+ m[1] = state.GetField(1, "m10", 0);
+ m[2] = state.GetField(1, "m20", 0);
+ m[3] = state.GetField(1, "m30", 0);
+
+ m[4] = state.GetField(1, "m01", 0);
+ m[5] = state.GetField(1, "m11", 0);
+ m[6] = state.GetField(1, "m21", 0);
+ m[7] = state.GetField(1, "m31", 0);
+
+ m[8] = state.GetField(1, "m02", 0);
+ m[9] = state.GetField(1, "m12", 0);
+ m[10] = state.GetField(1, "m22", 0);
+ m[11] = state.GetField(1, "m32", 0);
+
+ m[12] = state.GetField(1, "m03", 0);
+ m[13] = state.GetField(1, "m13", 0);
+ m[14] = state.GetField(1, "m23", 0);
+ m[15] = state.GetField(1, "m33", 0);
+
+ glMultMatrixf(m);
+ }
+ else if (LuaHelper::IsType(state, "table", 1))
+ {
+ float m[16];
+ m[0] = state.GetField(1, 1, 0);
+ m[1] = state.GetField(1, 2, 0);
+ m[2] = state.GetField(1, 3, 0);
+ m[3] = state.GetField(1, 4, 0);
+
+ m[4] = state.GetField(1, 5, 0);
+ m[5] = state.GetField(1, 6, 0);
+ m[6] = state.GetField(1, 7, 0);
+ m[7] = state.GetField(1, 8, 0);
+
+ m[8] = state.GetField(1, 9, 0);
+ m[9] = state.GetField(1, 10, 0);
+ m[10] = state.GetField(1, 11, 0);
+ m[11] = state.GetField(1, 12, 0);
+
+ m[12] = state.GetField(1, 13, 0);
+ m[13] = state.GetField(1, 14, 0);
+ m[14] = state.GetField(1, 15, 0);
+ m[15] = state.GetField(1, 16, 0);
+
+ glMultMatrixf(m);
+ }
+ else
+ {
+ state.ErrorType(1, "Matrix44 or mat44ColumnMajorTable");
+ }
+
+ return 0;
+}
+
+int Scale(lua_State* L)
+{
+ LUA_BIND_STATE(L);
+ float x = state.GetValue(1, 1);
+ float y = state.GetValue(2, 1);
+ float z = state.GetValue(3, 1);
+ glScalef(x, y, z);
+ return 0;
+}
+
+int Rotate(lua_State* L)
+{
+ LUA_BIND_STATE(L);
+ float angle = state.GetValue(1, 0);
+ float x = state.GetValue(2, 0);
+ float y = state.GetValue(3, 0);
+ float z = state.GetValue(4, 1);
+ glRotatef(angle, x, y, z);
+ return 0;
+}
+
+int Translate(lua_State* L)
+{
+ LUA_BIND_STATE(L);
+ float x = state.GetValue(1, 0);
+ float y = state.GetValue(2, 0);
+ float z = state.GetValue(3, 0);
+ glTranslatef(x, y, z);
return 0;
}
@@ -233,6 +409,12 @@ static luaL_Reg glFuncs[] = {
{"PopMatrix", PopMatrix},
{"MatrixMode", MatrixMode},
{"LoadMatrix", LoadMatrix},
+ {"LoadOrthoMatrix", OrthoMatrix},
+ {"LoadFrustumMatrix", FrustumMatrix},
+ {"MultMatrix", MultMatrix},
+ {"Scale", Scale},
+ {"Rotate", Rotate},
+ {"Translate", Translate},
{0, 0}
};
diff --git a/Runtime/Scripting/IO/IO.bind.cpp b/Runtime/Scripting/IO/IO.bind.cpp
new file mode 100644
index 0000000..d58d86f
--- /dev/null
+++ b/Runtime/Scripting/IO/IO.bind.cpp
@@ -0,0 +1,51 @@
+#include "Runtime/Lua/LuaHelper.h"
+#include "Runtime/Debug/Log.h"
+#include "Runtime/FileSystem/FileJobs.h"
+
+// IO.ReadFiles({}, callback)
+int ReadFiles(lua_State* L)
+{
+ LUA_BIND_STATE(L);
+ LUA_BIND_CHECK(L, "TF");
+
+ std::vector<std::string> files;
+ for (int i = 1; true; ++i)
+ {
+ state.GetField(1, i);
+ if (lua_type(L, -1) != LUA_TSTRING)
+ {
+ lua_pop(L, 1);
+ break;
+ }
+ const char* f = lua_tostring(L, -1);
+ state.Pop(1);
+ files.push_back(f);
+ }
+
+ ReadFilesJob* job = new ReadFilesJob(state.GetVM());
+ job->files = files;
+ job->callback.SetRef(state, 2);
+
+ JobSystem::Instance()->AddJobAtEnd(job);
+ return 0;
+}
+
+static luaL_Reg ioFuncs[] = {
+ {"ReadFiles", ReadFiles},
+ {0, 0}
+};
+
+int luaopen_GameLab_IO(lua_State* L)
+{
+ log_info("Scripting", "luaopen_GameLab_IO()");
+
+ LUA_BIND_STATE(L);
+
+ state.PushGlobalNamespace();
+ state.PushNamespace("GameLab");
+ state.PushNamespace("IO");
+
+ state.RegisterMethods(ioFuncs);
+
+ return 1;
+} \ No newline at end of file
diff --git a/Runtime/Threading/Job.cpp b/Runtime/Threading/Job.cpp
new file mode 100644
index 0000000..18794c5
--- /dev/null
+++ b/Runtime/Threading/Job.cpp
@@ -0,0 +1,13 @@
+#include "Job.h"
+#include "Runtime/Utilities/UIDGenerator.h"
+
+static UIDGenerator s_JobIDGenerator;
+
+Job::Job()
+ : m_ID(s_JobIDGenerator.GenUID())
+{
+}
+
+Job::~Job()
+{
+}
diff --git a/Runtime/Threading/Job.h b/Runtime/Threading/Job.h
new file mode 100644
index 0000000..db89feb
--- /dev/null
+++ b/Runtime/Threading/Job.h
@@ -0,0 +1,17 @@
+#pragma once
+
+// 任务的抽象基类
+class Job
+{
+public:
+ Job();
+ virtual ~Job();
+
+ virtual void Process() = 0;
+ virtual bool IsFinished() = 0;
+ virtual void Dispacth(void* param) = 0; // call in main thread
+
+protected:
+ int m_ID; // Job ID
+
+}; \ No newline at end of file
diff --git a/Runtime/Threading/JobSystem.cpp b/Runtime/Threading/JobSystem.cpp
new file mode 100644
index 0000000..a026300
--- /dev/null
+++ b/Runtime/Threading/JobSystem.cpp
@@ -0,0 +1,43 @@
+#include "JobSystem.h"
+
+JobSystem::JobSystem()
+{
+
+}
+
+JobSystem::~JobSystem()
+{
+
+}
+
+void JobSystem::Initilize(int workThreadCount)
+{
+ if (workThreadCount <= 0)
+ return;
+
+ for (int i = 0; i < workThreadCount; ++i)
+ {
+ WorkThread* thread = new WorkThread();
+ thread->Resume();
+ m_Threads.push_back(thread);
+ }
+}
+
+void JobSystem::Dispatch(void* param)
+{
+ for (int i = 0; i < m_Threads.size(); ++i)
+ {
+ m_Threads[i]->Dispatch(param);
+ }
+}
+
+void JobSystem::AddJobAtEnd(Job* job)
+{
+ WorkThread* thread = SelectThread();
+ thread->AddJobAtEnd(job);
+}
+
+WorkThread* JobSystem::SelectThread()
+{
+ return m_Threads[0];
+} \ No newline at end of file
diff --git a/Runtime/Threading/JobSystem.h b/Runtime/Threading/JobSystem.h
new file mode 100644
index 0000000..c95037c
--- /dev/null
+++ b/Runtime/Threading/JobSystem.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "Runtime/Utilities/Singleton.h"
+#include "Runtime/Threading/Thread.h"
+#include <vector>
+
+class JobSystem : public Singleton<JobSystem>
+{
+public:
+ JobSystem();
+ ~JobSystem();
+
+ void AddJobAtEnd(Job* job);
+
+ void Initilize(int workThreadCount = 1);
+ void Dispatch(void* param);
+
+private:
+ WorkThread* SelectThread();
+
+ std::vector<WorkThread*> m_Threads;
+
+}; \ No newline at end of file
diff --git a/Runtime/Threading/Mutex.cpp b/Runtime/Threading/Mutex.cpp
new file mode 100644
index 0000000..eabe48d
--- /dev/null
+++ b/Runtime/Threading/Mutex.cpp
@@ -0,0 +1,25 @@
+#include "Thread.h"
+#include "Mutex.h"
+
+Mutex::Mutex()
+{
+ m_Handle = ::CreateMutex(NULL, FALSE, NULL);
+ if (!m_Handle)
+ throw ThreadException("Cant use win32 mutex.");
+}
+
+Mutex::~Mutex()
+{
+ ::CloseHandle(m_Handle);
+ m_Handle = NULL;
+}
+
+void Mutex::Lock()
+{
+ ::WaitForSingleObject(m_Handle, (~(uint32)0));
+}
+
+void Mutex::Unlock()
+{
+ ::ReleaseMutex(m_Handle);
+} \ No newline at end of file
diff --git a/Runtime/Threading/Mutex.h b/Runtime/Threading/Mutex.h
new file mode 100644
index 0000000..44f8cb9
--- /dev/null
+++ b/Runtime/Threading/Mutex.h
@@ -0,0 +1,39 @@
+#pragma once
+#include <windows.h>
+
+class Mutex
+{
+public:
+ Mutex();
+ ~Mutex();
+
+ void Lock();
+ void Unlock();
+
+private:
+ HANDLE m_Handle;
+
+};
+
+
+class MutexLocker
+{
+public:
+ MutexLocker(Mutex& mutex)
+ : m(mutex)
+ {
+ m.Lock();
+ };
+ ~MutexLocker()
+ {
+ m.Unlock();
+ }
+ operator bool() { return false; };
+private:
+ void* operator new(size_t);
+ Mutex& m;
+};
+
+#define _lock(m) \
+if(MutexLocker lock_##m = m){} else
+
diff --git a/Runtime/Threads/Semaphore.cpp b/Runtime/Threading/Semaphore.cpp
index e69de29..e69de29 100644
--- a/Runtime/Threads/Semaphore.cpp
+++ b/Runtime/Threading/Semaphore.cpp
diff --git a/Runtime/Threads/Semaphore.h b/Runtime/Threading/Semaphore.h
index e69de29..e69de29 100644
--- a/Runtime/Threads/Semaphore.h
+++ b/Runtime/Threading/Semaphore.h
diff --git a/Runtime/Threading/Thread.cpp b/Runtime/Threading/Thread.cpp
new file mode 100644
index 0000000..0a41485
--- /dev/null
+++ b/Runtime/Threading/Thread.cpp
@@ -0,0 +1,69 @@
+#include <string>
+#include "Thread.h"
+#include "Runtime/Utilities/Assert.h"
+
+static std::string s_ThreadErr;
+
+static DWORD WINAPI ThreadMain(LPVOID param)
+{
+ Thread* thread = (Thread*)param;
+ thread->Run();
+ return NULL;
+}
+
+Thread::Thread(uint32 stacksize)
+{
+ m_Handle = ::CreateThread(
+ NULL
+ , stacksize
+ , ThreadMain
+ , this
+ , CREATE_SUSPENDED
+ , NULL);
+ if (m_Handle == 0)
+ {
+ s_ThreadErr = "Create Thread Failed. ErrorCode=" + std::to_string(GetLastError());
+ throw ThreadException(s_ThreadErr.c_str());
+ }
+}
+
+Thread::~Thread()
+{
+ CloseHandle(m_Handle);
+}
+
+void Thread::Resume()
+{
+ ::ResumeThread(m_Handle);
+}
+
+bool Thread::IsRunning()
+{
+ if (m_Handle) {
+ DWORD exitCode = 0;
+ // https://blog.csdn.net/yuanmeng567/article/details/19485719
+ ::GetExitCodeThread(m_Handle, &exitCode);
+ return exitCode == STILL_ACTIVE;
+ }
+ return false;
+}
+
+void Thread::Join()
+{
+ ::WaitForSingleObject(m_Handle, INFINITE);
+}
+
+void Thread::Kill()
+{
+ ::TerminateThread(m_Handle, FALSE);
+}
+
+void Thread::Sleep(uint ms)
+{
+ ::Sleep(ms);
+}
+
+bool Thread::IsCurrent()
+{
+ return m_Handle == ::GetCurrentThread();
+}
diff --git a/Runtime/Threading/Thread.h b/Runtime/Threading/Thread.h
new file mode 100644
index 0000000..ea86e16
--- /dev/null
+++ b/Runtime/Threading/Thread.h
@@ -0,0 +1,70 @@
+#pragma once
+#include <windows.h>
+#include <vector>
+#include <exception>
+
+#include "Job.h"
+#include "Runtime/Utilities/Type.h"
+#include "Mutex.h"
+
+class ThreadException : public std::exception
+{
+public:
+ ThreadException(const char* what)
+ : std::exception(what)
+ {
+ }
+};
+
+class Thread
+{
+public:
+ Thread(uint32 stacksize = 0)/*throw ThreadExeception*/;
+ virtual ~Thread();
+
+ virtual void Run() = 0;
+
+ virtual void Resume();
+ virtual void Join() ;
+ virtual void Kill() ;
+
+ virtual void Sleep(uint ms) ;
+
+ virtual bool IsRunning() ;
+ virtual bool IsCurrent() ;
+
+protected:
+ HANDLE m_Handle;
+
+};
+
+// 任务系统的线程
+class WorkThread : public Thread
+{
+public:
+ void Run() override;
+ void Dispatch(void* param); // call in main thread
+
+ void AddJobAtEnd(Job* job);
+
+private:
+ Mutex m_PendingMutex;
+ Mutex m_FinishedMutex;
+
+ std::vector<Job*> m_PendingJobs;
+ std::vector<Job*> m_FinishedJobs;
+
+};
+
+// 执行小段代码的线程
+class CodePieceThread : public Thread
+{
+public:
+ typedef void(*CodePiece)();
+
+ void Run() override;
+
+private:
+ std::vector<CodePiece> m_CodePieces;
+
+}; \ No newline at end of file
diff --git a/Runtime/Threading/WorkThread.cpp b/Runtime/Threading/WorkThread.cpp
new file mode 100644
index 0000000..b3b462a
--- /dev/null
+++ b/Runtime/Threading/WorkThread.cpp
@@ -0,0 +1,48 @@
+#include "Thread.h"
+#include "Runtime/Debug/Log.h"
+
+void WorkThread::Run()
+{
+ while (true)
+ {
+ _lock(m_PendingMutex)
+ {
+ for (auto iter = m_PendingJobs.begin(); iter != m_PendingJobs.end();)
+ {
+ Job* job = *iter;
+ job->Process();
+ if (job->IsFinished())
+ {
+ _lock(m_FinishedMutex) {
+ m_FinishedJobs.push_back(job);
+ }
+ iter = m_PendingJobs.erase(iter);
+ continue;
+ }
+ ++iter;
+ }
+ if (m_PendingJobs.size() == 0)
+ ::Sleep(1);
+ }
+ }
+}
+
+void WorkThread::Dispatch(void* param)
+{
+ _lock(m_FinishedMutex)
+ {
+ for (int i = 0; i < m_FinishedJobs.size(); ++i)
+ {
+ m_FinishedJobs[i]->Dispacth(param);
+ }
+ m_FinishedJobs.clear();
+ }
+}
+
+void WorkThread::AddJobAtEnd(Job* job)
+{
+ _lock(m_PendingMutex)
+ {
+ m_PendingJobs.push_back(job);
+ }
+} \ No newline at end of file
diff --git a/Runtime/Threads/Thread.h b/Runtime/Threads/Thread.h
deleted file mode 100644
index e69de29..0000000
--- a/Runtime/Threads/Thread.h
+++ /dev/null