aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2018-08-07 23:29:28 +0800
committerchai <chaifix@163.com>2018-08-07 23:29:28 +0800
commitf5e30a91cfe12118d2c5d389687ebb931a196c7c (patch)
tree8d410f5c4fcf421d18ef0c95dd4b6a8b3e247a46
parent2576caf003fdb3162ab8a3c7bf77c38a885c3858 (diff)
*update
-rw-r--r--bin/jin.exebin817664 -> 817664 bytes
-rw-r--r--build/vs2015/jin.rcbin3268 -> 3330 bytes
-rw-r--r--build/vs2015/jin.vcxproj2
-rw-r--r--build/vs2015/jin.vcxproj.filters2
-rw-r--r--res/icon.icobin0 -> 16958 bytes
-rw-r--r--res/icon.pngbin0 -> 40629 bytes
-rw-r--r--src/icon.icobin16958 -> 0 bytes
-rw-r--r--src/icon.jpgbin88290 -> 0 bytes
-rw-r--r--src/libjin/Thread/thread.cpp309
-rw-r--r--src/libjin/Thread/thread.h165
-rw-r--r--src/libjin/Utils/log.h134
11 files changed, 610 insertions, 2 deletions
diff --git a/bin/jin.exe b/bin/jin.exe
index 6aacb12..5605a29 100644
--- a/bin/jin.exe
+++ b/bin/jin.exe
Binary files differ
diff --git a/build/vs2015/jin.rc b/build/vs2015/jin.rc
index da0fb26..01bf177 100644
--- a/build/vs2015/jin.rc
+++ b/build/vs2015/jin.rc
Binary files differ
diff --git a/build/vs2015/jin.vcxproj b/build/vs2015/jin.vcxproj
index 4459824..8c9e5c5 100644
--- a/build/vs2015/jin.vcxproj
+++ b/build/vs2015/jin.vcxproj
@@ -330,7 +330,7 @@
<ResourceCompile Include="jin.rc" />
</ItemGroup>
<ItemGroup>
- <Image Include="..\..\src\icon.ico" />
+ <Image Include="..\..\res\icon.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/build/vs2015/jin.vcxproj.filters b/build/vs2015/jin.vcxproj.filters
index 9b4c750..50d8138 100644
--- a/build/vs2015/jin.vcxproj.filters
+++ b/build/vs2015/jin.vcxproj.filters
@@ -706,6 +706,6 @@
<ResourceCompile Include="jin.rc" />
</ItemGroup>
<ItemGroup>
- <Image Include="..\..\src\icon.ico" />
+ <Image Include="..\..\res\icon.ico" />
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/res/icon.ico b/res/icon.ico
new file mode 100644
index 0000000..9c0209f
--- /dev/null
+++ b/res/icon.ico
Binary files differ
diff --git a/res/icon.png b/res/icon.png
new file mode 100644
index 0000000..58bc2fa
--- /dev/null
+++ b/res/icon.png
Binary files differ
diff --git a/src/icon.ico b/src/icon.ico
deleted file mode 100644
index 2cc6f15..0000000
--- a/src/icon.ico
+++ /dev/null
Binary files differ
diff --git a/src/icon.jpg b/src/icon.jpg
deleted file mode 100644
index fee2575..0000000
--- a/src/icon.jpg
+++ /dev/null
Binary files differ
diff --git a/src/libjin/Thread/thread.cpp b/src/libjin/Thread/thread.cpp
new file mode 100644
index 0000000..064d3db
--- /dev/null
+++ b/src/libjin/Thread/thread.cpp
@@ -0,0 +1,309 @@
+#include "../modules.h"
+#if JIN_MODULES_THREAD
+
+#include "Thread.h"
+
+namespace jin
+{
+namespace thread
+{
+
+ class Mutex
+ {
+ public:
+ Mutex();
+ ~Mutex();
+
+ void lock();
+ void unlock();
+ private:
+ #if JIN_THREAD_SDL
+ SDL_mutex* mutex;
+ #endif
+ friend class Conditional;
+ };
+
+ // ̼߳signal wait
+ class Conditional
+ {
+ public:
+ Conditional();
+ ~Conditional();
+ void signal();
+ void broadcast();
+ bool wait(Mutex* mutex, int timeout = -1);
+ private:
+ #if JIN_THREAD_SDL
+ SDL_cond* cond;
+ #endif
+ };
+
+ class Lock
+ {
+ public:
+ Lock(Mutex* m) : mutex(m) {
+ mutex->lock();
+ }
+
+ Lock(Mutex& m) : mutex(&m) {
+ mutex->lock();
+ }
+
+ ~Lock() {
+ mutex->unlock();
+ }
+ private:
+ Mutex* mutex;
+
+ Lock(Lock&) {}
+
+ };
+
+ //////////////////////////////////////////////////////////////////////
+
+ Mutex::Mutex()
+ {
+ #if JIN_THREAD_SDL
+ mutex = SDL_CreateMutex();
+ #endif
+ }
+
+ Mutex::~Mutex()
+ {
+ #if JIN_THREAD_SDL
+ SDL_DestroyMutex(mutex);
+ #endif
+ }
+
+ void Mutex::lock()
+ {
+ #if JIN_THREAD_SDL
+ SDL_LockMutex(mutex);
+ #endif
+ }
+
+ void Mutex::unlock()
+ {
+ #if JIN_THREAD_SDL
+ SDL_UnlockMutex(mutex);
+ #endif
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ Conditional::Conditional()
+ {
+ #if JIN_THREAD_SDL
+ cond = SDL_CreateCond();
+ #endif
+ }
+
+ Conditional::~Conditional()
+ {
+ #if JIN_THREAD_SDL
+ SDL_DestroyCond(cond);
+ #endif
+ }
+
+ void Conditional::signal()
+ {
+ #if JIN_THREAD_SDL
+ SDL_CondSignal(cond);
+ #endif
+ }
+
+ void Conditional::broadcast()
+ {
+ #if JIN_THREAD_SDL
+ SDL_CondBroadcast(cond);
+ #endif
+ }
+
+ bool Conditional::wait(Mutex* mutex, int timeout)
+ {
+ #if JIN_THREAD_SDL
+ if (timeout < 0)
+ return !SDL_CondWait(cond, mutex->mutex);
+ else
+ return (SDL_CondWaitTimeout(cond, mutex->mutex, timeout) == 0);
+ #endif
+ }
+
+ //////////////////////////////////////////////////////////////////////
+
+ Thread::ThreadData::ThreadData(Mutex* m, Conditional* c)
+ : mutex(m)
+ , condition(c)
+ , share()
+ {
+ }
+
+ Thread::ThreadData::~ThreadData()
+ {
+ }
+
+ void Thread::ThreadData::set(int slot, Variant value)
+ {
+ Lock l(mutex);
+ share[slot] = value;
+ }
+
+ Thread::Variant Thread::ThreadData::get(int slot)
+ {
+ Lock l(mutex);
+ return share[slot];
+ }
+
+ bool Thread::ThreadData::exist(int slot)
+ {
+ Lock l(mutex);
+ return share.count(slot) == 1;
+ }
+
+ void Thread::ThreadData::remove(int slot)
+ {
+ Lock l(mutex);
+ if (exist(slot))
+ {
+ 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)
+ , threadRunner(runner)
+ {
+ mutex = new Mutex();
+ condition = new Conditional();
+ common = new Thread::ThreadData(mutex, condition);
+ }
+
+ Thread::~Thread()
+ {
+ #if JIN_THREAD_SDL
+ #endif
+ }
+
+ const char* Thread::getName()
+ {
+ Lock l(mutex);
+ return name.c_str();
+ };
+
+ bool Thread::isRunning()
+ {
+ Lock l(mutex);
+ return running;
+ };
+
+ bool Thread::start()
+ {
+ Lock l(mutex);
+ if (running)
+ return false;
+ if (handle)
+ {
+ #if JIN_THREAD_SDL
+ SDL_WaitThread(handle, nullptr);
+ #endif
+ }
+ #if JIN_THREAD_SDL
+ handle = SDL_CreateThread(ThreadFunciton, name.c_str(), this);
+ #elif JIN_THREAD_CPP
+ handle = new std::thread();
+ #endif
+ return (running = (handle != nullptr));
+ }
+
+ void Thread::wait()
+ {
+ {
+ Lock l(mutex);
+ if (!handle)
+ return;
+ }
+ #if JIN_THREAD_SDL
+ SDL_WaitThread(handle, nullptr);
+ #endif
+ Lock l(mutex);
+ running = false;
+ handle = nullptr;
+ }
+
+ void Thread::lock()
+ {
+ if (mutex != nullptr)
+ mutex->lock();
+ }
+
+ void Thread::unlock()
+ {
+ if (mutex != nullptr)
+ mutex->unlock();
+ }
+
+ void Thread::send(int slot, Variant value)
+ {
+ lock();
+ common->set(slot, value);
+ unlock();
+ condition->broadcast();
+ }
+
+ bool Thread::receive(int slot)
+ {
+ return common->exist(slot);
+ }
+
+ Thread::Variant Thread::fetch(int slot)
+ {
+ Thread::Variant v = common->get(slot);
+ return v;
+ }
+
+ 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(slot))
+ {
+ if (common->exist(ThreadData::SLOT_ERROR))
+ return 0;
+ condition->wait(mutex);
+ }
+ Thread::Variant v = common->get(slot);
+ unlock();
+ return v;
+ }
+
+ void Thread::remove(int slot)
+ {
+ lock();
+ common->remove(slot);
+ unlock();
+ }
+
+} // thread
+} // jin
+
+#endif // JIN_MODULES_THREAD \ No newline at end of file
diff --git a/src/libjin/Thread/thread.h b/src/libjin/Thread/thread.h
new file mode 100644
index 0000000..37c978d
--- /dev/null
+++ b/src/libjin/Thread/thread.h
@@ -0,0 +1,165 @@
+#ifndef __JIN_THREAD_H
+#define __JIN_THREAD_H
+#include "../modules.h"
+#if JIN_MODULES_THREAD
+
+#include <string>
+#include <map>
+#if JIN_THREAD_SDL
+# include "SDL2/SDL_thread.h"
+#elif JIN_THREAD_CPP
+# include <thread>
+# include <mutex>
+# include <condition_variable>
+#endif
+
+namespace jin
+{
+namespace thread
+{
+ /**
+ * ӢӢ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.
+ */
+ class Thread
+ {
+ public:
+ struct Variant
+ {
+ enum Type
+ {
+ NONE = 0,
+ INTERGER,
+ BOOLEAN,
+ CHARACTER,
+ CSTRING,
+ POINTER,
+ REAL,
+ };
+ Type type;
+ union
+ {
+ int integer;
+ bool boolean;
+ char character;
+ const char* cstring;
+ void* pointer;
+ float real;
+ };
+ Variant() :type(NONE) {};
+ Variant(const Variant& v){ memcpy(this, &v, sizeof(v)); }
+ Variant(int i) : integer(i), type(INTERGER) {};
+ Variant(float f) : real(f), type(REAL) {};
+ Variant(bool b) : boolean(b), type(BOOLEAN) {};
+ Variant(char c) : character(c), type(CHARACTER) {};
+ Variant(const char* s) : cstring(s), type(CSTRING) {};
+ Variant(void* p) : pointer(p), type(POINTER) {};
+ };
+
+ private:
+ class ThreadData
+ {
+ public:
+ ThreadData(Mutex*, Conditional*);
+ ~ThreadData();
+ 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;
+ static const int SLOT_INFO = -3;
+ static const int SLOT_DEBUG = -4;
+
+ private:
+ std::map<int, Variant> share; // threads shared value
+ };
+
+ public:
+ typedef void(ThreadRunner)(Thread* thread);
+ Thread(const std::string name, ThreadRunner threadfuncs);
+ ~Thread();
+ bool start();
+ void wait();
+ void send(int slot, Variant value);
+ bool receive(int slot);
+ Variant fetch(int slot);
+ Variant demand(int slot);
+ void remove(int slot);
+ const char* getName();
+ bool isRunning();
+ void lock();
+ void unlock();
+
+ private:
+ #if JIN_THREAD_SDL
+ SDL_Thread* handle; // SDL thread
+ #elif JIN_THREAD_CPP
+ std::thread* handle; // cpp thread
+ #endif
+ Mutex* mutex; // mutex variable
+ Conditional* condition; // condition variable
+ ThreadRunner* threadRunner; // thread function
+ ThreadData* common; // threads common data
+ 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
+} // jin
+
+#endif // JIN_MODULES_THREAD
+#endif // __JIN_THREAD_H \ No newline at end of file
diff --git a/src/libjin/Utils/log.h b/src/libjin/Utils/log.h
new file mode 100644
index 0000000..50ec3c8
--- /dev/null
+++ b/src/libjin/Utils/log.h
@@ -0,0 +1,134 @@
+/**
+* Single.h/loghelper.h
+* Copyright (C) 2017~2018 chai
+*/
+#ifndef __LOG_HELPER_H
+#define __LOG_HELPER_H
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <stdarg.h>
+
+class Loghelper
+{
+public:
+ // logĿ
+ enum Direction
+ {
+ DIR_CERR = 1 << 1, // ׼
+ DIR_FILE = 1 << 2, // logļ
+ };
+
+ // ȼ
+ enum Level
+ {
+ LV_NONE = 0, // none
+ LV_ERROR = 1 << 1, // error
+ LV_WARN = 1 << 2, // warn
+ LV_INFO = 1 << 3, // info
+ LV_DEBUG = 1 << 4, // debug
+ LV_ALL = 0xffffffff
+ };
+
+ static void log(Level _level, const char* _fmt, ...);
+
+ // ض
+ static void redirect(unsigned int _dir, char* _path = nullptr);
+
+ // ɸѡȼ
+ static void restrict(unsigned int levels);
+
+ static void close();
+
+private:
+ static unsigned int dir; // Ŀ
+ static unsigned int levels; // ȼ
+ static std::ofstream fs; // ļ
+};
+
+typedef Loghelper::Level Loglevel;
+
+#ifdef LOGHELPER_IMPLEMENT
+
+#define hasbit(flag, bit) ((flag & bit) == bit)
+
+unsigned int Loghelper::dir = Loghelper::Direction::DIR_CERR;
+unsigned int Loghelper::levels = Loghelper::Level::LV_ALL;
+std::ofstream Loghelper::fs;
+
+void Loghelper::log(Level _level, const char* _fmt, ...)
+{
+ if (!hasbit(levels, _level))
+ return;
+#define FORMAT_MSG_BUFFER_SIZE (204800)
+ char* levelStr = nullptr;
+ switch (_level)
+ {
+ case LV_ERROR:
+ levelStr = "[Jin Error]:";
+ break;
+ case LV_WARN:
+ levelStr = "[Jin Warn]:";
+ break;
+ case LV_INFO:
+ levelStr = "[Jin Info]:";
+ break;
+ case LV_DEBUG:
+ levelStr = "[Jin Debug]:";
+ break;
+ default:
+ levelStr = "[Jin Unknown]:";
+ break;
+ }
+ char buffer[FORMAT_MSG_BUFFER_SIZE + 1] = { 0 };
+ strcpy(buffer, levelStr);
+ va_list args;
+ va_start(args, _fmt);
+ vsnprintf(buffer + strlen(buffer), FORMAT_MSG_BUFFER_SIZE, _fmt, args);
+ va_end(args);
+ if (hasbit(dir, DIR_CERR))
+ {
+ std::cerr << buffer << std::endl;
+ }
+ if (hasbit(dir, DIR_FILE))
+ {
+ fs << buffer << std::endl;
+ }
+#undef FORMAT_MSG_BUFFER_SIZE
+}
+
+// ض
+void Loghelper::redirect(unsigned int _dir, char* _path)
+{
+ dir = _dir;
+ if (hasbit(dir, DIR_FILE))
+ {
+ try
+ {
+ fs.open(_path, std::ios_base::app);
+ }
+ catch (std::ios_base::failure& e) {
+ dir = DIR_CERR;
+ log(Level::LV_WARN, "ضlog· %s ʧ", _path);
+ }
+ }
+}
+
+// ɸѡȼ
+void Loghelper::restrict(unsigned int _levels)
+{
+ levels = _levels;
+}
+
+void Loghelper::close()
+{
+ if (!fs.fail())
+ fs.close();
+ fs.clear();
+}
+
+#undef hasbit
+
+#endif
+
+#endif