diff options
| author | chai <chaifix@163.com> | 2020-02-11 11:29:07 +0800 | 
|---|---|---|
| committer | chai <chaifix@163.com> | 2020-02-11 11:29:07 +0800 | 
| commit | 160e1299ef3d95f8e8c48706d7f61dd3dc6c6b60 (patch) | |
| tree | abe5ae5242d9cc6caf6edf103e662c44e978fca0 /src/libjin/threads | |
| parent | e095043485d1d298571af6d9eca7f0db9009ea7a (diff) | |
Diffstat (limited to 'src/libjin/threads')
| -rw-r--r-- | src/libjin/threads/thread.cpp | 582 | ||||
| -rw-r--r-- | src/libjin/threads/thread.h | 276 | 
2 files changed, 429 insertions, 429 deletions
| diff --git a/src/libjin/threads/thread.cpp b/src/libjin/threads/thread.cpp index 1c35efb..0dfa53b 100644 --- a/src/libjin/threads/thread.cpp +++ b/src/libjin/threads/thread.cpp @@ -5,297 +5,297 @@  namespace JinEngine  { -    namespace Threads -    { - -        class Mutex -        { -        public: -            Mutex(); -            ~Mutex(); - -            void lock(); -            void unlock(); -        private: -        #if jin_thread == 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 == 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 == jin_thread_sdl -            mutex = SDL_CreateMutex(); -        #endif -        } - -        Mutex::~Mutex() -        { -        #if jin_thread == jin_thread_sdl -            SDL_DestroyMutex(mutex); -        #endif -        } - -        void Mutex::lock() -        { -        #if jin_thread == jin_thread_sdl -            SDL_LockMutex(mutex); -        #endif -        } - -        void Mutex::unlock() -        { -        #if jin_thread == jin_thread_sdl -            SDL_UnlockMutex(mutex); -        #endif -        } - -        ////////////////////////////////////////////////////////////////////// - -        Conditional::Conditional() -        { -        #if jin_thread == jin_thread_sdl -            cond = SDL_CreateCond(); -        #endif -        } - -        Conditional::~Conditional() -        { -        #if jin_thread == jin_thread_sdl -            SDL_DestroyCond(cond); -        #endif -        } - -        void Conditional::signal() -        { -        #if jin_thread == jin_thread_sdl -            SDL_CondSignal(cond); -        #endif -        } - -        void Conditional::broadcast() -        { -        #if jin_thread == jin_thread_sdl -            SDL_CondBroadcast(cond); -        #endif -        } - -        bool Conditional::wait(Mutex* mutex, int timeout) -        { -        #if jin_thread == 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); -            } -        } - -        ////////////////////////////////////////////////////////////////////// - -        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 == 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(void* p) -        { -            Lock l(mutex); -            if (running)  -                return false; -            if (handle) -            { -            #if jin_thread == jin_thread_sdl -                SDL_WaitThread(handle, nullptr); -            #endif -            } -        #if jin_thread == jin_thread_sdl -            handle = SDL_CreateThread(threadRunner, name.c_str(), p); -        #elif jin_thread == jin_thread_cpp -            handle = new std::thread(); -        #endif  -            return (running = (handle != nullptr)); -        } - -        void Thread::wait() -        { -            { -                Lock l(mutex); -                if (!handle) -                    return; -            } -        #if jin_thread == 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, const 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(); -        } - -    } // namespace Threads +	namespace Threads +	{ + +		class Mutex +		{ +		public: +			Mutex(); +			~Mutex(); + +			void lock(); +			void unlock(); +		private: +		#if jin_thread == 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 == 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 == jin_thread_sdl +			mutex = SDL_CreateMutex(); +		#endif +		} + +		Mutex::~Mutex() +		{ +		#if jin_thread == jin_thread_sdl +			SDL_DestroyMutex(mutex); +		#endif +		} + +		void Mutex::lock() +		{ +		#if jin_thread == jin_thread_sdl +			SDL_LockMutex(mutex); +		#endif +		} + +		void Mutex::unlock() +		{ +		#if jin_thread == jin_thread_sdl +			SDL_UnlockMutex(mutex); +		#endif +		} + +		////////////////////////////////////////////////////////////////////// + +		Conditional::Conditional() +		{ +		#if jin_thread == jin_thread_sdl +			cond = SDL_CreateCond(); +		#endif +		} + +		Conditional::~Conditional() +		{ +		#if jin_thread == jin_thread_sdl +			SDL_DestroyCond(cond); +		#endif +		} + +		void Conditional::signal() +		{ +		#if jin_thread == jin_thread_sdl +			SDL_CondSignal(cond); +		#endif +		} + +		void Conditional::broadcast() +		{ +		#if jin_thread == jin_thread_sdl +			SDL_CondBroadcast(cond); +		#endif +		} + +		bool Conditional::wait(Mutex* mutex, int timeout) +		{ +		#if jin_thread == 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); +			} +		} + +		////////////////////////////////////////////////////////////////////// + +		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 == 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(void* p) +		{ +			Lock l(mutex); +			if (running)  +				return false; +			if (handle) +			{ +			#if jin_thread == jin_thread_sdl +				SDL_WaitThread(handle, nullptr); +			#endif +			} +		#if jin_thread == jin_thread_sdl +			handle = SDL_CreateThread(threadRunner, name.c_str(), p); +		#elif jin_thread == jin_thread_cpp +			handle = new std::thread(); +		#endif  +			return (running = (handle != nullptr)); +		} + +		void Thread::wait() +		{ +			{ +				Lock l(mutex); +				if (!handle) +					return; +			} +		#if jin_thread == 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, const 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(); +		} + +	} // namespace Threads  } // namespace JinEngine  #endif // defined(jin_thread)
\ No newline at end of file diff --git a/src/libjin/threads/thread.h b/src/libjin/threads/thread.h index 2b7ee35..6319e38 100644 --- a/src/libjin/threads/thread.h +++ b/src/libjin/threads/thread.h @@ -6,160 +6,160 @@  #include <string>  #include <map>  #if jin_thread == jin_thread_sdl  -    #include "SDL2/SDL_thread.h" +	#include "SDL2/SDL_thread.h"  #elif jin_thread == jin_thread_cpp  -    #include <thread> -    #include <mutex> -    #include <condition_variable> +	#include <thread> +	#include <mutex> +	#include <condition_variable>  #endif  namespace JinEngine  { -    namespace Threads -    { -        /** -         * ӢӢMutual exclusionд Mutexһڶ̱߳Уֹ߳ͬʱͬһԴ -         * ȫֱждĻơĿͨƬһһٽcritical sectionɡٽ -         * ָһԹԴзʵĴ룬һֻƻ㷨һ̡߳̿ӵжٽDz -         * һӦûҪ˻ƵԴУꡢСжϴڶеĴ -         * ݡͬ״̬ȵԴάЩԴͬһºǺѵģΪһ߳̿κһʱ̱ͣ -         * ߣָѣ -         */ -        class Mutex; -        class Conditional; +	namespace Threads +	{ +		/** +		 * ӢӢ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) {}; -            }; +		// +		// 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: -                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: +			class ThreadData +			{ +			public: +				static const int SLOT_ERROR = -1; +				static const int SLOT_WARN = -2; +				static const int SLOT_INFO = -3; +				static const int SLOT_DEBUG = -4; -                ThreadData(Mutex*, Conditional*); -                ~ThreadData(); -                bool exist(int slot); -                void set(int slot, Variant value); -                Variant get(int slot); -                void remove(int slot); +				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; +				Conditional* condition; +				Mutex* mutex; -            private: -                std::map<int, Variant> share; // threads shared value +			private: +				std::map<int, Variant> share; // threads shared value -            }; +			}; -        public: -            typedef int(*ThreadRunner)(void* obj); +		public: +			typedef int(*ThreadRunner)(void* obj); -            Thread(const std::string name, ThreadRunner threadfuncs); -            ~Thread(); -            bool start(void* p); -            void wait(); -            void send(int slot, const 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(); +			Thread(const std::string name, ThreadRunner threadfuncs); +			~Thread(); +			bool start(void* p); +			void wait(); +			void send(int slot, const 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(); -        protected: -        #if jin_thread == jin_thread_sdl  -            SDL_Thread* handle;         // SDL thread -        #elif jin_thread == 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 +		protected: +		#if jin_thread == jin_thread_sdl  +			SDL_Thread* handle;		 // SDL thread +		#elif jin_thread == 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 -        }; +		}; -    } // namespace Threads +	} // namespace Threads  } // namespace JinEngine  #endif // defined(jin_thread) | 
