added some threading functions
This commit is contained in:
		| @ -54,7 +54,8 @@ lib_LTLIBRARIES += libqsesixx.la | ||||
| libqsesixx_la_SOURCES = \ | ||||
| 	AppRoot.cpp \ | ||||
| 	SocketAddress.cpp \ | ||||
| 	Socket.cpp | ||||
| 	Socket.cpp \ | ||||
| 	Thread.cpp | ||||
| libqsesixx_la_LDFLAGS = -L. -L../cmn -version-info 1:0:0 -no-undefined | ||||
| libqsesixx_la_LIBADD = -lqsecmnxx -lqsecmn  | ||||
| endif | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| # Makefile.in generated by automake 1.14.1 from Makefile.am. | ||||
| # Makefile.in generated by automake 1.15 from Makefile.am. | ||||
| # @configure_input@ | ||||
|  | ||||
| # Copyright (C) 1994-2013 Free Software Foundation, Inc. | ||||
| # Copyright (C) 1994-2014 Free Software Foundation, Inc. | ||||
|  | ||||
| # This Makefile.in is free software; the Free Software Foundation | ||||
| # gives unlimited permission to copy and/or distribute it, | ||||
| @ -16,7 +16,17 @@ | ||||
|  | ||||
|  | ||||
| VPATH = @srcdir@ | ||||
| am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' | ||||
| am__is_gnu_make = { \ | ||||
|   if test -z '$(MAKELEVEL)'; then \ | ||||
|     false; \ | ||||
|   elif test -n '$(MAKE_HOST)'; then \ | ||||
|     true; \ | ||||
|   elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ | ||||
|     true; \ | ||||
|   else \ | ||||
|     false; \ | ||||
|   fi; \ | ||||
| } | ||||
| am__make_running_with_option = \ | ||||
|   case $${target_option-} in \ | ||||
|       ?) ;; \ | ||||
| @ -81,20 +91,19 @@ build_triplet = @build@ | ||||
| host_triplet = @host@ | ||||
| @ENABLE_CXX_TRUE@am__append_1 = libqsesixx.la | ||||
| subdir = lib/si | ||||
| DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ | ||||
| 	$(top_srcdir)/ac/depcomp $(noinst_HEADERS) | ||||
| ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 | ||||
| am__aclocal_m4_deps = $(top_srcdir)/m4/argz.m4 \ | ||||
| 	$(top_srcdir)/m4/ax_check_sign.m4 \ | ||||
| am__aclocal_m4_deps = $(top_srcdir)/m4/ax_check_sign.m4 \ | ||||
| 	$(top_srcdir)/m4/ax_cxx_namespace.m4 \ | ||||
| 	$(top_srcdir)/m4/ax_lib_mysql.m4 $(top_srcdir)/m4/ax_numval.m4 \ | ||||
| 	$(top_srcdir)/m4/ax_pthread.m4 $(top_srcdir)/m4/libtool.m4 \ | ||||
| 	$(top_srcdir)/m4/ltdl.m4 $(top_srcdir)/m4/ltoptions.m4 \ | ||||
| 	$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ | ||||
| 	$(top_srcdir)/m4/lt~obsolete.m4 \ | ||||
| 	$(top_srcdir)/m4/ltargz.m4 $(top_srcdir)/m4/ltdl.m4 \ | ||||
| 	$(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ | ||||
| 	$(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ | ||||
| 	$(top_srcdir)/m4/lx_find_mpi.m4 $(top_srcdir)/configure.ac | ||||
| am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ | ||||
| 	$(ACLOCAL_M4) | ||||
| DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ | ||||
| 	$(am__DIST_COMMON) | ||||
| mkinstalldirs = $(install_sh) -d | ||||
| CONFIG_HEADER = $(top_builddir)/include/qse/config.h | ||||
| CONFIG_CLEAN_FILES = | ||||
| @ -153,9 +162,9 @@ libqsesi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | ||||
| 	$(CFLAGS) $(libqsesi_la_LDFLAGS) $(LDFLAGS) -o $@ | ||||
| libqsesixx_la_DEPENDENCIES = | ||||
| am__libqsesixx_la_SOURCES_DIST = AppRoot.cpp SocketAddress.cpp \ | ||||
| 	Socket.cpp | ||||
| 	Socket.cpp Thread.cpp | ||||
| @ENABLE_CXX_TRUE@am_libqsesixx_la_OBJECTS = AppRoot.lo \ | ||||
| @ENABLE_CXX_TRUE@	SocketAddress.lo Socket.lo | ||||
| @ENABLE_CXX_TRUE@	SocketAddress.lo Socket.lo Thread.lo | ||||
| libqsesixx_la_OBJECTS = $(am_libqsesixx_la_OBJECTS) | ||||
| libqsesixx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ | ||||
| 	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ | ||||
| @ -242,12 +251,12 @@ am__define_uniq_tagged_files = \ | ||||
|   done | $(am__uniquify_input)` | ||||
| ETAGS = etags | ||||
| CTAGS = ctags | ||||
| am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/ac/depcomp | ||||
| DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) | ||||
| ACLOCAL = @ACLOCAL@ | ||||
| AMTAR = @AMTAR@ | ||||
| AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ | ||||
| AR = @AR@ | ||||
| ARGZ_H = @ARGZ_H@ | ||||
| AUTOCONF = @AUTOCONF@ | ||||
| AUTOHEADER = @AUTOHEADER@ | ||||
| AUTOMAKE = @AUTOMAKE@ | ||||
| @ -302,9 +311,11 @@ LTDLDEPS = @LTDLDEPS@ | ||||
| LTDLINCL = @LTDLINCL@ | ||||
| LTDLOPEN = @LTDLOPEN@ | ||||
| LTLIBOBJS = @LTLIBOBJS@ | ||||
| LT_ARGZ_H = @LT_ARGZ_H@ | ||||
| LT_CONFIG_H = @LT_CONFIG_H@ | ||||
| LT_DLLOADERS = @LT_DLLOADERS@ | ||||
| LT_DLPREOPEN = @LT_DLPREOPEN@ | ||||
| LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ | ||||
| MAKEINFO = @MAKEINFO@ | ||||
| MANIFEST_TOOL = @MANIFEST_TOOL@ | ||||
| MKDIR_P = @MKDIR_P@ | ||||
| @ -474,7 +485,8 @@ libqsesi_la_LIBADD = -lqsecmn $(PTHREAD_LIBS) $(SSL_LIBS) | ||||
| @ENABLE_CXX_TRUE@libqsesixx_la_SOURCES = \ | ||||
| @ENABLE_CXX_TRUE@	AppRoot.cpp \ | ||||
| @ENABLE_CXX_TRUE@	SocketAddress.cpp \ | ||||
| @ENABLE_CXX_TRUE@	Socket.cpp | ||||
| @ENABLE_CXX_TRUE@	Socket.cpp \ | ||||
| @ENABLE_CXX_TRUE@	Thread.cpp | ||||
|  | ||||
| @ENABLE_CXX_TRUE@libqsesixx_la_LDFLAGS = -L. -L../cmn -version-info 1:0:0 -no-undefined | ||||
| @ENABLE_CXX_TRUE@libqsesixx_la_LIBADD = -lqsecmnxx -lqsecmn  | ||||
| @ -494,7 +506,6 @@ $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps) | ||||
| 	echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/si/Makefile'; \ | ||||
| 	$(am__cd) $(top_srcdir) && \ | ||||
| 	  $(AUTOMAKE) --foreign lib/si/Makefile | ||||
| .PRECIOUS: Makefile | ||||
| Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status | ||||
| 	@case '$?' in \ | ||||
| 	  *config.status*) \ | ||||
| @ -563,6 +574,7 @@ distclean-compile: | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AppRoot.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Socket.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Thread.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-pro.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-sck.Plo@am__quote@ | ||||
| @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libqsesi_la-aio-tmr.Plo@am__quote@ | ||||
| @ -1074,6 +1086,8 @@ uninstall-am: uninstall-libLTLIBRARIES | ||||
| 	mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ | ||||
| 	tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES | ||||
|  | ||||
| .PRECIOUS: Makefile | ||||
|  | ||||
|  | ||||
| # Tell versions [3.59,3.63) of GNU make to not export all variables. | ||||
| # Otherwise a system limit (for SysV at least) may be exceeded. | ||||
|  | ||||
| @ -39,9 +39,11 @@ | ||||
| QSE_BEGIN_NAMESPACE(QSE) | ||||
| ///////////////////////////////// | ||||
|  | ||||
| Socket::Socket () QSE_CPP_NOEXCEPT: handle(QSE_INVALID_SCKHND), errcode(E_NOERR) | ||||
| #include "../cmn/syserr.h" | ||||
| IMPLEMENT_SYSERR_TO_ERRNUM (Socket::ErrorCode, Socket::ErrorCode::) | ||||
|  | ||||
| Socket::Socket () QSE_CPP_NOEXCEPT: handle(QSE_INVALID_SCKHND), errcode(E_ENOERR) | ||||
| { | ||||
| 	this->errmsg[0] = QSE_T('\0'); | ||||
| } | ||||
|  | ||||
| Socket::~Socket () QSE_CPP_NOEXCEPT | ||||
| @ -56,32 +58,6 @@ int Socket::fdopen (int handle) QSE_CPP_NOEXCEPT | ||||
| } | ||||
| #endif | ||||
|  | ||||
| void Socket::setError (ErrorCode error_code, const qse_char_t* fmt, ...) | ||||
| { | ||||
| 	static const qse_char_t* errstr[] =  | ||||
| 	{ | ||||
| 		QSE_T("no error"), | ||||
| 		QSE_T("insufficient memory"), | ||||
| 		QSE_T("invalid parameter"), | ||||
| 		QSE_T("in progress"), | ||||
| 		QSE_T("socket not open"), | ||||
| 		QSE_T("system error") | ||||
| 	}; | ||||
|  | ||||
| 	this->errcode = error_code; | ||||
| 	if (fmt) | ||||
| 	{ | ||||
| 		va_list ap; | ||||
| 		va_start (ap, fmt); | ||||
| 		qse_strxvfmt (this->errmsg, QSE_COUNTOF(errmsg), fmt, ap); | ||||
| 		va_end (ap); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		qse_strxcpy (this->errmsg, QSE_COUNTOF(errmsg), errstr[error_code]); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int Socket::open (int domain, int type, int protocol, int traits) QSE_CPP_NOEXCEPT | ||||
| { | ||||
| 	int x; | ||||
| @ -104,7 +80,7 @@ open_socket: | ||||
| 			goto open_socket; | ||||
| 		} | ||||
| 	#endif | ||||
| 		this->set_error_with_syserr (errno); | ||||
| 		this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @ -121,7 +97,7 @@ open_socket: | ||||
| 		if (fl == -1) | ||||
| 		{ | ||||
| 		fcntl_failure: | ||||
| 			this->set_error_with_syserr (errno); | ||||
| 			this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 			::close (x); | ||||
| 			x = -1; | ||||
| 		} | ||||
| @ -151,7 +127,7 @@ int Socket::connect (const SocketAddress& target) QSE_CPP_NOEXCEPT | ||||
|  | ||||
| 	if (::connect(this->handle, (struct sockaddr*)target.getAddrPtr(), target.getAddrSize()) == -1) | ||||
| 	{ | ||||
| 		this->set_error_with_syserr (errno); | ||||
| 		this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @ -164,7 +140,20 @@ int Socket::bind (const SocketAddress& target) QSE_CPP_NOEXCEPT | ||||
|  | ||||
| 	if (::bind(this->handle, (struct sockaddr*)target.getAddrPtr(), target.getAddrSize()) == -1) | ||||
| 	{ | ||||
| 		this->set_error_with_syserr (errno); | ||||
| 		this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int Socket::listen (int backlog) QSE_CPP_NOEXCEPT | ||||
| { | ||||
| 	QSE_ASSERT (this->handle != QSE_INVALID_SCKHND); | ||||
|  | ||||
| 	if (::listen(this->handle, backlog) == -1) | ||||
| 	{ | ||||
| 		this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @ -173,21 +162,65 @@ int Socket::bind (const SocketAddress& target) QSE_CPP_NOEXCEPT | ||||
|  | ||||
| int Socket::accept (Socket* newsck, SocketAddress* newaddr, int traits) QSE_CPP_NOEXCEPT | ||||
| { | ||||
| 	int n; | ||||
| 	int newfd, flag_v; | ||||
| 	qse_sklen_t addrlen; | ||||
|  | ||||
| 	QSE_ASSERT (this->handle != QSE_INVALID_SCKHND); | ||||
|  | ||||
| #if 0 | ||||
| 	qse_socklen_t len = newaddr->getAddrSize(); | ||||
| #if defined(SOCK_NONBLOCK) && defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4) | ||||
|  | ||||
| 	if ((n = ::accept4 (this->handle, newaddr->getAddrPtr(), &len)) == -1) | ||||
| 	flag_v = 0; | ||||
| 	if (traits & T_NONBLOCK ) flag_v |= SOCK_NONBLOCK; | ||||
| 	if (traits & T_CLOEXEC) flag_v |= SOCK_CLOEXEC; | ||||
|  | ||||
| 	addrlen = newaddr->getAddrCapa(); | ||||
| 	newfd = ::accept4(this->handle, (struct sockaddr*)newaddr->getAddrPtr(), &addrlen, flag_v); | ||||
| 	if (newfd == -1) | ||||
| 	{ | ||||
| 		this->set_error_with_syserr (errno); | ||||
| 		if (errno != ENOSYS) | ||||
| 		{ | ||||
| 			this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 			return -1; | ||||
| 		} | ||||
|  | ||||
| 		// go on for the normal 3-parameter accept | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		goto accept_done; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	addrlen = newaddr->getAddrCapa(); | ||||
| 	newfd = ::accept(this->handle, (struct sockaddr*)newaddr->getAddrPtr(), &addrlen); | ||||
| 	if (newfd == -1) | ||||
| 	{ | ||||
| 		this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	newsck->handle = n; | ||||
| #endif | ||||
| 	flag_v = 0; | ||||
| 	if (traits & T_NONBLOCK ) flag_v |= O_NONBLOCK; | ||||
| 	if (traits & T_CLOEXEC) flag_v |= O_CLOEXEC; | ||||
|  | ||||
| 	if (flag_v) | ||||
| 	{ | ||||
| 		int fl = ::fcntl(newfd, F_GETFL, 0); | ||||
| 		if (fl == -1) | ||||
| 		{ | ||||
| 		fcntl_failure: | ||||
| 			this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 			::close (newfd); | ||||
| 			return -1; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if (::fcntl(newfd, F_SETFL, fl | flag_v) == -1) goto fcntl_failure; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| accept_done: | ||||
| 	newsck->handle = newfd; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -198,7 +231,7 @@ qse_ssize_t Socket::send (const void* buf, qse_size_t len) QSE_CPP_NOEXCEPT | ||||
| 	qse_ssize_t n = ::send(this->handle, buf, len, 0); | ||||
| 	if (n == -1) | ||||
| 	{ | ||||
| 		this->set_error_with_syserr (errno); | ||||
| 		this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @ -212,7 +245,7 @@ qse_ssize_t Socket::send (const void* buf, qse_size_t len, const SocketAddress& | ||||
| 	qse_ssize_t n = ::sendto(this->handle, buf, len, 0, (struct sockaddr*)dstaddr.getAddrPtr(), dstaddr.getAddrSize()); | ||||
| 	if (n == -1) | ||||
| 	{ | ||||
| 		this->set_error_with_syserr (errno); | ||||
| 		this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @ -226,7 +259,7 @@ qse_ssize_t Socket::receive (void* buf, qse_size_t len) QSE_CPP_NOEXCEPT | ||||
| 	qse_ssize_t n = ::recv(this->handle, buf, len, 0); | ||||
| 	if (n == -1) | ||||
| 	{ | ||||
| 		this->set_error_with_syserr (errno); | ||||
| 		this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @ -241,45 +274,13 @@ qse_ssize_t Socket::receive (void* buf, qse_size_t len, SocketAddress& srcaddr) | ||||
| 	qse_ssize_t n = ::recvfrom(this->handle, buf, len, 0, (struct sockaddr*)srcaddr.getAddrPtr(), &addrlen); | ||||
| 	if (n == -1) | ||||
| 	{ | ||||
| 		this->set_error_with_syserr (errno); | ||||
| 		this->setErrorCode (syserr_to_errnum(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	return n;  | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| void Socket::set_error_with_syserr (int syserr) | ||||
| { | ||||
| 	qse_mchar_t buf[128]; | ||||
| 	ErrorCode errcode; | ||||
|  | ||||
| 	switch (errno) | ||||
| 	{ | ||||
| 		case EINVAL: | ||||
| 			errcode = this->E_INVAL; | ||||
| 			break; | ||||
|  | ||||
| 		case ENOMEM: | ||||
| 			errcode = this->E_NOMEM; | ||||
| 			break; | ||||
|  | ||||
| 		case EINPROGRESS: | ||||
| 			errcode = this->E_INPROG; | ||||
| 			break; | ||||
|  | ||||
| // TODO: translate more system error codes | ||||
|  | ||||
| 		default: | ||||
| 			strerror_r(errno, buf, QSE_COUNTOF(buf)); | ||||
| 			this->setError (this->E_SYSERR, QSE_T("%hs"), buf); | ||||
| 			return; | ||||
| 	} | ||||
|  | ||||
| 	this->setError (errcode); | ||||
| } | ||||
|  | ||||
| ///////////////////////////////// | ||||
| QSE_END_NAMESPACE(QSE) | ||||
| ///////////////////////////////// | ||||
|  | ||||
							
								
								
									
										73
									
								
								qse/lib/si/Thread.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								qse/lib/si/Thread.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,73 @@ | ||||
| /* | ||||
|  * $Id$ | ||||
|  * | ||||
|     Copyright (c) 2006-2014 Chung, Hyung-Hwan. All rights reserved. | ||||
|  | ||||
|     Redistribution and use in source and binary forms, with or without | ||||
|     modification, are permitted provided that the following conditions | ||||
|     are met: | ||||
|     1. Redistributions of source code must retain the above copyright | ||||
|        notice, this list of conditions and the following disclaimer. | ||||
|     2. Redistributions in binary form must reproduce the above copyright | ||||
|        notice, this list of conditions and the following disclaimer in the | ||||
|        documentation and/or other materials provided with the distribution. | ||||
|  | ||||
|     THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EQSERESS OR | ||||
|     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||||
|     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||||
|     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||||
|     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||||
|     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
|     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
|     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
|     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #include <qse/si/Thread.hpp> | ||||
| #include "thr-prv.h" | ||||
|  | ||||
| #include <stdio.h> | ||||
| QSE_BEGIN_NAMESPACE(QSE) | ||||
|  | ||||
|  | ||||
| Thread::Handle Thread::INVALID_HANDLE = QSE_THR_HND_INVALID; | ||||
|  | ||||
| Thread::Thread() QSE_CPP_NOEXCEPT //: thread_target (QSE_NULL) | ||||
| { | ||||
| 	//qse_thr_init (this, this->getMmgr()); | ||||
| 	qse_thr_init (this, QSE_NULL); | ||||
| } | ||||
|  | ||||
| Thread::~Thread () QSE_CPP_NOEXCEPT | ||||
| { | ||||
| 	QSE_ASSERT (this->__state != Thread::RUNNING); | ||||
| 	// it is subclasses' responsibility to stop the thread gracefully. | ||||
| 	// so stop is not called here. | ||||
| 	// this->stop (); | ||||
|  | ||||
| 	/*if (this->__joinable)*/ this->join (); | ||||
| 	qse_thr_fini (this); | ||||
| } | ||||
|  | ||||
| int thr_func (qse_thr_t* thr) | ||||
| { | ||||
| 	Thread* t = (Thread*)thr; | ||||
| 	return t->main (); | ||||
| } | ||||
|  | ||||
| int Thread::start (int flags) QSE_CPP_NOEXCEPT | ||||
| { | ||||
| 	return qse_thr_start(this, thr_func, flags); | ||||
| } | ||||
|  | ||||
| int Thread::stop () QSE_CPP_NOEXCEPT | ||||
| { | ||||
| 	// NOTICE: | ||||
| 	// make sure that subclasses override "stop" and call it | ||||
| 	// properly so that the thread can be terminated gracefully. | ||||
| 	// "stop" here just aborts the running thread. | ||||
| 	return qse_thr_stop(this); | ||||
| } | ||||
|  | ||||
| QSE_END_NAMESPACE(QSE) | ||||
| @ -24,6 +24,9 @@ | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #ifndef _QSE_LIB_SI_FS_PRV_H_ | ||||
| #define _QSE_LIB_SI_FS_PRV_H_ | ||||
|  | ||||
| #include <qse/si/fs.h> | ||||
| #include <qse/si/glob.h> | ||||
| #include <qse/si/dir.h> | ||||
| @ -199,10 +202,12 @@ int qse_fs_invokeactcb ( | ||||
| 	qse_fs_action_t action, | ||||
| 	qse_fs_char_t*  src_fspath, | ||||
| 	qse_fs_char_t*  dst_fspath, | ||||
| 	qse_uintmax_t bytes_total, | ||||
| 	qse_uintmax_t bytes_done | ||||
| 	qse_uintmax_t   bytes_total, | ||||
| 	qse_uintmax_t   bytes_done | ||||
| ); | ||||
|  | ||||
| #if defined(__cplusplus) | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif | ||||
|  | ||||
| @ -24,14 +24,14 @@ | ||||
|     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
|  */ | ||||
|  | ||||
| #ifndef _QSE_LIB_CMN_THR_H_ | ||||
| #define _QSE_LIB_CMN_THR_H_ | ||||
| #ifndef _QSE_LIB_SI_THR_PRV_H_ | ||||
| #define _QSE_LIB_SI_THR_PRV_H_ | ||||
|  | ||||
| #include <qse/si/thr.h> | ||||
|  | ||||
|  | ||||
| #if (!defined(__unix__) && !defined(__unix)) || defined(HAVE_PTHREAD) | ||||
|  | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| #	include <windows.h> | ||||
| #	include <process.h> | ||||
| @ -63,20 +63,6 @@ | ||||
| #	define QSE_THR_HND_INVALID 0 | ||||
| #endif | ||||
|  | ||||
| struct qse_thr_t | ||||
| { | ||||
| 	qse_mmgr_t*       mmgr; | ||||
|  | ||||
| 	qse_thr_routine_t __main_routine; | ||||
| 	qse_thr_routine_t __temp_routine; | ||||
| 	qse_bool_t        __joinable; | ||||
| 	qse_size_t        __stacksize; | ||||
|  | ||||
| 	qse_thr_hnd_t     __handle; | ||||
| 	qse_thr_state_t   __state; | ||||
|  | ||||
| 	int               __return_code; | ||||
| }; | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @ -32,14 +32,14 @@ | ||||
|  | ||||
| #if (!defined(__unix__) && !defined(__unix)) || defined(HAVE_PTHREAD) | ||||
|  | ||||
| qse_thr_t* qse_thr_open (qse_mmgr_t* mmgr, qse_size_t xtnsize, qse_thr_routine_t routine) | ||||
| qse_thr_t* qse_thr_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) | ||||
| { | ||||
| 	qse_thr_t* thr; | ||||
|  | ||||
| 	thr = (qse_thr_t*) QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_thr_t) + xtnsize); | ||||
| 	if (thr) | ||||
| 	{ | ||||
| 		if (qse_thr_init (thr, mmgr, routine) <= -1) | ||||
| 		if (qse_thr_init (thr, mmgr) <= -1) | ||||
| 		{ | ||||
| 			QSE_MMGR_FREE (mmgr, thr); | ||||
| 			return QSE_NULL; | ||||
| @ -56,7 +56,7 @@ void qse_thr_close (qse_thr_t* thr) | ||||
| 	QSE_MMGR_FREE (thr->mmgr, thr); | ||||
| } | ||||
|  | ||||
| int qse_thr_init (qse_thr_t* thr, qse_mmgr_t* mmgr, qse_thr_routine_t routine) | ||||
| int qse_thr_init (qse_thr_t* thr, qse_mmgr_t* mmgr) | ||||
| { | ||||
| 	QSE_MEMSET (thr, 0, QSE_SIZEOF(*thr)); | ||||
|  | ||||
| @ -64,8 +64,8 @@ int qse_thr_init (qse_thr_t* thr, qse_mmgr_t* mmgr, qse_thr_routine_t routine) | ||||
| 	thr->__handle = QSE_THR_HND_INVALID; | ||||
| 	thr->__state = QSE_THR_INCUBATING; | ||||
| 	thr->__return_code = 0; | ||||
| 	thr->__main_routine = routine; | ||||
| 	thr->__joinable = 1; | ||||
| 	thr->__main_routine = QSE_NULL; | ||||
| 	thr->__flags = 0; | ||||
| 	thr->__stacksize = 0; | ||||
|  | ||||
| 	return 0; | ||||
| @ -109,20 +109,25 @@ static void* __thread_main (void* arg) | ||||
| { | ||||
| 	qse_thr_t* thr = (qse_thr_t*)arg; | ||||
|  | ||||
| 	if (thr->__flags & QSE_THR_SIGNALS_BLOCKED)  | ||||
| 		qse_thr_blockallsigs (thr); | ||||
| 	else | ||||
| 		qse_thr_unblockallsigs (thr); | ||||
| 	 | ||||
| 	while (thr->__state != QSE_THR_RUNNING)  | ||||
| 	{ | ||||
| #if defined(_WIN32) | ||||
| 	#if defined(_WIN32) | ||||
| 		Sleep (0); | ||||
| #elif defined(__OS2__) | ||||
| 	#elif defined(__OS2__) | ||||
| 		DosSleep (0); | ||||
| #elif defined(HAVE_NANOSLEEP) | ||||
| 	#elif defined(HAVE_NANOSLEEP) | ||||
| 		struct timespec ts; | ||||
| 		ts.tv_sec = 0; | ||||
| 		ts.tv_nsec = 0; | ||||
| 		nanosleep (&ts, &ts); | ||||
| #else | ||||
| 	#else | ||||
| 		sleep (0); | ||||
| #endif | ||||
| 	#endif | ||||
| 	} | ||||
|  | ||||
| #if defined(HAVE_PTHREAD) | ||||
| @ -134,7 +139,7 @@ static void* __thread_main (void* arg) | ||||
| 	pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, QSE_NULL); | ||||
| #endif | ||||
|  | ||||
| 	thr->__return_code = thr->__temp_routine? thr->__temp_routine(thr): thr->__main_routine(thr); | ||||
| 	thr->__return_code = thr->__main_routine(thr); | ||||
| 	thr->__state = QSE_THR_TERMINATED; | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| @ -195,8 +200,7 @@ static int __create_thread (qse_thr_t* thr) | ||||
| 	pthread_attr_t attr; | ||||
| 	pthread_attr_init (&attr); | ||||
|  | ||||
| 	if (pthread_attr_setdetachstate (&attr, (thr->__joinable?  | ||||
| 		PTHREAD_CREATE_JOINABLE: PTHREAD_CREATE_DETACHED)) != 0)  | ||||
| 	if (pthread_attr_setdetachstate(&attr, ((thr->__flags & QSE_THR_DETACHED)? PTHREAD_CREATE_DETACHED: PTHREAD_CREATE_JOINABLE)) != 0)  | ||||
| 	{ | ||||
| 		pthread_attr_destroy (&attr); | ||||
| 		return -1; | ||||
| @ -226,32 +230,25 @@ static int __cancel_thread (qse_thr_t* thr) | ||||
| { | ||||
| 	if (thr->__state != QSE_THR_RUNNING) return -1; | ||||
| #if defined(_WIN32) | ||||
| 	if (TerminateThread (thr->__handle, 0) == 0) return -1; | ||||
| 	if (TerminateThread(thr->__handle, 0) == 0) return -1; | ||||
| #elif defined(__OS2__) | ||||
| 	if (DosKillThread (thr->__handle) != NO_ERROR) return -1; | ||||
| 	if (DosKillThread(thr->__handle) != NO_ERROR) return -1; | ||||
| #elif defined(__DOS__) | ||||
| 	/* not implemented */ | ||||
| #elif defined(__BEOS__) | ||||
| 	if (kill_thread (thr->__handle) < B_OK) return -1; | ||||
| 	if (kill_thread(thr->__handle) < B_OK) return -1; | ||||
| #elif defined(HAVE_PTHREAD) | ||||
| 	if (pthread_cancel (thr->__handle) != 0) return -1; | ||||
| 	if (pthread_cancel(thr->__handle) != 0) return -1; | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int qse_thr_start (qse_thr_t* thr, int flags, ...) | ||||
| int qse_thr_start (qse_thr_t* thr, qse_thr_rtn_t func, int flags) | ||||
| { | ||||
| 	if (thr->__state == QSE_THR_RUNNING) return -1; | ||||
|  | ||||
| 	thr->__joinable = ((flags & QSE_THR_DETACHED) == 0); | ||||
| 	if (flags & QSE_THR_NEW_ROUTINE)  | ||||
| 	{ | ||||
| 		va_list va; | ||||
| 		va_start (va, flags); | ||||
| 		thr->__temp_routine = va_arg (va, qse_thr_routine_t); | ||||
| 		va_end (va); | ||||
| 	} | ||||
| 	else thr->__temp_routine = QSE_NULL; | ||||
| 	thr->__flags = flags; | ||||
| 	thr->__main_routine = func; | ||||
|  | ||||
| 	if (__create_thread(thr) == -1)  | ||||
| 	{ | ||||
| @ -280,7 +277,7 @@ int qse_thr_stop (qse_thr_t* thr) | ||||
| int qse_thr_join (qse_thr_t* thr) | ||||
| { | ||||
| 	if (thr->__state == QSE_THR_INCUBATING) return -1; | ||||
| 	if (!thr->__joinable) return -1; | ||||
| 	if (thr->__flags & QSE_THR_DETACHED) return -1; | ||||
|  | ||||
| #if defined(_WIN32) | ||||
| 	if (thr->__state == QSE_THR_RUNNING)  | ||||
| @ -301,20 +298,20 @@ int qse_thr_join (qse_thr_t* thr) | ||||
| 	if (pthread_join(thr->__handle, QSE_NULL) != 0) return -1; | ||||
| #endif | ||||
|  | ||||
| 	thr->__joinable = 0; | ||||
| 	thr->__flags |= QSE_THR_DETACHED; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| int qse_thr_detach (qse_thr_t* thr) | ||||
| { | ||||
| 	if (thr->__state == QSE_THR_INCUBATING) return -1; | ||||
| 	if (!thr->__joinable) return -1; | ||||
| 	if (thr->__flags & QSE_THR_DETACHED) return -1; | ||||
|  | ||||
| #if defined(HAVE_PTHREAD) | ||||
| 	if (pthread_detach(thr->__handle) != 0) return -1; | ||||
| #endif | ||||
|  | ||||
| 	thr->__joinable = 0; | ||||
| 	thr->__flags |= QSE_THR_DETACHED; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -325,7 +322,7 @@ int qse_thr_kill (qse_thr_t* thr, int sig) | ||||
| 	if (thr->__state != QSE_THR_RUNNING) return -1; | ||||
|  | ||||
| #if defined(HAVE_PTHREAD) | ||||
| 	if (pthread_kill (thr->__handle, sig) != 0) return -1; | ||||
| 	if (pthread_kill(thr->__handle, sig) != 0) return -1; | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
| @ -341,7 +338,7 @@ int qse_thr_blocksig (qse_thr_t* thr, int sig) | ||||
| #if defined(HAVE_PTHREAD) | ||||
| 	sigemptyset (&mask); | ||||
| 	sigaddset (&mask, sig); | ||||
| 	if (pthread_sigmask (SIG_BLOCK, &mask, QSE_NULL) != 0) return -1; | ||||
| 	if (pthread_sigmask(SIG_BLOCK, &mask, QSE_NULL) != 0) return -1; | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
| @ -357,7 +354,7 @@ int qse_thr_unblocksig (qse_thr_t* thr, int sig) | ||||
| #if defined(HAVE_PTHREAD) | ||||
| 	sigemptyset (&mask); | ||||
| 	sigaddset (&mask, sig); | ||||
| 	if (pthread_sigmask (SIG_UNBLOCK, &mask, QSE_NULL) != 0) return -1; | ||||
| 	if (pthread_sigmask(SIG_UNBLOCK, &mask, QSE_NULL) != 0) return -1; | ||||
| #endif | ||||
| 	return 0; | ||||
| } | ||||
| @ -392,6 +389,7 @@ int qse_thr_unblockallsigs (qse_thr_t* thr) | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| qse_thr_hnd_t qse_thr_gethnd (qse_thr_t* thr) | ||||
| { | ||||
| 	return thr->__handle; | ||||
| @ -407,7 +405,7 @@ qse_thr_state_t qse_thr_getstate (qse_thr_t* thr) | ||||
| 	return thr->__state; | ||||
| } | ||||
|  | ||||
| qse_thr_hnd_t qse_getcurthrhnd (void) | ||||
| qse_thr_hnd_t qse_get_thr_hnd (void) | ||||
| { | ||||
| #if defined(_WIN32) | ||||
| 	return GetCurrentThread (); | ||||
| @ -423,7 +421,7 @@ qse_thr_hnd_t qse_getcurthrhnd (void) | ||||
| #elif defined(__BEOS__) | ||||
| 	return QSE_THR_HND_INVALID; /* TODO: implement this */ | ||||
| #else | ||||
| 	return pthread_self (); | ||||
| 	return pthread_self(); | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user