diff options
author | chai <chaifix@163.com> | 2018-08-07 23:29:28 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2018-08-07 23:29:28 +0800 |
commit | f5e30a91cfe12118d2c5d389687ebb931a196c7c (patch) | |
tree | 8d410f5c4fcf421d18ef0c95dd4b6a8b3e247a46 | |
parent | 2576caf003fdb3162ab8a3c7bf77c38a885c3858 (diff) |
*update
-rw-r--r-- | bin/jin.exe | bin | 817664 -> 817664 bytes | |||
-rw-r--r-- | build/vs2015/jin.rc | bin | 3268 -> 3330 bytes | |||
-rw-r--r-- | build/vs2015/jin.vcxproj | 2 | ||||
-rw-r--r-- | build/vs2015/jin.vcxproj.filters | 2 | ||||
-rw-r--r-- | res/icon.ico | bin | 0 -> 16958 bytes | |||
-rw-r--r-- | res/icon.png | bin | 0 -> 40629 bytes | |||
-rw-r--r-- | src/icon.ico | bin | 16958 -> 0 bytes | |||
-rw-r--r-- | src/icon.jpg | bin | 88290 -> 0 bytes | |||
-rw-r--r-- | src/libjin/Thread/thread.cpp | 309 | ||||
-rw-r--r-- | src/libjin/Thread/thread.h | 165 | ||||
-rw-r--r-- | src/libjin/Utils/log.h | 134 |
11 files changed, 610 insertions, 2 deletions
diff --git a/bin/jin.exe b/bin/jin.exe Binary files differindex 6aacb12..5605a29 100644 --- a/bin/jin.exe +++ b/bin/jin.exe diff --git a/build/vs2015/jin.rc b/build/vs2015/jin.rc Binary files differindex da0fb26..01bf177 100644 --- a/build/vs2015/jin.rc +++ b/build/vs2015/jin.rc 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 Binary files differnew file mode 100644 index 0000000..9c0209f --- /dev/null +++ b/res/icon.ico diff --git a/res/icon.png b/res/icon.png Binary files differnew file mode 100644 index 0000000..58bc2fa --- /dev/null +++ b/res/icon.png diff --git a/src/icon.ico b/src/icon.ico Binary files differdeleted file mode 100644 index 2cc6f15..0000000 --- a/src/icon.ico +++ /dev/null diff --git a/src/icon.jpg b/src/icon.jpg Binary files differdeleted file mode 100644 index fee2575..0000000 --- a/src/icon.jpg +++ /dev/null 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 |