aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libjin/Thread/Thread.cpp67
-rw-r--r--src/libjin/Thread/Thread.h129
-rw-r--r--src/libjin/Utils/Proxy/lock.h4
-rw-r--r--src/libjin/jin.h8
-rw-r--r--src/libjin/thread/thread.cpp67
-rw-r--r--src/libjin/thread/thread.h129
-rw-r--r--src/lua/thread/luaopen_Thread.cpp50
-rw-r--r--src/lua/thread/luaopen_thread.cpp182
8 files changed, 461 insertions, 175 deletions
diff --git a/src/libjin/Thread/Thread.cpp b/src/libjin/Thread/Thread.cpp
index 06975f7..374778b 100644
--- a/src/libjin/Thread/Thread.cpp
+++ b/src/libjin/Thread/Thread.cpp
@@ -23,6 +23,7 @@ namespace thread
friend class Conditional;
};
+ // ̼߳signal wait
class Conditional
{
public:
@@ -43,15 +44,19 @@ namespace thread
Lock(Mutex* m) : mutex(m) {
mutex->lock();
}
+
Lock(Mutex& m) : mutex(&m) {
mutex->lock();
}
+
~Lock() {
mutex->unlock();
}
private:
Mutex* mutex;
+
Lock(Lock&) {}
+
};
//////////////////////////////////////////////////////////////////////
@@ -137,33 +142,43 @@ namespace thread
{
}
- void Thread::ThreadData::set(std::string name, Value value)
+ void Thread::ThreadData::set(int slot, Variant value)
{
- //if (share.count(name) != 0);
- share[name] = value;
+ Lock l(mutex);
+ share[slot] = value;
}
- Thread::Value Thread::ThreadData::get(std::string name)
+ Thread::Variant Thread::ThreadData::get(int slot)
{
- return share[name];
+ Lock l(mutex);
+ return share[slot];
}
- bool Thread::ThreadData::exist(const std::string& name)
+ bool Thread::ThreadData::exist(int slot)
{
- return share.count(name) == 1;
+ Lock l(mutex);
+ return share.count(slot) == 1;
}
- void Thread::ThreadData::remove(std::string name)
+ void Thread::ThreadData::remove(int slot)
{
Lock l(mutex);
- if (exist(name))
+ if (exist(slot))
{
- share.erase(name);
+ share.erase(slot);
}
}
//////////////////////////////////////////////////////////////////////
+ int Thread::ThreadFunciton(void* p)
+ {
+ Thread* thread = (Thread*)p;
+ if (thread->threadRunner != nullptr)
+ thread->threadRunner(thread);
+ return 0;
+ }
+
Thread::Thread(const std::string tname, ThreadRunner runner)
: name(tname)
, running(false)
@@ -204,7 +219,7 @@ namespace thread
#endif
}
#if JIN_THREAD_SDL
- handle = SDL_CreateThread(threadRunner, name.c_str(), this);
+ handle = SDL_CreateThread(ThreadFunciton, name.c_str(), this);
#elif JIN_THREAD_CPP
handle = new std::thread();
#endif
@@ -238,35 +253,45 @@ namespace thread
mutex->unlock();
}
- void Thread::send(std::string name, Value value)
+ void Thread::send(int slot, Variant value)
{
lock();
- common->set(name, value);
+ common->set(slot, value);
unlock();
condition->broadcast();
}
- bool Thread::receive(std::string name)
+ bool Thread::receive(int slot)
{
- return common->exist(name);
+ return common->exist(slot);
}
- Thread::Value Thread::fetch(std::string name)
+ Thread::Variant Thread::fetch(int slot)
{
- Thread::Value v = common->get(name);
+ Thread::Variant v = common->get(slot);
return v;
}
- Thread::Value Thread::demand(std::string name)
+ Thread::Variant Thread::demand(int slot)
{
+ /**
+ * pthread_mutex_lock(mtx);
+ * while(pass == 0)
+ * {
+ * pthread_mutex_unlock(mtx);
+ * pthread_cond_just_wait(cv);
+ * pthread_mutex_lock(mtx);
+ * }
+ * pthread_mutex_unlock(mtx);
+ */
lock();
- while (!common->exist(name))
+ while (!common->exist(slot))
{
- if (common->exist("error"))
+ if (common->exist(ThreadData::SLOT_ERROR))
return 0;
condition->wait(mutex);
}
- Thread::Value v = common->get(name);
+ Thread::Variant v = common->get(slot);
unlock();
return v;
}
diff --git a/src/libjin/Thread/Thread.h b/src/libjin/Thread/Thread.h
index 4996705..aeb0d9e 100644
--- a/src/libjin/Thread/Thread.h
+++ b/src/libjin/Thread/Thread.h
@@ -17,54 +17,48 @@ namespace jin
{
namespace thread
{
- /*
- * ӢӢMutual exclusionд Mutexһڶ̱߳Уֹ߳ͬʱͬһԴ
- * ȫֱждĻơĿͨƬһһٽcritical sectionɡٽ
- * ָһԹԴзʵĴ룬һֻƻ㷨һ򡢽̡߳̿ӵжٽ򣬵Dz
- * һӦûҪ˻ƵԴУꡢСжϴڶеĴ
- * ݡͬ״̬ȵԴάЩԴͬһºǺѵģΪһ߳̿κһʱ̱ͣ
- * ߣ߻ָѣ
- */
+ /**
+ * ӢӢMutual exclusionд Mutexһڶ̱߳Уֹ߳ͬʱͬһԴ
+ * ȫֱждĻơĿͨƬһһٽcritical sectionɡٽ
+ * ָһԹԴзʵĴ룬һֻƻ㷨һ򡢽̡߳̿ӵжٽ򣬵Dz
+ * һӦûҪ˻ƵԴУꡢСжϴڶеĴ
+ * ݡͬ״̬ȵԴάЩԴͬһºǺѵģΪһ߳̿κһʱ̱ͣ
+ * ߣ߻ָѣ
+ */
class Mutex;
class Conditional;
- /*
- * Thread:demand Receive a message from a thread. Wait for the message to exist before returning.
- * Thread:getName Get the name of a thread.
- * Thread:kill Forcefully terminate the thread.
- * Thread:peek Receive a message from a thread, but leave it in the message box.
- * Thread:receive Receive a message from a thread.
- * Thread:send Send a message.
- * Thread:set Set a value.
- * Thread:start Starts the thread.
- * Thread:wait Wait for a thread to finish.
- */
+ /**
+ * Thread::demand Receive a message from a thread. Wait for the message to exist before returning.
+ * Thread::getName Get the name of a thread.
+ * Thread::kill Forcefully terminate the thread.
+ * Thread::peek Receive a message from a thread, but leave it in the message box.
+ * Thread::receive Receive a message from a thread.
+ * Thread::send Send a message.
+ * Thread::set Set a value.
+ * Thread::start Starts the thread.
+ * Thread::wait Wait for a thread to finish.
+ */
class Thread
{
public:
- union Value
+
+ union Variant
{
- enum
- {
- INTEGER,
- REAL,
- BOOL,
- STRING,
- POINTER
- } type;
-
int integer;
- float real;
bool boolean;
+ char character;
const char* cstring;
void* pointer;
+ float real;
- Value() {};
- Value(int i) : integer(i), type(INTEGER){};
- Value(float r) : real(r), type(REAL) {};
- Value(bool b) : boolean(b), type(BOOL) {};
- Value(const char* cstr) : cstring(cstr), type(STRING) {};
- Value(void* p) : pointer(p), type(POINTER) {};
+ Variant() {};
+ Variant(int i) : integer(i) {};
+ Variant(float f) : real(f) {};
+ Variant(bool b) : boolean(b) {};
+ Variant(char c) : character(c) {};
+ Variant(const char* s) : cstring(s) {};
+ Variant(void* p) : pointer(p) {};
};
private:
@@ -73,36 +67,36 @@ namespace thread
public:
ThreadData(Mutex*, Conditional*);
~ThreadData();
- bool exist(const std::string& name);
- void set(std::string name, Value value);
- Value get(std::string name);
- void remove(std::string name);
+ bool exist(int slot);
+ void set(int slot, Variant value);
+ Variant get(int slot);
+ void remove(int slot);
Conditional* condition;
Mutex* mutex;
+ static const int SLOT_ERROR = -1;
+ static const int SLOT_WARN = -2;
+
private:
- std::map<std::string, Value> share; // threads shared value
- std::map<std::string, void*> sharevalue;
+ std::map<int, Variant> share; // threads shared value
};
public:
- typedef int(ThreadRunner)(void* /*ThreadData*/);
+ typedef void(ThreadRunner)(Thread* thread);
Thread(const std::string name, ThreadRunner threadfuncs);
~Thread();
bool start();
void wait();
- void send(std::string name, Value value);
- bool receive(std::string name);
- Value fetch(std::string name);
- Value demand(std::string name);
+ void send(int slot, Variant value);
+ bool receive(int slot);
+ Variant fetch(int slot);
+ Variant demand(int slot);
const char* getName();
bool isRunning();
- //void kill();
- //Value peek();
-
- private:
void lock();
void unlock();
+
+ private:
#if JIN_THREAD_SDL
SDL_Thread* handle; // SDL thread
#elif JIN_THREAD_CPP
@@ -112,9 +106,40 @@ namespace thread
Conditional* condition; // condition variable
ThreadRunner* threadRunner; // thread function
ThreadData* common; // threads common data
- const std::string name; // thread name
+ const std::string name; // thread name, for debugging purposes
+ /**
+ * https://stackoverflow.com/questions/149932/naming-conventions-for-threads
+ *
+ * Use short names because they don't make the lines in a log file too long.
+ *
+ * Create names where the important part is at the beginning. Log viewers in a
+ * graphical user interface tend to have tables with columns, and the thread
+ * column is usually small or will be made small by you to read everything else.
+ *
+ * Do not use the word "thread" in the thread name because it is obvious.
+ *
+ * Make the thread names easily grep-able. Avoid similar sounding thread names
+ *
+ * If you have several threads of the same nature, enumerate them with IDs that
+ * are unique to one execution of the application or one log file, whichever fits
+ * your logging habits.
+ *
+ * Avoid generalizations like "WorkerThread" (how do you name the next 5 worker
+ * threads?), "GUIThread" (which GUI? is it for one window? for everything?) or
+ * "Calculation" (what does it calculate?).
+ *
+ * If you have a test group that uses thread names to grep your application's log
+ * files, do not rename your threads after some time. Your testers will hate you for
+ * doing so. Thread names in well-tested applications should be there to stay.
+ *
+ * When you have threads that service a network connection, try to include the target
+ * network address in the thread name (e.g. channel_123.212.123.3). Don't forget about
+ * enumeration though if there are multiple connections to the same host.
+ */
bool running; // running
+ static int ThreadFunciton(void* p);
+
};
} // thread
diff --git a/src/libjin/Utils/Proxy/lock.h b/src/libjin/Utils/Proxy/lock.h
new file mode 100644
index 0000000..29194a1
--- /dev/null
+++ b/src/libjin/Utils/Proxy/lock.h
@@ -0,0 +1,4 @@
+class Lock
+{
+
+}; \ No newline at end of file
diff --git a/src/libjin/jin.h b/src/libjin/jin.h
index 148911c..ad83fae 100644
--- a/src/libjin/jin.h
+++ b/src/libjin/jin.h
@@ -15,9 +15,9 @@
#include "Time/Timer.h"
#include "Thread/Thread.h"
-#define JIN_VERSION "Jin 0.1"
-#define JIN_AUTHOR "Chai"
-#define JIN_RELEASE "Jin 0.1.1"
-#define JIN_VERSION_NUM 101;
+const char* JIN_VERSION = "Jin 0.1";
+const char* JIN_AUTHOR = "Chai";
+const char* JIN_RELEASE = "Jin 0.1.1";
+const int JIN_VERSION_NUM = 101;
#endif // __JIN_H \ No newline at end of file
diff --git a/src/libjin/thread/thread.cpp b/src/libjin/thread/thread.cpp
index 06975f7..374778b 100644
--- a/src/libjin/thread/thread.cpp
+++ b/src/libjin/thread/thread.cpp
@@ -23,6 +23,7 @@ namespace thread
friend class Conditional;
};
+ // ̼߳signal wait
class Conditional
{
public:
@@ -43,15 +44,19 @@ namespace thread
Lock(Mutex* m) : mutex(m) {
mutex->lock();
}
+
Lock(Mutex& m) : mutex(&m) {
mutex->lock();
}
+
~Lock() {
mutex->unlock();
}
private:
Mutex* mutex;
+
Lock(Lock&) {}
+
};
//////////////////////////////////////////////////////////////////////
@@ -137,33 +142,43 @@ namespace thread
{
}
- void Thread::ThreadData::set(std::string name, Value value)
+ void Thread::ThreadData::set(int slot, Variant value)
{
- //if (share.count(name) != 0);
- share[name] = value;
+ Lock l(mutex);
+ share[slot] = value;
}
- Thread::Value Thread::ThreadData::get(std::string name)
+ Thread::Variant Thread::ThreadData::get(int slot)
{
- return share[name];
+ Lock l(mutex);
+ return share[slot];
}
- bool Thread::ThreadData::exist(const std::string& name)
+ bool Thread::ThreadData::exist(int slot)
{
- return share.count(name) == 1;
+ Lock l(mutex);
+ return share.count(slot) == 1;
}
- void Thread::ThreadData::remove(std::string name)
+ void Thread::ThreadData::remove(int slot)
{
Lock l(mutex);
- if (exist(name))
+ if (exist(slot))
{
- share.erase(name);
+ share.erase(slot);
}
}
//////////////////////////////////////////////////////////////////////
+ int Thread::ThreadFunciton(void* p)
+ {
+ Thread* thread = (Thread*)p;
+ if (thread->threadRunner != nullptr)
+ thread->threadRunner(thread);
+ return 0;
+ }
+
Thread::Thread(const std::string tname, ThreadRunner runner)
: name(tname)
, running(false)
@@ -204,7 +219,7 @@ namespace thread
#endif
}
#if JIN_THREAD_SDL
- handle = SDL_CreateThread(threadRunner, name.c_str(), this);
+ handle = SDL_CreateThread(ThreadFunciton, name.c_str(), this);
#elif JIN_THREAD_CPP
handle = new std::thread();
#endif
@@ -238,35 +253,45 @@ namespace thread
mutex->unlock();
}
- void Thread::send(std::string name, Value value)
+ void Thread::send(int slot, Variant value)
{
lock();
- common->set(name, value);
+ common->set(slot, value);
unlock();
condition->broadcast();
}
- bool Thread::receive(std::string name)
+ bool Thread::receive(int slot)
{
- return common->exist(name);
+ return common->exist(slot);
}
- Thread::Value Thread::fetch(std::string name)
+ Thread::Variant Thread::fetch(int slot)
{
- Thread::Value v = common->get(name);
+ Thread::Variant v = common->get(slot);
return v;
}
- Thread::Value Thread::demand(std::string name)
+ Thread::Variant Thread::demand(int slot)
{
+ /**
+ * pthread_mutex_lock(mtx);
+ * while(pass == 0)
+ * {
+ * pthread_mutex_unlock(mtx);
+ * pthread_cond_just_wait(cv);
+ * pthread_mutex_lock(mtx);
+ * }
+ * pthread_mutex_unlock(mtx);
+ */
lock();
- while (!common->exist(name))
+ while (!common->exist(slot))
{
- if (common->exist("error"))
+ if (common->exist(ThreadData::SLOT_ERROR))
return 0;
condition->wait(mutex);
}
- Thread::Value v = common->get(name);
+ Thread::Variant v = common->get(slot);
unlock();
return v;
}
diff --git a/src/libjin/thread/thread.h b/src/libjin/thread/thread.h
index 4996705..aeb0d9e 100644
--- a/src/libjin/thread/thread.h
+++ b/src/libjin/thread/thread.h
@@ -17,54 +17,48 @@ namespace jin
{
namespace thread
{
- /*
- * ӢӢMutual exclusionд Mutexһڶ̱߳Уֹ߳ͬʱͬһԴ
- * ȫֱждĻơĿͨƬһһٽcritical sectionɡٽ
- * ָһԹԴзʵĴ룬һֻƻ㷨һ򡢽̡߳̿ӵжٽ򣬵Dz
- * һӦûҪ˻ƵԴУꡢСжϴڶеĴ
- * ݡͬ״̬ȵԴάЩԴͬһºǺѵģΪһ߳̿κһʱ̱ͣ
- * ߣ߻ָѣ
- */
+ /**
+ * ӢӢMutual exclusionд Mutexһڶ̱߳Уֹ߳ͬʱͬһԴ
+ * ȫֱждĻơĿͨƬһһٽcritical sectionɡٽ
+ * ָһԹԴзʵĴ룬һֻƻ㷨һ򡢽̡߳̿ӵжٽ򣬵Dz
+ * һӦûҪ˻ƵԴУꡢСжϴڶеĴ
+ * ݡͬ״̬ȵԴάЩԴͬһºǺѵģΪһ߳̿κһʱ̱ͣ
+ * ߣ߻ָѣ
+ */
class Mutex;
class Conditional;
- /*
- * Thread:demand Receive a message from a thread. Wait for the message to exist before returning.
- * Thread:getName Get the name of a thread.
- * Thread:kill Forcefully terminate the thread.
- * Thread:peek Receive a message from a thread, but leave it in the message box.
- * Thread:receive Receive a message from a thread.
- * Thread:send Send a message.
- * Thread:set Set a value.
- * Thread:start Starts the thread.
- * Thread:wait Wait for a thread to finish.
- */
+ /**
+ * Thread::demand Receive a message from a thread. Wait for the message to exist before returning.
+ * Thread::getName Get the name of a thread.
+ * Thread::kill Forcefully terminate the thread.
+ * Thread::peek Receive a message from a thread, but leave it in the message box.
+ * Thread::receive Receive a message from a thread.
+ * Thread::send Send a message.
+ * Thread::set Set a value.
+ * Thread::start Starts the thread.
+ * Thread::wait Wait for a thread to finish.
+ */
class Thread
{
public:
- union Value
+
+ union Variant
{
- enum
- {
- INTEGER,
- REAL,
- BOOL,
- STRING,
- POINTER
- } type;
-
int integer;
- float real;
bool boolean;
+ char character;
const char* cstring;
void* pointer;
+ float real;
- Value() {};
- Value(int i) : integer(i), type(INTEGER){};
- Value(float r) : real(r), type(REAL) {};
- Value(bool b) : boolean(b), type(BOOL) {};
- Value(const char* cstr) : cstring(cstr), type(STRING) {};
- Value(void* p) : pointer(p), type(POINTER) {};
+ Variant() {};
+ Variant(int i) : integer(i) {};
+ Variant(float f) : real(f) {};
+ Variant(bool b) : boolean(b) {};
+ Variant(char c) : character(c) {};
+ Variant(const char* s) : cstring(s) {};
+ Variant(void* p) : pointer(p) {};
};
private:
@@ -73,36 +67,36 @@ namespace thread
public:
ThreadData(Mutex*, Conditional*);
~ThreadData();
- bool exist(const std::string& name);
- void set(std::string name, Value value);
- Value get(std::string name);
- void remove(std::string name);
+ bool exist(int slot);
+ void set(int slot, Variant value);
+ Variant get(int slot);
+ void remove(int slot);
Conditional* condition;
Mutex* mutex;
+ static const int SLOT_ERROR = -1;
+ static const int SLOT_WARN = -2;
+
private:
- std::map<std::string, Value> share; // threads shared value
- std::map<std::string, void*> sharevalue;
+ std::map<int, Variant> share; // threads shared value
};
public:
- typedef int(ThreadRunner)(void* /*ThreadData*/);
+ typedef void(ThreadRunner)(Thread* thread);
Thread(const std::string name, ThreadRunner threadfuncs);
~Thread();
bool start();
void wait();
- void send(std::string name, Value value);
- bool receive(std::string name);
- Value fetch(std::string name);
- Value demand(std::string name);
+ void send(int slot, Variant value);
+ bool receive(int slot);
+ Variant fetch(int slot);
+ Variant demand(int slot);
const char* getName();
bool isRunning();
- //void kill();
- //Value peek();
-
- private:
void lock();
void unlock();
+
+ private:
#if JIN_THREAD_SDL
SDL_Thread* handle; // SDL thread
#elif JIN_THREAD_CPP
@@ -112,9 +106,40 @@ namespace thread
Conditional* condition; // condition variable
ThreadRunner* threadRunner; // thread function
ThreadData* common; // threads common data
- const std::string name; // thread name
+ const std::string name; // thread name, for debugging purposes
+ /**
+ * https://stackoverflow.com/questions/149932/naming-conventions-for-threads
+ *
+ * Use short names because they don't make the lines in a log file too long.
+ *
+ * Create names where the important part is at the beginning. Log viewers in a
+ * graphical user interface tend to have tables with columns, and the thread
+ * column is usually small or will be made small by you to read everything else.
+ *
+ * Do not use the word "thread" in the thread name because it is obvious.
+ *
+ * Make the thread names easily grep-able. Avoid similar sounding thread names
+ *
+ * If you have several threads of the same nature, enumerate them with IDs that
+ * are unique to one execution of the application or one log file, whichever fits
+ * your logging habits.
+ *
+ * Avoid generalizations like "WorkerThread" (how do you name the next 5 worker
+ * threads?), "GUIThread" (which GUI? is it for one window? for everything?) or
+ * "Calculation" (what does it calculate?).
+ *
+ * If you have a test group that uses thread names to grep your application's log
+ * files, do not rename your threads after some time. Your testers will hate you for
+ * doing so. Thread names in well-tested applications should be there to stay.
+ *
+ * When you have threads that service a network connection, try to include the target
+ * network address in the thread name (e.g. channel_123.212.123.3). Don't forget about
+ * enumeration though if there are multiple connections to the same host.
+ */
bool running; // running
+ static int ThreadFunciton(void* p);
+
};
} // thread
diff --git a/src/lua/thread/luaopen_Thread.cpp b/src/lua/thread/luaopen_Thread.cpp
index c08c262..99ddee1 100644
--- a/src/lua/thread/luaopen_Thread.cpp
+++ b/src/lua/thread/luaopen_Thread.cpp
@@ -32,9 +32,9 @@ namespace jin
return nullptr;
}
- static int threadRunner(void* p)
+ static void threadRunner(jin::thread::Thread* t)
{
- Thread* thread = (Thread*)p;
+ Thread* thread = (Thread*)t;
lua_State* L = lua_open();
luax_openlibs(L);
luaopen_jin(L);
@@ -64,21 +64,21 @@ namespace jin
static int l_send(lua_State* L)
{
Thread* t = checkThread(L);
- const char* name = luax_checkstring(L, 2);
+ int slot = luax_checkinteger(L, 2);
if (luax_isnumber(L, 3))
{
float real = luax_checknumber(L, 3);
- t->send(name, real);
+ t->send(slot, real);
}
else if (luax_isboolean(L, 3))
{
bool bol = luax_checkbool(L, 3);
- t->send(name, bol);
+ t->send(slot, bol);
}
else if (luax_isstring(L, 3))
{
const char* str = luax_checkstring(L, 3);
- t->send(name, str);
+ t->send(slot, str);
}
return 0;
}
@@ -86,8 +86,8 @@ namespace jin
static int l_receive(lua_State* L)
{
Thread* t = checkThread(L);
- const char* name = luax_checkstring(L, 2);
- bool result = t->receive(name);
+ int slot = luax_checkinteger(L, 2);
+ bool result = t->receive(slot);
luax_pushboolean(L, result);
return 1;
}
@@ -95,23 +95,23 @@ namespace jin
static int l_fetch(lua_State* L)
{
Thread* t = checkThread(L);
- const char* name = luax_checkstring(L, 2);
- Thread::Value v = t->fetch(name);
- if (v.type == Thread::Value::INTEGER)
- {
- luax_pushinteger(L, v.integer);
- }
- else if (v.type == Thread::Value::BOOL)
- {
- luax_pushboolean(L, v.boolean);
- }
- else if (v.type == Thread::Value::STRING)
- {
- luax_pushstring(L, v.cstring);
- }
- else if (v.type == Thread::Value::POINTER)
- {
- }
+ int slot = luax_checkinteger(L, 2);
+ Thread::Variant v = t->fetch(slot);
+ //if (v.type == Thread::Value::INTEGER)
+ //{
+ // luax_pushinteger(L, v.integer);
+ //}
+ //else if (v.type == Thread::Value::BOOL)
+ //{
+ // luax_pushboolean(L, v.boolean);
+ //}
+ //else if (v.type == Thread::Value::STRING)
+ //{
+ // luax_pushstring(L, v.cstring);
+ //}
+ //else if (v.type == Thread::Value::POINTER)
+ //{
+ //}
return 1;
}
diff --git a/src/lua/thread/luaopen_thread.cpp b/src/lua/thread/luaopen_thread.cpp
new file mode 100644
index 0000000..99ddee1
--- /dev/null
+++ b/src/lua/thread/luaopen_thread.cpp
@@ -0,0 +1,182 @@
+#include "lua/luax.h"
+#include "libjin/jin.h"
+#include "../luaopen_jin.h"
+#include "../luaopen_types.h"
+
+namespace jin
+{
+ namespace lua
+ {
+
+ static int luaopen_thread(lua_State* L);
+
+ class Thread : public jin::thread::Thread
+ {
+ public:
+ Thread(std::string _name, std::string _code, jin::thread::Thread::ThreadRunner runner)
+ : jin::thread::Thread(name, runner)
+ , name(_name)
+ , code(_code)
+ {
+ }
+
+ const std::string name;
+ const std::string code;
+ };
+
+ static inline Thread* checkThread(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, TYPE_THREAD);
+ if (proxy != nullptr)
+ return (Thread*)proxy->object;
+ return nullptr;
+ }
+
+ static void threadRunner(jin::thread::Thread* t)
+ {
+ Thread* thread = (Thread*)t;
+ lua_State* L = lua_open();
+ luax_openlibs(L);
+ luaopen_jin(L);
+ luax_dostring(L, thread->code.c_str());
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ return 1;
+ }
+
+ static int l_start(lua_State* L)
+ {
+ Thread* t = checkThread(L);
+ bool result = t->start();
+ luax_pushboolean(L, result);
+ return 1;
+ }
+
+ static int l_wait(lua_State* L)
+ {
+ Thread* t = checkThread(L);
+ t->wait();
+ return 0;
+ }
+
+ static int l_send(lua_State* L)
+ {
+ Thread* t = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ if (luax_isnumber(L, 3))
+ {
+ float real = luax_checknumber(L, 3);
+ t->send(slot, real);
+ }
+ else if (luax_isboolean(L, 3))
+ {
+ bool bol = luax_checkbool(L, 3);
+ t->send(slot, bol);
+ }
+ else if (luax_isstring(L, 3))
+ {
+ const char* str = luax_checkstring(L, 3);
+ t->send(slot, str);
+ }
+ return 0;
+ }
+
+ static int l_receive(lua_State* L)
+ {
+ Thread* t = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ bool result = t->receive(slot);
+ luax_pushboolean(L, result);
+ return 1;
+ }
+
+ static int l_fetch(lua_State* L)
+ {
+ Thread* t = checkThread(L);
+ int slot = luax_checkinteger(L, 2);
+ Thread::Variant v = t->fetch(slot);
+ //if (v.type == Thread::Value::INTEGER)
+ //{
+ // luax_pushinteger(L, v.integer);
+ //}
+ //else if (v.type == Thread::Value::BOOL)
+ //{
+ // luax_pushboolean(L, v.boolean);
+ //}
+ //else if (v.type == Thread::Value::STRING)
+ //{
+ // luax_pushstring(L, v.cstring);
+ //}
+ //else if (v.type == Thread::Value::POINTER)
+ //{
+ //}
+ return 1;
+ }
+
+ static int l_demand(lua_State* L)
+ {
+ Thread* t = checkThread(L);
+
+ return 1;
+ }
+
+ static int l_getName(lua_State* L)
+ {
+ return 1;
+ }
+
+ static int l_isRunning(lua_State* L)
+ {
+ return 1;
+ }
+
+ static const luaL_Reg thread_function[] = {
+ { "__gc", l_gc },
+ { "start", l_start },
+ { "wait", l_wait },
+ { "send", l_send },
+ { "receive", l_receive },
+ { "fetch", l_fetch },
+ { "demand", l_demand },
+ { "getName", l_getName },
+ { "isRunning", l_isRunning },
+ { 0, 0 }
+ };
+
+ static int luaopen_Thread(lua_State* L)
+ {
+ luax_newtype(L, TYPE_SOURCE, thread_function);
+
+ return 0;
+ }
+
+ // jin.thread.Thread(name)
+ static int l_newThread(lua_State* L)
+ {
+ const char* name = luax_checkstring(L, 1);
+ const char* code = luax_checkstring(L, 2);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, TYPE_THREAD, sizeof(Proxy));
+ Thread* thread = new Thread(name, code, threadRunner);
+ proxy->bind(thread);
+ return 1;
+ }
+
+ static int l_getThread(lua_State* L)
+ {
+
+ }
+
+ static const luaL_Reg f[] = {
+ { "Thread", l_newThread},
+ { "getThread", l_getThread},
+ { 0, 0 }
+ };
+
+ static int luaopen_thread(lua_State* L)
+ {
+
+ }
+ }
+} \ No newline at end of file