⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.cpp

📁 贡献一份commoncpp2,有兴趣的可以研究一下
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// Copyright (C) 1999-2005 Open Source Telecom Corporation.//  // This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// // As a special exception, you may use this file as part of a free software// library without restriction.  Specifically, if other files instantiate// templates or use macros or inline functions from this file, or you compile// this file and link it with other files to produce an executable, this// file does not by itself cause the resulting executable to be covered by// the GNU General Public License.  This exception does not however    // invalidate any other reasons why the executable file might be covered by// the GNU General Public License.    //// This exception applies only to the code released under the name GNU// Common C++.  If you copy code from other releases into a copy of GNU// Common C++, as the General Public License permits, the exception does// not apply to the code that you add in this way.  To avoid misleading// anyone as to the status of such modified files, you must delete// this exception notice from them.//// If you write modifications of your own for GNU Common C++, it is your choice// whether to permit this exception to apply to your modifications.// If you do not wish that, delete this exception notice.//#include <cc++/config.h>#include <cc++/export.h>#include <cc++/thread.h>#include <cc++/exception.h>#ifdef	__BORLANDC__#include <stdio.h>#else#include <cstdio>#endif#include "private.h"#ifdef CCXX_HAVE_NEW_INIT#include <new>#elseinline void* operator new(size_t s,void* p){ return p;}#endif#ifdef WIN32#include <process.h>#endif#ifdef	CCXX_NAMESPACESnamespace ost {#endif#ifdef	_THR_UNIXWARE#undef	_POSIX_THREAD_PRIORITY_SCHEDULING#define	sigwait(x, y) _thr_sigwait(x, y)#endif#ifdef  __linux__#define CCXX_SIG_THREAD_ALARM// NOTE: Comment this line to test Resume/Signal using one signal method#define CCXX_SIG_THREAD_STOPCONT#endif#ifndef WIN32typedef	void	*(*exec_t)(void *);typedef	RETSIGTYPE (*signalexec_t)(int);extern "C"{#ifndef CCXX_SIG_THREAD_STOPCONT#ifndef _THR_SUNOS5#ifndef HAVE_PTHREAD_SUSPENDstatic RETSIGTYPE ccxx_sigsuspend(int);#endif#endif#endifstatic void ccxx_exec_handler(Thread *th);static void ccxx_thread_cleanup(void* arg);static void ccxx_thread_destructor(void* arg);static void ccxx_sig_handler(int signo);}#endif // ndef WIN32#ifdef	CCXX_SIG_THREAD_CANCELextern "C" RETSIGTYPE _th_sigcancel(int sig){	pthread_exit(NULL);}#endif#ifdef WIN32typedef	unsigned (__stdcall *exec_t)(void *);#ifndef CCXX_NO_DLL# if defined(_MSC_VER) && !defined(_DLL)#  error This project cannot be compiled as a static library. Some implementation stuff require DLL# endif#endif // CCXX_NO_DLL#endif // WIN32/* * Start Suspend/Resume stuff */// method to suspend are// - system suspend/resume recursive// - system suspend/resume not recursive// - one signal only, not recursive#ifndef WIN32#define CCXX_SUSPEND_MODE_RECURSIVE 1#define CCXX_SUSPEND_MODE_NOT_RECURSIVE 2#define CCXX_SUSPEND_MODE_ONE_SIGNAL 3#define	CCXX_SUSPEND_MODE_MACH 4#if defined(_THR_MACH) && !defined(MACOSX)#define	CCXX_SUSPEND_MODE CCXX_SUSPEND_MODE_MACH#elif defined(HAVE_PTHREAD_SUSPEND)#define CCXX_SUSPEND_MODE CCXX_SUSPEND_MODE_NOT_RECURSIVEstatic inline void ccxx_resume(cctid_t tid) { pthread_continue(tid); }static inline void ccxx_suspend(cctid_t tid) { pthread_suspend(tid); }#else# if defined(_THR_SUNOS5) || defined(CCXX_SIG_THREAD_STOPCONT)#  define CCXX_SUSPEND_MODE CCXX_SUSPEND_MODE_NOT_RECURSIVE#  ifdef _THR_SUNOS5    static inline void ccxx_resume(cctid_t tid) { thr_continue((thread_t)tid); }    static inline void ccxx_suspend(cctid_t tid) { thr_suspend((thread_t)tid); }#  else#   define CCXX_SIG_THREAD_SUSPEND SIGSTOP#   define CCXX_SIG_THREAD_RESUME  SIGCONT    static inline void ccxx_resume(cctid_t tid) { 	    pthread_kill(tid, CCXX_SIG_THREAD_RESUME);     }    static inline void ccxx_suspend(cctid_t tid) { 	    pthread_kill(tid, CCXX_SIG_THREAD_SUSPEND);     }#  endif# else#  define CCXX_SUSPEND_MODE CCXX_SUSPEND_MODE_ONE_SIGNAL#  ifndef SIGUSR3#  ifdef  SIGWINCH#  define SIGUSR3 SIGWINCH#  else#  define SIGUSR3 SIGINT#  endif#  endif#  define CCXX_SIG_THREAD_SUSPEND SIGUSR3#  define CCXX_SIG_THREAD_RESUME SIGUSR3   static inline void ccxx_resume(cctid_t tid) { 	   pthread_kill(tid, CCXX_SIG_THREAD_RESUME);    }   static inline void ccxx_suspend(cctid_t tid) { 	   pthread_kill(tid, CCXX_SIG_THREAD_SUSPEND);    }# endif#endif#endif // ndef WIN32Thread::Cancel Thread::enterCancel(void){	Thread *th = getThread();	if(!th)		return cancelInitial;	Cancel old = th->_cancel;		if(old != cancelDisabled && old != cancelImmediate)	{		th->setCancel(cancelImmediate);#ifdef	WIN32		Thread::yield();#else		pthread_testcancel();#endif	}	return old;}void Thread::exitCancel(Cancel old){	Thread *th = getThread();	if(!th)		return;	if(old != th->_cancel)	{#ifndef	WIN32		pthread_testcancel();#endif		th->setCancel(old);	}}void Thread::suspend(void){	if(!priv)		return;#ifdef WIN32	if (!priv->_active || !priv->_suspendEnable)	{#ifdef	CCXX_EXCEPTIONS		if (Thread::getException() != throwNothing)			throw this;#endif		return;	}	SuspendThread(priv->_hThread);#else	if (!priv->_suspendEnable) return;#if CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_MACH	thread_suspend(priv->_mach);#endif#if CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_RECURSIVE	ccxx_suspend(priv->_tid);#endif#if (CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_NOT_RECURSIVE) \  || (CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_ONE_SIGNAL)	if (++priv->_suspendcount != 1) return;	ccxx_suspend(priv->_tid);#endif#endif // WIN32}#if defined(__FreeBSD__)#define	AUTOSTACK	0x10000#endif#if defined(MACOSX)#define	AUTOSTACK	0#endif#ifndef	AUTOSTACK#define	AUTOSTACK	0x100000#endifsize_t Thread::_autostack = AUTOSTACK;void Thread::resume(void){	if(!priv)		return;#ifdef WIN32	if (!priv->_active || !priv->_suspendEnable)	{#ifdef	CCXX_EXCEPTIONS		if (Thread::getException() != throwNothing)			throw this;#endif		return;	}	ResumeThread(priv->_hThread);#else	if (!priv->_suspendEnable) return;#if CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_MACH	thread_resume(priv->_mach);#endif#if CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_RECURSIVE	ccxx_resume(priv->_tid);#endif#if (CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_NOT_RECURSIVE) \  || (CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_ONE_SIGNAL)	int c;	if ( (c = --priv->_suspendcount) > 0) return;	if ( c < 0 ) 	{		++priv->_suspendcount;		return;	}	ccxx_resume(priv->_tid);#endif#endif // WIN32}void Thread::join(void){	bool detached = isDetached();	joinSem.wait();	if(detached)	{		joinSem.post();		return;	}#ifdef	WIN32		// wait for real w32 thread to cleanup	if(priv->_hThread)	{		WaitForSingleObject(priv->_hThread, INFINITE);		::CloseHandle(priv->_hThread);		priv->_hThread = NULL;	}		#else			// make sure we cleanup exiting thread	if(priv->_jtid)	{		pthread_join(priv->_jtid, NULL);	}	priv->_jtid = 0;#endif	joinSem.post();	// enable next waiting thread after cleanup}#ifndef WIN32#if CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_ONE_SIGNAL// NOTE: Do not modify _suspendcount here, one program can call// Suspend 2 or more time but this function can be called only onceinline RETSIGTYPE ThreadImpl::ThreadSigSuspend(int){	sigset_t sigs;	sigemptyset(&sigs);	sigaddset(&sigs, SIGUSR3);	while ( (getThread()->priv->_suspendcount) > 0)	{#ifdef	HAVE_SIGWAIT2		int signo;		sigwait(&sigs, &signo);#else		sigwait(&sigs);#endif	}}static RETSIGTYPE ccxx_sigsuspend(int signo){	return ThreadImpl::ThreadSigSuspend(signo);}#endifvoid	Thread::setSuspend(Suspend mode){	if(!priv)		return;	priv->_suspendEnable = (mode == suspendEnable);#ifndef	HAVE_PTHREAD_SUSPEND#ifdef  CCXX_SIG_THREAD_SUSPEND	sigset_t mask;	sigemptyset(&mask);	sigaddset(&mask, CCXX_SIG_THREAD_SUSPEND);	switch(mode)	{	case suspendEnable:		pthread_sigmask(SIG_UNBLOCK, &mask, NULL);		return;	case suspendDisable:		pthread_sigmask(SIG_BLOCK, &mask, NULL);	}#endif#endif}/* * End Suspend/Resume stuff */static	sigset_t *blocked_signals(sigset_t *sig){	sigemptyset(sig);	sigaddset(sig, SIGINT);	sigaddset(sig, SIGKILL);	sigaddset(sig, SIGHUP);	sigaddset(sig, SIGABRT);	sigaddset(sig, SIGALRM);	sigaddset(sig, SIGPIPE);#if CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_ONE_SIGNAL	sigaddset(sig, SIGUSR3);#endif	return sig;}#endif // ndef WIN32typedef enum ThreadType { 	threadTypeNormal=0, 	threadTypeMain, 	threadTypePosix,	threadTypeDummy} ThreadType;class MainThread : public Thread{protected:	void run(void) {return;};#ifndef WIN32	void onSignal(int signo) { std::exit(signo);};#endifpublic:	MainThread() : Thread(true) {};};// mantain info on thread creationclass DummyThread : public Thread{protected:	void run() {};public:	DummyThread() : Thread(false) { priv->_type = threadTypeDummy; }#ifdef WIN32	static void CheckDelete();#endif};#ifdef WIN32static ThreadKey _self;#else// NOTE: _self instantiation MUST appear before _mainthread !!ThreadKey ThreadImpl::_self(ccxx_thread_destructor);#endif#ifdef WIN32void DummyThread::CheckDelete(){	Thread *th = (Thread*)_self.getKey();	if (!th) return;	// delete if dummy thread	if (th->priv->_type == threadTypeDummy)		delete th;}#endifstatic	MainThread _mainthread;Thread	*Thread::_main = NULL;// invalid pointer to thread used to test deleted thread// point in the middle of mainthread...#define DUMMY_INVALID_THREAD ((Thread*)(((char*)((Thread*)&_mainthread))+1))#if !defined(WIN32)#ifndef	CCXX_SIG_THREAD_ALARMPosixThread *PosixThread::_timer = NULL;Mutex	PosixThread::_arm;#endif#endif//void PosixThread::sigInstall(int);Thread::Thread(bool isMain):_cancel(cancelDefault), _start(NULL), priv(new ThreadImpl(threadTypeDummy)){#ifdef WIN32	priv->_tid = GetCurrentThreadId();	// FIXME: error handling	HANDLE process = GetCurrentProcess();	DuplicateHandle(process,GetCurrentThread(),process,&priv->_hThread,0,FALSE,DUPLICATE_SAME_ACCESS);	_parent = this;	priv->_cancellation = CreateEvent(NULL, TRUE, FALSE, NULL);		if(isMain)	{		setName("main()");		priv->_type   = threadTypeMain;		_main = this;	}	else		setName("-dummy-");	_self.setKey(this);#else	priv->_suspendEnable = false;	priv->_tid = pthread_self();	_parent = NULL;	struct sigaction act;		// NOTE: for race condition (signal handler can use getThread)	// you should initialize _main and _self before registering signals	ThreadImpl::_self.setKey(this);	if(isMain == true)	{		_main = this;		priv->_type = threadTypeMain;#if !defined(__CYGWIN32__) && !defined(__MINGW32__)		PosixThread::sigInstall(SIGHUP);		PosixThread::sigInstall(SIGALRM);		PosixThread::sigInstall(SIGPIPE);		PosixThread::sigInstall(SIGABRT);		memset(&act, sizeof(act), 0);		act.sa_handler = (signalexec_t)&ccxx_sig_handler;		sigemptyset(&act.sa_mask);# ifdef	SA_RESTART		act.sa_flags = SA_RESTART;# else		act.sa_flags = 0;# endif# ifdef	SA_INTERRUPT		act.sa_flags |= SA_INTERRUPT;# endif# ifdef	SIGPOLL		sigaction(SIGPOLL, &act, NULL);# else		sigaction(SIGIO, &act, NULL);# endif		# if CCXX_SUSPEND_MODE == CCXX_SUSPEND_MODE_ONE_SIGNAL		act.sa_handler = ccxx_sigsuspend;		sigemptyset(&act.sa_mask);#  ifdef	SA_RESTART		act.sa_flags = SA_RESTART;#  else		act.sa_flags = 0;#  endif		sigaction(SIGUSR3, &act, NULL);# endif# ifdef	CCXX_SIG_THREAD_CANCEL		memset(&act, sizeof(act), 0);		act.sa_flags = 0;		act.sa_handler = _th_sigcancel;		sigemptyset(&act.sa_mask);		sigaddset(&act.sa_mask, SIGHUP);		sigaddset(&act.sa_mask, SIGALRM);		sigaddset(&act.sa_mask, SIGPIPE);		sigaction(CCXX_SIG_THREAD_CANCEL, &act, NULL);# endif#endif    	}#endif // WIN32}	Thread::Thread(int pri, size_t stack):_cancel(cancelDefault), _start(NULL), priv(new ThreadImpl(threadTypeNormal)){#ifdef WIN32	if(!_main)	{		_self.setKey(NULL);		_main = this;		setName("main()");	}	else#ifdef	WIN32		_name[0] = 0;#else		snprintf(_name, sizeof(_name), "%d", getId());#endif	_parent = Thread::get();	if(_parent)		priv->_throw = _parent->priv->_throw;	else		_parent = this;		priv->_cancellation = CreateEvent(NULL, TRUE, FALSE, NULL);	if(!priv->_cancellation)		THROW(this);	if(stack <= _autostack)		priv->_stack = 0;	else		priv->_stack = stack;	if(pri > 2)		pri = 2;	if(pri < -2)		pri = -2;	switch(pri)	{	case 1:		priv->_priority = THREAD_PRIORITY_ABOVE_NORMAL;		break;	case -1:		priv->_priority = THREAD_PRIORITY_BELOW_NORMAL;		break;	case 2:		priv->_priority = THREAD_PRIORITY_HIGHEST;		break;	case -2:		priv->_priority = THREAD_PRIORITY_LOWEST;		break;	default:		priv->_priority = THREAD_PRIORITY_NORMAL;	}#else	int	salign;	pthread_attr_init(&priv->_attr);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -