diff --git a/qse/configure b/qse/configure index 0f2c2003..80f7c0d3 100755 --- a/qse/configure +++ b/qse/configure @@ -21425,6 +21425,82 @@ $as_echo "#define QSE_SOCKLEN_T_IS_SIGNED 1" >>confdefs.h fi +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of pthread_t" >&5 +$as_echo_n "checking size of pthread_t... " >&6; } +if ${ac_cv_sizeof_pthread_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (pthread_t))" "ac_cv_sizeof_pthread_t" "#include +"; then : + +else + if test "$ac_cv_type_pthread_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (pthread_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_pthread_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_pthread_t" >&5 +$as_echo "$ac_cv_sizeof_pthread_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_PTHREAD_T $ac_cv_sizeof_pthread_t +_ACEOF + + +if test ${ac_cv_sizeof_pthread_t} -gt 0 +then + + typename=`echo pthread_t | sed "s/[^a-zA-Z0-9_]/_/g"` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_t is signed" >&5 +$as_echo_n "checking whether pthread_t is signed... " >&6; } +if eval \${ax_cv_decl_${typename}_signed+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ + int foo [ 1 - 2 * !(((pthread_t) -1) < 0) ] + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "ax_cv_decl_${typename}_signed=\"yes\"" +else + eval "ax_cv_decl_${typename}_signed=\"no\"" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$ax_cv_decl_${typename}_signed + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + symbolname=`echo pthread_t | sed "s/[^a-zA-Z0-9_]/_/g" | tr "a-z" "A-Z"` + if eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"yes\""; then + +$as_echo "#define QSE_PTHREAD_T_IS_SIGNED 1" >>confdefs.h + + elif eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"no\""; then + $as_echo_n "" + fi + +fi + if test ${ac_cv_sizeof___int128_t} -gt 0 then { $as_echo "$as_me:${as_lineno-$LINENO}: checking __int128_t with %" >&5 @@ -21748,6 +21824,11 @@ cat >>confdefs.h <<_ACEOF _ACEOF +cat >>confdefs.h <<_ACEOF +#define QSE_SIZEOF_PTHREAD_T ${ac_cv_sizeof_pthread_t} +_ACEOF + + qse_package_version_major="`echo ${PACKAGE_VERSION} | cut -d. -f1`" qse_package_version_minor="`echo ${PACKAGE_VERSION} | cut -d. -f2`" diff --git a/qse/configure.ac b/qse/configure.ac index b3c97894..eff23c91 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -446,6 +446,15 @@ else fi +AC_CHECK_SIZEOF(pthread_t,, [#include ]) +if test ${ac_cv_sizeof_pthread_t} -gt 0 +then + AX_CHECK_SIGN([pthread_t], + [ AC_DEFINE(QSE_PTHREAD_T_IS_SIGNED, 1, [Define if pthread_t is signed]) ], + [ AS_ECHO_N("") ], + [#include ]) +fi + dnl gcc 3.4.3 on opensolaris x86 gave this warning without -msse or dnl something similar. dnl SSE vector argument without SSE enabled changes the ABI @@ -575,6 +584,7 @@ AC_DEFINE_UNQUOTED(QSE_SIZEOF_STRUCT_SOCKADDR_IN, ${ac_cv_sizeof_struct_sockaddr AC_DEFINE_UNQUOTED(QSE_SIZEOF_STRUCT_SOCKADDR_IN6, ${ac_cv_sizeof_struct_sockaddr_in6}, [sizeof(struct sockaddr_in6)]) AC_DEFINE_UNQUOTED(QSE_SIZEOF_STRUCT_SOCKADDR_UN, ${ac_cv_sizeof_struct_sockaddr_un}, [sizeof(struct sockaddr_un)]) AC_DEFINE_UNQUOTED(QSE_SIZEOF_SOCKLEN_T, ${ac_cv_sizeof_socklen_t}, [sizeof(socklen_t)]) +AC_DEFINE_UNQUOTED(QSE_SIZEOF_PTHREAD_T, ${ac_cv_sizeof_pthread_t}, [sizeof(pthread_t)]) qse_package_version_major="`echo ${PACKAGE_VERSION} | cut -d. -f1`" diff --git a/qse/include/qse/cmn/sck.h b/qse/include/qse/cmn/sck.h index 1c4b522a..c375880f 100644 --- a/qse/include/qse/cmn/sck.h +++ b/qse/include/qse/cmn/sck.h @@ -93,4 +93,4 @@ QSE_EXPORT void qse_shutsckhnd ( #endif - + diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index 01ca02aa..22a4d51c 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -1094,6 +1094,18 @@ QSE_EXPORT qse_size_t qse_mbsxjoin ( ... ); +QSE_EXPORT qse_size_t qse_mbsjoinv ( + qse_mchar_t* buf, + va_list ap +); + +QSE_EXPORT qse_size_t qse_mbsxjoinv ( + qse_mchar_t* buf, + qse_size_t size, + va_list ap +); + + /* * The qse_wcsjoin() function joins a list of wide-charcter strings into * a buffer. The list of strings is terminated by QSE_NULL. @@ -1116,17 +1128,28 @@ QSE_EXPORT qse_size_t qse_wcsxjoin ( ... ); -QSE_EXPORT qse_size_t qse_strjoin ( - qse_char_t* buf, - ... +QSE_EXPORT qse_size_t qse_wcsjoinv ( + qse_wchar_t* buf, + va_list ap ); -QSE_EXPORT qse_size_t qse_strxjoin ( - qse_char_t* buf, - qse_size_t size, - ... +QSE_EXPORT qse_size_t qse_wcsxjoinv ( + qse_wchar_t* buf, + qse_size_t size, + va_list ap ); +#if defined(QSE_CHAR_IS_MCHAR) +# define qse_strjoin qse_mbsjoin +# define qse_strxjoin qse_mbsxjoin +# define qse_strjoinv(buf,ap) qse_mbsjoinv(buf,ap) +# define qse_strxjoinv(buf,size,ap) qse_mbsxjoinv(buf,size,ap) +#else +# define qse_strjoin qse_wcsjoin +# define qse_strxjoin qse_wcsxjoin +# define qse_strjoinv(buf,ap) qse_wcsjoinv(buf,ap) +# define qse_strxjoinv(buf,size,ap) qse_wcsxjoinv(buf,size,ap) +#endif /* ---------------------------------------------------- */ diff --git a/qse/include/qse/config.h.in b/qse/include/qse/config.h.in index 4173eeb8..93c09946 100644 --- a/qse/include/qse/config.h.in +++ b/qse/include/qse/config.h.in @@ -892,6 +892,9 @@ /* Patch level */ #undef QSE_PACKAGE_VERSION_PATCH +/* Define if pthread_t is signed */ +#undef QSE_PTHREAD_T_IS_SIGNED + /* sizeof(char) */ #undef QSE_SIZEOF_CHAR @@ -922,6 +925,9 @@ /* sizeof(off_t) */ #undef QSE_SIZEOF_OFF_T +/* sizeof(pthread_t) */ +#undef QSE_SIZEOF_PTHREAD_T + /* sizeof(short) */ #undef QSE_SIZEOF_SHORT @@ -1006,6 +1012,9 @@ /* The size of `off_t', as computed by sizeof. */ #undef SIZEOF_OFF_T +/* The size of `pthread_t', as computed by sizeof. */ +#undef SIZEOF_PTHREAD_T + /* The size of `short', as computed by sizeof. */ #undef SIZEOF_SHORT diff --git a/qse/include/qse/sys/Makefile.am b/qse/include/qse/sys/Makefile.am index 3e442dba..98704c00 100644 --- a/qse/include/qse/sys/Makefile.am +++ b/qse/include/qse/sys/Makefile.am @@ -1,6 +1,7 @@ pkgincludedir = $(includedir)/qse/sys -pkginclude_HEADERS = +pkginclude_HEADERS = \ + thr.h if ENABLE_CXX pkginclude_HEADERS += \ diff --git a/qse/include/qse/sys/Makefile.in b/qse/include/qse/sys/Makefile.in index 93bf80b7..2b33c910 100644 --- a/qse/include/qse/sys/Makefile.in +++ b/qse/include/qse/sys/Makefile.in @@ -117,7 +117,7 @@ am__can_run_installinfo = \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac -am__pkginclude_HEADERS_DIST = SocketAddress.hpp +am__pkginclude_HEADERS_DIST = thr.h SocketAddress.hpp am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -343,7 +343,7 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -pkginclude_HEADERS = $(am__append_1) +pkginclude_HEADERS = thr.h $(am__append_1) all: all-am .SUFFIXES: diff --git a/qse/include/qse/sys/SocketAddress.hpp b/qse/include/qse/sys/SocketAddress.hpp index cb637d68..fd12089b 100644 --- a/qse/include/qse/sys/SocketAddress.hpp +++ b/qse/include/qse/sys/SocketAddress.hpp @@ -36,22 +36,38 @@ QSE_BEGIN_NAMESPACE(QSE) class SocketAddress { public: - int getFamily () const; - void* getStorage (int* len); + SocketAddress (); + SocketAddress (int family); + SocketAddress (const qse_skad_t* skad); + SocketAddress (const qse_nwad_t* nwad); + SocketAddress (const struct sockaddr* ptr, int len); + + int getFamily () const; - int getStorageSize () const + qse_skad_t* getAddrPtr() + { + return &this->skad; + } + + const qse_skad_t* getAddrPtr() const + { + return &this->skad; + } + + int getAddrSize () const { return qse_skadsize(&this->skad); } void setIpaddr (const qse_ip4ad_t* ipaddr); void setIpaddr (const qse_ip6ad_t* ipaddr); + qse_uint16_t getPort() const; // in network-byte order void setPort (qse_uint16_t port); // in network-byte order - int set (const qse_skad_t* skad); - int set (const void* ptr, int len); + int set (const qse_skad_t* skad); int set (const qse_nwad_t* nwad); + int set (const struct sockaddr* ptr, int len); // treat ptr as a pointer to struct sockaddr protected: qse_skad_t skad; diff --git a/qse/include/qse/sys/thr.h b/qse/include/qse/sys/thr.h new file mode 100644 index 00000000..0a6f6d26 --- /dev/null +++ b/qse/include/qse/sys/thr.h @@ -0,0 +1,232 @@ +/* + * $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. + */ + +#ifndef _QSE_CMN_THR_H_ +#define _QSE_CMN_THR_H_ + +#include +#include + +/** + * The qse_thr_t type defines a thread object. + */ +typedef struct qse_thr_t qse_thr_t; + +/** + * The qse_thr_routine_t type defines a thread routine that can be passed to + * qse_thr_open() and qse_thr_start(). When it is executed, the pointer to the + * calling thread object is passed as its first argument. + */ +typedef int (*qse_thr_routine_t) (qse_thr_t*); + +enum qse_thr_state_t +{ + QSE_THR_INCUBATING, + QSE_THR_RUNNING, + QSE_THR_TERMINATED, + QSE_THR_ABORTED +}; +typedef enum qse_thr_state_t qse_thr_state_t; + +enum qse_thr_flag_t +{ + QSE_THR_DETACHED = (1 << 0), + QSE_THR_NEW_ROUTINE = (1 << 1) +}; +typedef enum qse_thr_flag_t qse_thr_flag_t; + +#if defined(_WIN32) + /* => typedef PVOID HANDLE; */ + typedef void* qse_thr_hnd_t; +#elif defined(__OS2__) + + /* not implemented */ +# error not implemented +#elif defined(__DOS__) + /* not implemented */ +# error not implemented +#elif defined(__BEOS__) + /*typedef thread_id qse_thr_hnd_t;*/ + typdef qse_int32_t qse_thr_hnd_t; +#else + #if (QSE_SIZEOF_PTHREAD_T == QSE_SIZEOF_INT) + #if defined(QSE_PTHREAD_T_IS_SIGNED) + typedef int qse_thr_hnd_t; + #else + typedef unsigned int qse_thr_hnd_t; + #endif + #elif (QSE_SIZEOF_PTHREAD_T == QSE_SIZEOF_LONG) + #if defined(QSE_PTHREAD_T_IS_SIGNED) + typedef long qse_thr_hnd_t; + #else + typedef unsigned long qse_thr_hnd_t; + #endif + #else + typedef int qse_thr_hnd_t; + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The qse_thr_open() function instantiates a thread object. The function + * pointed to by \a routine is executed when qse_thr_start() is called. + * + */ +qse_thr_t* qse_thr_open ( + qse_mmgr_t* mmgr, + qse_size_t xtnsize, + qse_thr_routine_t routine +); + +/** + * The qse_thr_close() function destroys a thread object. Make sure that the + * thread routine has been terminated properly. + */ +void qse_thr_close ( + qse_thr_t* thr +); + +int qse_thr_init ( + qse_thr_t* thr, + qse_mmgr_t* mmgr, + qse_thr_routine_t routine +); + +void qse_thr_fini ( + qse_thr_t* thr +); + +qse_size_t qse_thr_getstacksize ( + qse_thr_t* thr +); + +/** + * The qse_thr_setstacksize() function sets the stack size of a thread. + * It must be called before a thread routine gets started. + */ +void qse_thr_setstacksize ( + qse_thr_t* thr, + qse_size_t num +); + +/** + * The qse_thr_start() executes a thread routine in a new thread of control. + * A new temporary thread routine can be passed as the third argument to + * override the main thread routine for a single invocation if \a flags contains + * the #QSE_THR_NEW_ROUTINE bit. + * + * QSE_THR_DETACHED, when set in \a flags, puts the thread in a detached state. + * Otherwise, the thread is joinable. + * + * \return 0 on success, -1 on failure + */ +int qse_thr_start ( + qse_thr_t* thr, + int flags, /**< 0 or bitwise-or of QSE_THR_NEW_ROUTINE and QSE_THR_DETACHED */ + ... +); + +/** + * The qse_thr_stop() function aborts a thread. + * \return 0 on success, -1 on failure + */ +int qse_thr_stop (qse_thr_t* thr); + +/** + * The qse_thr_join() function waits for thread termination. + * \return 0 on success, -1 on failure + */ +int qse_thr_join (qse_thr_t* thr); + +/** + * The qse_thr_detach() function detaches a thread. + * \return 0 on success, -1 on failure + */ +int qse_thr_detach (qse_thr_t* thr); + +/** + * The qse_thr_kill() function sends a signal to a thread. + */ +int qse_thr_kill (qse_thr_t* thr, int sig); + +/** + * The qse_thr_blocksig() function causes a therad to block the signal \a sig. + */ +int qse_thr_blocksig (qse_thr_t* thr, int sig); + +/** + * The qse_thr_unblocksig() function causes a therad to unblock the signal \a sig. + */ +int qse_thr_unblocksig (qse_thr_t* thr, int sig); + +/** + * The qse_thr_blockallsigs() function causes a therad to block all signals. + */ +int qse_thr_blockallsigs (qse_thr_t* thr); + +/** + * The qse_thr_unblockallsigs() function causes a therad to unblock all signals. + */ +int qse_thr_unblockallsigs (qse_thr_t* thr); + + +/** + * The qse_thr_gethnd() function returns the native thread handle. + */ +qse_thr_hnd_t qse_thr_gethnd ( + qse_thr_t* thr +); + +/** + * The qse_thr_getretcode() returns the return code a thread rountine + * that has been terminated. If no thread routine has been started and + * terminated, 0 is returned. + */ +int qse_thr_getretcode ( + qse_thr_t* thr +); + +/** + * The qse_thr_state() function returns the current state. + */ +qse_thr_state_t qse_thr_getstate ( + qse_thr_t* thr +); + +/** + * The qse_getcurthrhnd() function returns the native handle to the + * calling thread. + */ +qse_thr_hnd_t qse_getcurthrhnd (void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/qse/lib/cmn/Makefile.am b/qse/lib/cmn/Makefile.am index dc8ab476..93398830 100644 --- a/qse/lib/cmn/Makefile.am +++ b/qse/lib/cmn/Makefile.am @@ -15,6 +15,7 @@ noinst_HEADERS = \ fs.h \ glob.h \ mem.h \ + str-cat.h \ str-dyn.h \ str-fcpy.h \ str-fmt.h \ diff --git a/qse/lib/cmn/Makefile.in b/qse/lib/cmn/Makefile.in index 43ad344d..6c1411ff 100644 --- a/qse/lib/cmn/Makefile.in +++ b/qse/lib/cmn/Makefile.in @@ -458,6 +458,7 @@ noinst_HEADERS = \ fs.h \ glob.h \ mem.h \ + str-cat.h \ str-dyn.h \ str-fcpy.h \ str-fmt.h \ diff --git a/qse/lib/cmn/str-cat.c b/qse/lib/cmn/str-cat.c index ad0deaad..5cc36fe1 100644 --- a/qse/lib/cmn/str-cat.c +++ b/qse/lib/cmn/str-cat.c @@ -26,162 +26,42 @@ #include -qse_size_t qse_mbscat (qse_mchar_t* buf, const qse_mchar_t* str) -{ - qse_mchar_t* org = buf; - buf += qse_mbslen(buf); - while ((*buf++ = *str++) != QSE_MT('\0')); - return buf - org - 1; -} +#undef T +#undef char_t +#undef strcat +#undef strncat +#undef strcatn +#undef strxcat +#undef strxncat +#undef strlen -qse_size_t qse_mbsncat (qse_mchar_t* buf, const qse_mchar_t* str, qse_size_t len) -{ - qse_size_t x; - const qse_mchar_t* end = str + len; +#define T(x) QSE_MT(x) +#define char_t qse_mchar_t +#define strcat qse_mbscat +#define strncat qse_mbsncat +#define strcatn qse_mbscatn +#define strxcat qse_mbsxcat +#define strxncat qse_mbsxncat +#define strlen qse_mbslen +#include "str-cat.h" - x = qse_mbslen(buf); buf += x; - while (str < end) *buf++ = *str++; - *buf = QSE_MT('\0'); - return len + x; -} +/* ----------------------------------- */ -qse_size_t qse_mbscatn (qse_mchar_t* buf, const qse_mchar_t* str, qse_size_t n) -{ - qse_size_t x; - qse_mchar_t* org = buf; - const qse_mchar_t* end = str + n; - - x = qse_mbslen(buf); buf += x; - while (str < end) - { - if ((*buf++ = *str++) == QSE_MT('\0')) return buf - org - 1; - } - return n + x; -} - - -qse_size_t qse_mbsxcat (qse_mchar_t* buf, qse_size_t bsz, const qse_mchar_t* str) -{ - qse_mchar_t* p, * p2; - qse_size_t blen; - - blen = qse_mbslen(buf); - if (blen >= bsz) return blen; /* something wrong */ - - p = buf + blen; - p2 = buf + bsz - 1; - - while (p < p2) - { - if (*str == QSE_MT('\0')) break; - *p++ = *str++; - } - - if (bsz > 0) *p = QSE_MT('\0'); - return p - buf; -} - -qse_size_t qse_mbsxncat ( - qse_mchar_t* buf, qse_size_t bsz, const qse_mchar_t* str, qse_size_t len) -{ - qse_mchar_t* p, * p2; - const qse_mchar_t* end; - qse_size_t blen; - - blen = qse_mbslen(buf); - if (blen >= bsz) return blen; /* something wrong */ - - p = buf + blen; - p2 = buf + bsz - 1; - - end = str + len; - - while (p < p2) - { - if (str >= end) break; - *p++ = *str++; - } - - if (bsz > 0) *p = QSE_MT('\0'); - return p - buf; -} - -qse_size_t qse_wcscat (qse_wchar_t* buf, const qse_wchar_t* str) -{ - qse_wchar_t* org = buf; - buf += qse_wcslen(buf); - while ((*buf++ = *str++) != QSE_WT('\0')); - return buf - org - 1; -} - -qse_size_t qse_wcsncat (qse_wchar_t* buf, const qse_wchar_t* str, qse_size_t len) -{ - qse_size_t x; - const qse_wchar_t* end = str + len; - - x = qse_wcslen(buf); buf += x; - while (str < end) *buf++ = *str++; - *buf = QSE_WT('\0'); - return len + x; -} - -qse_size_t qse_wcscatn (qse_wchar_t* buf, const qse_wchar_t* str, qse_size_t n) -{ - qse_size_t x; - qse_wchar_t* org = buf; - const qse_wchar_t* end = str + n; - - x = qse_wcslen(buf); buf += x; - while (str < end) - { - if ((*buf++ = *str++) == QSE_WT('\0')) return buf - org - 1; - } - return n + x; -} - -qse_size_t qse_wcsxcat (qse_wchar_t* buf, qse_size_t bsz, const qse_wchar_t* str) -{ - qse_wchar_t* p, * p2; - qse_size_t blen; - - blen = qse_wcslen(buf); - if (blen >= bsz) return blen; /* something wrong */ - - p = buf + blen; - p2 = buf + bsz - 1; - - while (p < p2) - { - if (*str == QSE_WT('\0')) break; - *p++ = *str++; - } - - if (bsz > 0) *p = QSE_WT('\0'); - return p - buf; -} - -qse_size_t qse_wcsxncat ( - qse_wchar_t* buf, qse_size_t bsz, const qse_wchar_t* str, qse_size_t len) -{ - qse_wchar_t* p, * p2; - const qse_wchar_t* end; - qse_size_t blen; - - blen = qse_wcslen(buf); - if (blen >= bsz) return blen; /* something wrong */ - - p = buf + blen; - p2 = buf + bsz - 1; - - end = str + len; - - while (p < p2) - { - if (str >= end) break; - *p++ = *str++; - } - - if (bsz > 0) *p = QSE_WT('\0'); - return p - buf; -} +#undef T +#undef char_t +#undef strcat +#undef strncat +#undef strcatn +#undef strxcat +#undef strxncat +#undef strlen +#define T(x) QSE_WT(x) +#define char_t qse_wchar_t +#define strcat qse_wcscat +#define strncat qse_wcsncat +#define strcatn qse_wcscatn +#define strxcat qse_wcsxcat +#define strxncat qse_wcsxncat +#define strlen qse_wcslen +#include "str-cat.h" diff --git a/qse/lib/cmn/str-cat.h b/qse/lib/cmn/str-cat.h new file mode 100644 index 00000000..90af9ac3 --- /dev/null +++ b/qse/lib/cmn/str-cat.h @@ -0,0 +1,109 @@ +/* + * $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 EXPRESS 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. + */ + +#if !defined(char_t) && !defined(strcat) && !defined(strxcat) +# error Never include this file +#endif + +qse_size_t strcat (char_t* buf, const char_t* str) +{ + char_t* org = buf; + buf += strlen(buf); + while ((*buf++ = *str++) != T('\0')); + return buf - org - 1; +} + +qse_size_t strncat (char_t* buf, const char_t* str, qse_size_t len) +{ + qse_size_t x; + const char_t* end = str + len; + + x = strlen(buf); buf += x; + while (str < end) *buf++ = *str++; + *buf = T('\0'); + return len + x; +} + +qse_size_t strcatn (char_t* buf, const char_t* str, qse_size_t n) +{ + qse_size_t x; + char_t* org = buf; + const char_t* end = str + n; + + x = strlen(buf); buf += x; + while (str < end) + { + /* copies not more than n characters and stop if '\0' is met */ + if ((*buf++ = *str++) == T('\0')) return buf - org - 1; + } + return n + x; +} + +qse_size_t strxcat (char_t* buf, qse_size_t bsz, const char_t* str) +{ + char_t* p, * p2; + qse_size_t blen; + + blen = strlen(buf); + if (blen >= bsz) return blen; /* something wrong */ + + p = buf + blen; + p2 = buf + bsz - 1; + + while (p < p2) + { + if (*str == T('\0')) break; + *p++ = *str++; + } + + if (bsz > 0) *p = T('\0'); + return p - buf; +} + +qse_size_t strxncat (char_t* buf, qse_size_t bsz, const char_t* str, qse_size_t len) +{ + char_t* p, * p2; + const char_t* end; + qse_size_t blen; + + blen = strlen(buf); + if (blen >= bsz) return blen; /* something wrong */ + + p = buf + blen; + p2 = buf + bsz - 1; + + end = str + len; + + while (p < p2) + { + if (str >= end) break; + *p++ = *str++; + } + + if (bsz > 0) *p = T('\0'); + return p - buf; +} + diff --git a/qse/lib/cmn/str-fcpy.h b/qse/lib/cmn/str-fcpy.h index a61b8b7c..dfab6cb2 100644 --- a/qse/lib/cmn/str-fcpy.h +++ b/qse/lib/cmn/str-fcpy.h @@ -24,8 +24,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -qse_size_t strfcpy ( - char_t* buf, const char_t* fmt, const char_t* str[]) +qse_size_t strfcpy (char_t* buf, const char_t* fmt, const char_t* str[]) { char_t* b = buf; const char_t* f = fmt; @@ -69,8 +68,7 @@ qse_size_t strfcpy ( return b - buf; } -qse_size_t strfncpy ( - char_t* buf, const char_t* fmt, const cstr_t str[]) +qse_size_t strfncpy (char_t* buf, const char_t* fmt, const cstr_t str[]) { char_t* b = buf; const char_t* f = fmt; @@ -123,9 +121,7 @@ qse_size_t strfncpy ( return b - buf; } -qse_size_t strxfcpy ( - char_t* buf, qse_size_t bsz, - const char_t* fmt, const char_t* str[]) +qse_size_t strxfcpy (char_t* buf, qse_size_t bsz, const char_t* fmt, const char_t* str[]) { char_t* b = buf; char_t* end = buf + bsz - 1; @@ -185,9 +181,7 @@ fini: return b - buf; } -qse_size_t strxfncpy ( - char_t* buf, qse_size_t bsz, - const char_t* fmt, const cstr_t str[]) +qse_size_t strxfncpy (char_t* buf, qse_size_t bsz, const char_t* fmt, const cstr_t str[]) { char_t* b = buf; char_t* end = buf + bsz - 1; diff --git a/qse/lib/cmn/str-join.c b/qse/lib/cmn/str-join.c index 16c1edad..ddbb7650 100644 --- a/qse/lib/cmn/str-join.c +++ b/qse/lib/cmn/str-join.c @@ -25,7 +25,6 @@ */ #include -#include /* ----------------------------------- */ @@ -64,20 +63,3 @@ #define strcpy qse_wcscpy #define strxcpy qse_wcsxcpy #include "str-join.h" - -#undef char_t -#undef strjoin -#undef strjoinv -#undef strxjoin -#undef strxjoinv -#undef strcpy -#undef strxcpy - -#define char_t qse_char_t -#define strjoin qse_strjoin -#define strjoinv qse_strjoinv -#define strxjoin qse_strxjoin -#define strxjoinv qse_strxjoinv -#define strcpy qse_strcpy -#define strxcpy qse_strxcpy -#include "str-join.h" diff --git a/qse/lib/cmn/str-join.h b/qse/lib/cmn/str-join.h index ea5028ea..54650f84 100644 --- a/qse/lib/cmn/str-join.h +++ b/qse/lib/cmn/str-join.h @@ -47,7 +47,6 @@ qse_size_t strxjoinv (char_t* buf, qse_size_t size, va_list ap) return size - left; } - qse_size_t strxjoin (char_t* buf, qse_size_t size, ...) { va_list ap; diff --git a/qse/lib/sys/Makefile.am b/qse/lib/sys/Makefile.am index 842df0b6..c6125562 100644 --- a/qse/lib/sys/Makefile.am +++ b/qse/lib/sys/Makefile.am @@ -4,11 +4,12 @@ AM_CPPFLAGS = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include -lib_LTLIBRARIES = -#lib_LTLIBRARIES = libqsesys.la -#libqsesys_la_SOURCES = -#libqsesys_la_LDFLAGS = -L../cmn -version-info 1:0:0 -no-undefined -#libqsesys_la_LIBADD = -lqsecmn +lib_LTLIBRARIES = libqsesys.la +libqsesys_la_SOURCES = \ + thr.c \ + thr.h +libqsesys_la_LDFLAGS = -L../cmn -version-info 1:0:0 -no-undefined +libqsesys_la_LIBADD = -lqsecmn if ENABLE_CXX lib_LTLIBRARIES += libqsesysxx.la diff --git a/qse/lib/sys/Makefile.in b/qse/lib/sys/Makefile.in index fe18e4f7..00751d8b 100644 --- a/qse/lib/sys/Makefile.in +++ b/qse/lib/sys/Makefile.in @@ -78,10 +78,6 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -#lib_LTLIBRARIES = libqsesys.la -#libqsesys_la_SOURCES = -#libqsesys_la_LDFLAGS = -L../cmn -version-info 1:0:0 -no-undefined -#libqsesys_la_LIBADD = -lqsecmn @ENABLE_CXX_TRUE@am__append_1 = libqsesysxx.la subdir = lib/sys DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ @@ -130,14 +126,20 @@ am__uninstall_files_from_dir = { \ } am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) -libqsesysxx_la_DEPENDENCIES = -am__libqsesysxx_la_SOURCES_DIST = SocketAddress.cpp -@ENABLE_CXX_TRUE@am_libqsesysxx_la_OBJECTS = SocketAddress.lo -libqsesysxx_la_OBJECTS = $(am_libqsesysxx_la_OBJECTS) +libqsesys_la_DEPENDENCIES = +am_libqsesys_la_OBJECTS = thr.lo +libqsesys_la_OBJECTS = $(am_libqsesys_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = +libqsesys_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libqsesys_la_LDFLAGS) $(LDFLAGS) -o $@ +libqsesysxx_la_DEPENDENCIES = +am__libqsesysxx_la_SOURCES_DIST = SocketAddress.cpp +@ENABLE_CXX_TRUE@am_libqsesysxx_la_OBJECTS = SocketAddress.lo +libqsesysxx_la_OBJECTS = $(am_libqsesysxx_la_OBJECTS) libqsesysxx_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ $(AM_CXXFLAGS) $(CXXFLAGS) $(libqsesysxx_la_LDFLAGS) \ @@ -159,6 +161,24 @@ DEFAULT_INCLUDES = depcomp = $(SHELL) $(top_srcdir)/ac/depcomp am__depfiles_maybe = depfiles am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ @@ -177,8 +197,9 @@ AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) am__v_CXXLD_0 = @echo " CXXLD " $@; am__v_CXXLD_1 = -SOURCES = $(libqsesysxx_la_SOURCES) -DIST_SOURCES = $(am__libqsesysxx_la_SOURCES_DIST) +SOURCES = $(libqsesys_la_SOURCES) $(libqsesysxx_la_SOURCES) +DIST_SOURCES = $(libqsesys_la_SOURCES) \ + $(am__libqsesysxx_la_SOURCES_DIST) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -384,7 +405,13 @@ AM_CPPFLAGS = \ -I$(top_builddir)/include \ -I$(top_srcdir)/include -lib_LTLIBRARIES = $(am__append_1) +lib_LTLIBRARIES = libqsesys.la $(am__append_1) +libqsesys_la_SOURCES = \ + thr.c \ + thr.h + +libqsesys_la_LDFLAGS = -L../cmn -version-info 1:0:0 -no-undefined +libqsesys_la_LIBADD = -lqsecmn @ENABLE_CXX_TRUE@libqsesysxx_la_SOURCES = \ @ENABLE_CXX_TRUE@ SocketAddress.cpp @@ -393,7 +420,7 @@ lib_LTLIBRARIES = $(am__append_1) all: all-am .SUFFIXES: -.SUFFIXES: .cpp .lo .o .obj +.SUFFIXES: .c .cpp .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -460,6 +487,9 @@ clean-libLTLIBRARIES: rm -f $${locs}; \ } +libqsesys.la: $(libqsesys_la_OBJECTS) $(libqsesys_la_DEPENDENCIES) $(EXTRA_libqsesys_la_DEPENDENCIES) + $(AM_V_CCLD)$(libqsesys_la_LINK) -rpath $(libdir) $(libqsesys_la_OBJECTS) $(libqsesys_la_LIBADD) $(LIBS) + libqsesysxx.la: $(libqsesysxx_la_OBJECTS) $(libqsesysxx_la_DEPENDENCIES) $(EXTRA_libqsesysxx_la_DEPENDENCIES) $(AM_V_CXXLD)$(libqsesysxx_la_LINK) $(am_libqsesysxx_la_rpath) $(libqsesysxx_la_OBJECTS) $(libqsesysxx_la_LIBADD) $(LIBS) @@ -470,6 +500,28 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thr.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< .cpp.o: @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/qse/lib/sys/SocketAddress.cpp b/qse/lib/sys/SocketAddress.cpp index 86a2b00e..f648e3ae 100644 --- a/qse/lib/sys/SocketAddress.cpp +++ b/qse/lib/sys/SocketAddress.cpp @@ -89,19 +89,42 @@ QSE_BEGIN_NAMESPACE(QSE) ///////////////////////////////// + +SocketAddress::SocketAddress () +{ + QSE_MEMSET (&this->skad, 0, QSE_SIZEOF(this->skad)); +} + +SocketAddress::SocketAddress (int family) +{ + QSE_MEMSET (&this->skad, 0, QSE_SIZEOF(this->skad)); + FAMILY(&this->skad) = family; +} + +SocketAddress::SocketAddress (const qse_skad_t* skad) +{ + this->set (skad); +} + +SocketAddress::SocketAddress (const qse_nwad_t* nwad) +{ + this->set (nwad); +} + +SocketAddress::SocketAddress (const struct sockaddr* ptr, int len) +{ + if (this->set (ptr, len) <= -1) + { + QSE_MEMSET (&this->skad, 0, QSE_SIZEOF(this->skad)); + } +} + int SocketAddress::getFamily () const { return FAMILY(&this->skad); //return qse_skadfamily (&this->skad); } -void* SocketAddress::getStorage (int* len) -{ - if (len) *len = qse_skadsize(&this->skad); - return (void*)&this->skad; -} - - void SocketAddress::setIpaddr (const qse_ip4ad_t* ipaddr) { #if defined(AF_INET) @@ -179,19 +202,19 @@ int SocketAddress::set (const qse_skad_t* skad) return 0; } -int SocketAddress::set (const void* ptr, int len) +int SocketAddress::set (const qse_nwad_t* nwad) +{ + return qse_nwadtoskad (nwad, &this->skad); +} + +int SocketAddress::set (const struct sockaddr* ptr, int len) { - if (len < QSE_SIZEOF(struct sockaddr)) return -1; int exp_size = qse_skadsize((const qse_skad_t*)ptr); if (len < exp_size) return -1; QSE_MEMCPY (&this->skad, ptr, exp_size); return 0; } -int SocketAddress::set (const qse_nwad_t* nwad) -{ - return qse_nwadtoskad (nwad, &this->skad); -} ///////////////////////////////// QSE_END_NAMESPACE(QSE) diff --git a/qse/lib/sys/thr.c b/qse/lib/sys/thr.c new file mode 100644 index 00000000..1d488e67 --- /dev/null +++ b/qse/lib/sys/thr.c @@ -0,0 +1,373 @@ +/* + * $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 EXPRESS 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 "thr.h" +#include "../cmn/mem.h" +#include + +#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* 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) + { + QSE_MMGR_FREE (mmgr, thr); + return QSE_NULL; + } + else QSE_MEMSET (QSE_XTN(thr), 0, xtnsize); + } + + return thr; +} + +void qse_thr_close (qse_thr_t* thr) +{ + qse_thr_fini (thr); + QSE_MMGR_FREE (thr->mmgr, thr); +} + +int qse_thr_init (qse_thr_t* thr, qse_mmgr_t* mmgr, qse_thr_routine_t routine) +{ + QSE_MEMSET (thr, 0, QSE_SIZEOF(*thr)); + + thr->mmgr = mmgr; + thr->__handle = QSE_THR_HND_INVALID; + thr->__state = QSE_THR_INCUBATING; + thr->__return_code = 0; + thr->__main_routine = routine; + thr->__joinable = 1; + thr->__stacksize = 0; + + return 0; +} + +void qse_thr_fini (qse_thr_t* thr) +{ +#if defined(_WIN32) + if (thr->__handle != QSE_THR_HND_INVALID) CloseHandle (thr->__handle); +#endif + thr->__handle = QSE_THR_HND_INVALID; +} + + +qse_size_t qse_thr_getstacksize (qse_thr_t* thr) +{ + return thr->__stacksize; +} + +void qse_thr_setstacksize (qse_thr_t* thr, qse_size_t num) +{ + thr->__stacksize = num; +} + +#if defined(__BEOS__) +static int32 __thread_main (void* arg) +#else +static void* __thread_main (void* arg) +#endif +{ + qse_thr_t* thr = (qse_thr_t*)arg; + + while (thr->__state != QSE_THR_RUNNING) + { +#if defined(_WIN32) + Sleep (0); +#elif defined(HAVE_NANOSLEEP) + struct timespec ts; + ts.tv_sec =0; + ts.tv_nsec = 0; + nanosleep (&ts, &ts); +#else + sleep (0); +#endif + } + +#if !defined(_WIN32) && !defined(__BEOS__) + /* + * the asynchronous cancel-type is used to better emulate + * the bad effect of WIN32's TerminateThread using pthread_cancel + */ + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, QSE_NULL); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, QSE_NULL); +#endif + + thr->__return_code = thr->__temp_routine? thr->__temp_routine(thr): thr->__main_routine(thr); + thr->__state = QSE_THR_TERMINATED; + +#if defined(_WIN32) + _endthreadex (thr->__return_code); + return QSE_NULL; +#elif defined(__BEOS__) + exit_thread (thr->__return_code); + return 0; +#else + pthread_exit (&thr->__return_code); + return QSE_NULL; +#endif +} + +static int __create_thread (qse_thr_t* thr) +{ +#if defined(_WIN32) + unsigned int tid; + + if (thr->__handle != QSE_THR_HND_INVALID) CloseHandle (thr->__handle); + + thr->__handle = (HANDLE)_beginthreadex (QSE_NULL, 0, (unsigned int (__stdcall*)(void*))__thread_main, thr, 0, &tid); + if (thr->__handle == 0) return -1; +#elif defined(__BEOS__) + thread_id tid; + + tid = spawn_thread ((thread_func)__thread_main, QSE_NULL, 120, thr); + if (tid < B_OK) return -1; + + thr->__handle = tid; + resume_thread(thr->__handle); +#elif defined(HAVE_PTHREAD) + pthread_attr_t attr; + pthread_attr_init (&attr); + + if (pthread_attr_setdetachstate (&attr, (thr->__joinable? + PTHREAD_CREATE_JOINABLE: PTHREAD_CREATE_DETACHED)) != 0) + { + pthread_attr_destroy (&attr); + return -1; + } + + if (thr->__stacksize > 0) + { + if (pthread_attr_setstacksize (&attr, thr->__stacksize) != 0) + { + pthread_attr_destroy (&attr); + return -1; + } + } + + if (pthread_create (&thr->__handle, &attr, __thread_main, thr) != 0) + { + pthread_attr_destroy (&attr); + return -1; + } + + pthread_attr_destroy (&attr); +#endif + return 0; +} + +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; +#elif defined(__BEOS__) + if (kill_thread (thr->__handle) < B_OK) return -1; +#elif defined(HAVE_PTHREAD) + if (pthread_cancel (thr->__handle) != 0) return -1; +#endif + return 0; +} + +int qse_thr_start (qse_thr_t* thr, 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; + + if (__create_thread(thr) == -1) + { + thr->__state = QSE_THR_INCUBATING; + thr->__handle = QSE_THR_HND_INVALID; + return -1; + } + + thr->__state = QSE_THR_RUNNING; + return 0; +} + +int qse_thr_stop (qse_thr_t* thr) +{ + if (thr->__state == QSE_THR_RUNNING) + { + if (__cancel_thread(thr) == -1) return -1; + /* can't be sure of whether or not the thread is really terminated. */ + thr->__state = QSE_THR_ABORTED; + return 0; + } + + return -1; +} + +int qse_thr_join (qse_thr_t* thr) +{ + if (thr->__state == QSE_THR_INCUBATING) return -1; + if (!thr->__joinable) return -1; + +#if defined(_WIN32) + if (thr->__state == QSE_THR_RUNNING) + { + if (WaitForSingleObject ( + thr->__handle, INFINITE) == WAIT_FAILED) return -1; + } +#elif defined(__BEOS__) + if (wait_for_thread(thr->__handle, QSE_NULL) < B_OK) return -1; +#elif defined(HAVE_PTHREAD) + if (pthread_join(thr->__handle, QSE_NULL) != 0) return -1; +#endif + + thr->__joinable = 0; + return 0; +} + +int qse_thr_detach (qse_thr_t* thr) +{ + if (thr->__state == QSE_THR_INCUBATING) return -1; + if (!thr->__joinable) return -1; + +#if defined(HAVE_PTHREAD) + if (pthread_detach(thr->__handle) != 0) return -1; +#endif + + thr->__joinable = 0; + return 0; +} + +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; +#endif + return 0; +} + +int qse_thr_blocksig (qse_thr_t* thr, int sig) +{ +#if defined(HAVE_PTHREAD) + sigset_t mask; +#endif + + if (thr->__state != QSE_THR_RUNNING) return -1; + +#if defined(HAVE_PTHREAD) + sigemptyset (&mask); + sigaddset (&mask, sig); + if (pthread_sigmask (SIG_BLOCK, &mask, QSE_NULL) != 0) return -1; +#endif + return 0; +} + +int qse_thr_unblocksig (qse_thr_t* thr, int sig) +{ +#if defined(HAVE_PTHREAD) + sigset_t mask; +#endif + + if (thr->__state != QSE_THR_RUNNING) return -1; + +#if defined(HAVE_PTHREAD) + sigemptyset (&mask); + sigaddset (&mask, sig); + if (pthread_sigmask (SIG_UNBLOCK, &mask, QSE_NULL) != 0) return -1; +#endif + return 0; +} + +int qse_thr_blockallsigs (qse_thr_t* thr) +{ +#if defined(HAVE_PTHREAD) + sigset_t mask; +#endif + + if (thr->__state != QSE_THR_RUNNING) return -1; + +#if defined(HAVE_PTHREAD) + sigfillset (&mask); + if (pthread_sigmask (SIG_BLOCK, &mask, QSE_NULL) != 0) return -1; +#endif + return 0; +} + +int qse_thr_unblockallsigs (qse_thr_t* thr) +{ +#if defined(HAVE_PTHREAD) + sigset_t mask; +#endif + + if (thr->__state != QSE_THR_RUNNING) return -1; + +#if defined(HAVE_PTHREAD) + sigfillset (&mask); + if (pthread_sigmask (SIG_UNBLOCK, &mask, QSE_NULL) != 0) return -1; +#endif + return 0; +} + +qse_thr_hnd_t qse_thr_gethnd (qse_thr_t* thr) +{ + return thr->__handle; +} + +int qse_thr_getretcode (qse_thr_t* thr) +{ + return thr->__return_code; +} + +qse_thr_state_t qse_thr_getstate (qse_thr_t* thr) +{ + return thr->__state; +} + +qse_thr_hnd_t qse_getcurthrhnd (void) +{ +#if defined(_WIN32) + return GetCurrentThread (); +#elif defined(__OS2__) + return QSE_THR_HND_INVALID; /* TODO: implement this */ +#elif defined(__DOS__) + return QSE_THR_HND_INVALID; /* TODO: implement this */ +#elif defined(__BEOS__) + return QSE_THR_HND_INVALID; /* TODO: implement this */ +#else + return pthread_self (); +#endif +} + +#endif diff --git a/qse/lib/sys/thr.h b/qse/lib/sys/thr.h new file mode 100644 index 00000000..ba99a6f1 --- /dev/null +++ b/qse/lib/sys/thr.h @@ -0,0 +1,77 @@ +/* + * $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 EXPRESS 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. + */ + +#ifndef _QSE_LIB_CMN_THR_H_ +#define _QSE_LIB_CMN_THR_H_ + +#include + + +#if (!defined(__unix__) && !defined(__unix)) || defined(HAVE_PTHREAD) + +#if defined(_WIN32) +# include +# define QSE_THR_HND_INVALID INVALID_HANDLE_VALUE +#elif defined(__OS2__) + /* not implemented */ + +#elif defined(__DOS__) + + /* not implemented */ + +#elif defined(__BEOS__) +# include +# define QSE_THR_HND_INVALID (-1) +#else +# if defined(AIX) && defined(__GNUC__) + typedef int crid_t; + typedef unsigned int class_id_t; +# endif +# include +# include + +# 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 + + +#endif