diff --git a/qse/configure b/qse/configure index 80f7c0d3..8680954c 100755 --- a/qse/configure +++ b/qse/configure @@ -21501,6 +21501,158 @@ $as_echo "#define QSE_PTHREAD_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_mutex_t" >&5 +$as_echo_n "checking size of pthread_mutex_t... " >&6; } +if ${ac_cv_sizeof_pthread_mutex_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (pthread_mutex_t))" "ac_cv_sizeof_pthread_mutex_t" "#include +"; then : + +else + if test "$ac_cv_type_pthread_mutex_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_mutex_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_pthread_mutex_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_pthread_mutex_t" >&5 +$as_echo "$ac_cv_sizeof_pthread_mutex_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_PTHREAD_MUTEX_T $ac_cv_sizeof_pthread_mutex_t +_ACEOF + + +if test ${ac_cv_sizeof_pthread_mutex_t} -gt 0 +then + + typename=`echo pthread_mutex_t | sed "s/[^a-zA-Z0-9_]/_/g"` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_mutex_t is signed" >&5 +$as_echo_n "checking whether pthread_mutex_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_mutex_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_mutex_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_MUTEX_T_IS_SIGNED 1" >>confdefs.h + + elif eval "test \"\${ax_cv_decl_${typename}_signed}\" = \"no\""; then + $as_echo_n "" + fi + +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_cond_t" >&5 +$as_echo_n "checking size of pthread_cond_t... " >&6; } +if ${ac_cv_sizeof_pthread_cond_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (pthread_cond_t))" "ac_cv_sizeof_pthread_cond_t" "#include +"; then : + +else + if test "$ac_cv_type_pthread_cond_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_cond_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_pthread_cond_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_pthread_cond_t" >&5 +$as_echo "$ac_cv_sizeof_pthread_cond_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_PTHREAD_COND_T $ac_cv_sizeof_pthread_cond_t +_ACEOF + + +if test ${ac_cv_sizeof_pthread_cond_t} -gt 0 +then + + typename=`echo pthread_cond_t | sed "s/[^a-zA-Z0-9_]/_/g"` + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_cond_t is signed" >&5 +$as_echo_n "checking whether pthread_cond_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_cond_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_cond_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_MUTEX_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 @@ -21829,6 +21981,16 @@ cat >>confdefs.h <<_ACEOF _ACEOF +cat >>confdefs.h <<_ACEOF +#define QSE_SIZEOF_PTHREAD_MUTEX_T ${ac_cv_sizeof_pthread_mutex_t} +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define QSE_SIZEOF_PTHREAD_COND_T ${ac_cv_sizeof_pthread_cond_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 eff23c91..2a1625de 100644 --- a/qse/configure.ac +++ b/qse/configure.ac @@ -455,6 +455,24 @@ then [#include ]) fi +AC_CHECK_SIZEOF(pthread_mutex_t,, [#include ]) +if test ${ac_cv_sizeof_pthread_mutex_t} -gt 0 +then + AX_CHECK_SIGN([pthread_mutex_t], + [ AC_DEFINE(QSE_PTHREAD_MUTEX_T_IS_SIGNED, 1, [Define if pthread_mutex_t is signed]) ], + [ AS_ECHO_N("") ], + [#include ]) +fi + +AC_CHECK_SIZEOF(pthread_cond_t,, [#include ]) +if test ${ac_cv_sizeof_pthread_cond_t} -gt 0 +then + AX_CHECK_SIGN([pthread_cond_t], + [ AC_DEFINE(QSE_PTHREAD_MUTEX_T_IS_SIGNED, 1, [Define if pthread_cond_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 @@ -585,6 +603,8 @@ AC_DEFINE_UNQUOTED(QSE_SIZEOF_STRUCT_SOCKADDR_IN6, ${ac_cv_sizeof_struct_sockadd 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)]) +AC_DEFINE_UNQUOTED(QSE_SIZEOF_PTHREAD_MUTEX_T, ${ac_cv_sizeof_pthread_mutex_t}, [sizeof(pthread_mutex_t)]) +AC_DEFINE_UNQUOTED(QSE_SIZEOF_PTHREAD_COND_T, ${ac_cv_sizeof_pthread_cond_t}, [sizeof(pthread_cond_t)]) qse_package_version_major="`echo ${PACKAGE_VERSION} | cut -d. -f1`" diff --git a/qse/include/qse/cmn/time.h b/qse/include/qse/cmn/time.h index 30bb921e..ee37ddde 100644 --- a/qse/include/qse/cmn/time.h +++ b/qse/include/qse/cmn/time.h @@ -27,7 +27,7 @@ #ifndef _QSE_CMN_TIME_H_ #define _QSE_CMN_TIME_H_ -/** @file +/** \file * This file provides time manipulation functions. */ diff --git a/qse/include/qse/config.h.in b/qse/include/qse/config.h.in index 93c09946..b35aa52d 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_cond_t is signed */ +#undef QSE_PTHREAD_MUTEX_T_IS_SIGNED + /* Define if pthread_t is signed */ #undef QSE_PTHREAD_T_IS_SIGNED @@ -925,6 +928,12 @@ /* sizeof(off_t) */ #undef QSE_SIZEOF_OFF_T +/* sizeof(pthread_cond_t) */ +#undef QSE_SIZEOF_PTHREAD_COND_T + +/* sizeof(pthread_mutex_t) */ +#undef QSE_SIZEOF_PTHREAD_MUTEX_T + /* sizeof(pthread_t) */ #undef QSE_SIZEOF_PTHREAD_T @@ -1012,6 +1021,12 @@ /* The size of `off_t', as computed by sizeof. */ #undef SIZEOF_OFF_T +/* The size of `pthread_cond_t', as computed by sizeof. */ +#undef SIZEOF_PTHREAD_COND_T + +/* The size of `pthread_mutex_t', as computed by sizeof. */ +#undef SIZEOF_PTHREAD_MUTEX_T + /* The size of `pthread_t', as computed by sizeof. */ #undef SIZEOF_PTHREAD_T diff --git a/qse/include/qse/sys/Makefile.am b/qse/include/qse/sys/Makefile.am index f34516d4..56ef857a 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 = \ + cnd.h \ mtx.h \ thr.h diff --git a/qse/include/qse/sys/Makefile.in b/qse/include/qse/sys/Makefile.in index 37e451c5..5c315011 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 = mtx.h thr.h SocketAddress.hpp +am__pkginclude_HEADERS_DIST = cnd.h mtx.h 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 = mtx.h thr.h $(am__append_1) +pkginclude_HEADERS = cnd.h mtx.h thr.h $(am__append_1) all: all-am .SUFFIXES: diff --git a/qse/include/qse/sys/cnd.h b/qse/include/qse/sys/cnd.h new file mode 100644 index 00000000..ca2acf97 --- /dev/null +++ b/qse/include/qse/sys/cnd.h @@ -0,0 +1,140 @@ +/* + * $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_CND_H_ +#define _QSE_CMN_CND_H_ + +#include +#include +#include +#include + +typedef struct qse_cnd_t qse_cnd_t; + + +#if defined(_WIN32) + /* define nothing */ +#elif defined(__OS2__) +# error not implemented + +#elif defined(__DOS__) +# error not implemented + +#else + +# if (QSE_SIZEOF_PTHREAD_COND_T == 0) +# error unsupported + +# elif (QSE_SIZEOF_PTHREAD_COND_T == QSE_SIZEOF_INT) +# if defined(QSE_PTHREAD_COND_T_IS_SIGNED) + typedef int qse_cnd_hnd_t; +# else + typedef unsigned int qse_cnd_hnd_t; +# endif +# elif (QSE_SIZEOF_PTHREAD_COND_T == QSE_SIZEOF_LONG) +# if defined(QSE_PTHREAD_COND_T_IS_SIGNED) + typedef long qse_cnd_hnd_t; +# else + typedef unsigned long qse_cnd_hnd_t; +# endif +# else +# include + struct qse_cnd_hnd_t + { + qse_uint8_t b[QSE_SIZEOF_PTHREAD_COND_T]; + }; + typedef struct qse_cnd_hnd_t qse_cnd_hnd_t; +# include +# endif + +#endif + +struct qse_cnd_t +{ + qse_mmgr_t* mmgr; + +#if defined(_WIN32) + void* gate; + void* queue; + void* mutex; + unsigned int gone; + unsigned long blocked; + unsigned int waiting; +#else + qse_cnd_hnd_t hnd; +#endif +}; + +#ifdef __cplusplus +extern "C" { +#endif + + +qse_cnd_t* qse_cnd_open ( + qse_mmgr_t* mmgr, + qse_size_t xtnsize +); + +void qse_cnd_close ( + qse_cnd_t* cnd +); + +int qse_cnd_init ( + qse_cnd_t* cnd, + qse_mmgr_t* mmgr +); + +void qse_cnd_fini ( + qse_cnd_t* cnd +); + +qse_mmgr_t* qse_cnd_getmmgr ( + qse_cnd_t* cnd +); + +void* qse_cnd_getxtn ( + qse_cnd_t* cnd +); + +void qse_cnd_signal ( + qse_cnd_t* cond +); + +void qse_cnd_broadcast ( + qse_cnd_t* cond +); + +void qse_cnd_wait ( + qse_cnd_t* cond, + qse_mtx_t* mutex, + qse_ntime_t* waiting_time +); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/qse/include/qse/sys/mtx.h b/qse/include/qse/sys/mtx.h index ce085e76..9cf6eb2b 100644 --- a/qse/include/qse/sys/mtx.h +++ b/qse/include/qse/sys/mtx.h @@ -31,21 +31,50 @@ #include #include +typedef struct qse_mtx_t qse_mtx_t; #if defined(_WIN32) + /* => typedef PVOID HANDLE; */ typedef void* qse_mtx_hnd_t; + #elif defined(__OS2__) + + /* not implemented */ # error not implemented #elif defined(__DOS__) + /* not implemented */ # error not implemented #elif defined(__BEOS__) - typedef sem_id qse_mtx_hnd_t; + /* typedef sem_id qse_mtx_hnd_t; */ + typdef qse_int32_t qse_mtx_hnd_t; #else -# include - typedef pthread_mutex_t qse_mtx_hnd_t; -#endif -typedef struct qse_mtx_t qse_mtx_t; +# if (QSE_SIZEOF_PTHREAD_MUTEX_T == 0) +# error unsupported + +# elif (QSE_SIZEOF_PTHREAD_MUTEX_T == QSE_SIZEOF_INT) +# if defined(QSE_PTHREAD_MUTEX_T_IS_SIGNED) + typedef int qse_mtx_hnd_t; +# else + typedef unsigned int qse_mtx_hnd_t; +# endif +# elif (QSE_SIZEOF_PTHREAD_MUTEX_T == QSE_SIZEOF_LONG) +# if defined(QSE_PTHREAD_MUTEX_T_IS_SIGNED) + typedef long qse_mtx_hnd_t; +# else + typedef unsigned long qse_mtx_hnd_t; +# endif +# else +# include + struct qse_mtx_hnd_t + { + qse_uint8_t b[QSE_SIZEOF_PTHREAD_MUTEX_T]; + }; + typedef struct qse_mtx_hnd_t qse_mtx_hnd_t; +# include +# endif + +#endif struct qse_mtx_t { diff --git a/qse/lib/sys/Makefile.am b/qse/lib/sys/Makefile.am index 9d070ad0..aa15374e 100644 --- a/qse/lib/sys/Makefile.am +++ b/qse/lib/sys/Makefile.am @@ -6,6 +6,7 @@ AM_CPPFLAGS = \ lib_LTLIBRARIES = libqsesys.la libqsesys_la_SOURCES = \ + cnd.c \ mtx.c \ thr.c \ thr.h diff --git a/qse/lib/sys/Makefile.in b/qse/lib/sys/Makefile.in index 8151ffeb..6baed342 100644 --- a/qse/lib/sys/Makefile.in +++ b/qse/lib/sys/Makefile.in @@ -127,7 +127,7 @@ am__uninstall_files_from_dir = { \ am__installdirs = "$(DESTDIR)$(libdir)" LTLIBRARIES = $(lib_LTLIBRARIES) libqsesys_la_DEPENDENCIES = -am_libqsesys_la_OBJECTS = mtx.lo thr.lo +am_libqsesys_la_OBJECTS = cnd.lo mtx.lo 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@) @@ -407,6 +407,7 @@ AM_CPPFLAGS = \ lib_LTLIBRARIES = libqsesys.la $(am__append_1) libqsesys_la_SOURCES = \ + cnd.c \ mtx.c \ thr.c \ thr.h @@ -501,6 +502,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketAddress.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cnd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mtx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thr.Plo@am__quote@ diff --git a/qse/lib/sys/cnd.c b/qse/lib/sys/cnd.c new file mode 100644 index 00000000..aff905e2 --- /dev/null +++ b/qse/lib/sys/cnd.c @@ -0,0 +1,383 @@ +/* + * $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 cnditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of cnditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of cnditions 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 +#include "../cmn/mem.h" + +#if (!defined(__unix__) && !defined(__unix)) || defined(HAVE_PTHREAD) + +#if defined(_WIN32) + #include +#elif defined(__OS2__) + /* implement this */ +#elif defined(__DOS__) + /* implement this */ +#else + #if defined(AIX) && defined(__GNUC__) + typedef int crid_t; + typedef unsigned int class_id_t; + #endif + #include +#endif + +qse_cnd_t* qse_cnd_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) +{ + qse_cnd_t* cnd; + + cnd = (qse_cnd_t*) QSE_MMGR_ALLOC (mmgr, QSE_SIZEOF(qse_cnd_t) + xtnsize); + if (cnd) + { + if (qse_cnd_init (cnd, mmgr) <= -1) + { + QSE_MMGR_FREE (mmgr, cnd); + return QSE_NULL; + } + else QSE_MEMSET (QSE_XTN(cnd), 0, xtnsize); + } + + return cnd; +} + +void qse_cnd_close (qse_cnd_t* cnd) +{ + qse_cnd_fini (cnd); + QSE_MMGR_FREE (cnd->mmgr, cnd); +} + + +int qse_cnd_init (qse_cnd_t* cnd, qse_mmgr_t* mmgr) +{ + QSE_MEMSET (cnd, 0, QSE_SIZEOF(*cnd)); + cnd->mmgr = mmgr; + +#ifdef _WIN32 + cnd->gone = 0; + cnd->blocked = 0; + cnd->waiting = 0; + + cnd->gate = CreateSemaphore (0, 1, 1, 0); + cnd->queue = CreateSemaphore (0, 0, QSE_TYPE_MAX(long), 0); + cnd->mutex = CreateMutex (0, 0, 0); + + if (cnd->gate == QSE_NULL || + cnd->queue == QSE_NULL || + cnd->mutex == QSE_NULL) + { + int num = qse_maperrno (GetLastError()); + + if (cnd->gate) CloseHandle (cnd->gate); + if (cnd->queue) CloseHandle (cnd->queue); + if (cnd->mutex) CloseHandle (cnd->mutex); + + return -1; + } +#elif defined(__OS2__) +# error not implemented +#elif defined(__DOS__) +# error not implemented +#else + if (pthread_cond_init ((pthread_cond_t*)&cnd->hnd, QSE_NULL) != 0) return -1; +#endif + + return 0; +} + +void qse_cnd_fini (qse_cnd_t* cnd) +{ +#ifdef _WIN32 + CloseHandle (cnd->gate); + CloseHandle (cnd->queue); + CloseHandle (cnd->mutex); +#elif defined(__OS2__) +# error not implemented +#elif defined(__DOS__) +# error not implemented +#else + pthread_cond_destroy ((pthread_cond_t*)&cnd->hnd); +#endif +} + +void qse_cnd_signal (qse_cnd_t* cnd) +{ +#ifdef _WIN32 + unsigned int signals = 0; + + WaitForSingleObject ((HANDLE)cnd->mutex, INFINITE); + if (cnd->waiting != 0) + { + if (cnd->blocked == 0) + { + ReleaseMutex ((HANDLE)cnd->mutex); + return; + } + + ++cnd->waiting; + --cnd->blocked; + signals = 1; + } + else + { + WaitForSingleObject ((HANDLE)cnd->gate, INFINITE); + if (cnd->blocked > cnd->gone) + { + if (cnd->gone != 0) + { + cnd->blocked -= cnd->gone; + cnd->gone = 0; + } + signals = cnd->waiting = 1; + --cnd->blocked; + } + else + { + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + } + } + + ReleaseMutex ((HANDLE)cnd->mutex); + if (signals) ReleaseSemaphore ((HANDLE)cnd->queue, signals, QSE_NULL); +#else + pthread_cond_signal ((pthread_cond_t*)&cnd->hnd); +#endif +} + +void qse_cnd_broadcast (qse_cnd_t* cnd) +{ +#ifdef _WIN32 + unsigned int signals = 0; + + WaitForSingleObject ((HANDLE)cnd->mutex, INFINITE); + + if (cnd->waiting != 0) + { + if (cnd->blocked == 0) + { + ReleaseMutex ((HANDLE)cnd->mutex); + return; + } + + cnd->waiting += (signals = cnd->blocked); + cnd->blocked = 0; + } + else + { + WaitForSingleObject ((HANDLE)cnd->gate, INFINITE); + if (cnd->blocked > cnd->gone) + { + if (cnd->gone != 0) + { + cnd->blocked -= cnd->gone; + cnd->gone = 0; + } + signals = cnd->waiting = cnd->blocked; + cnd->blocked = 0; + } + else + { + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + } + } + + ReleaseMutex ((HANDLE)cnd->mutex); + if (signals) ReleaseSemaphore ((HANDLE)cnd->queue, signals, QSE_NULL); +#else + pthread_cond_broadcast ((pthread_cond_t*)&cnd->hnd); +#endif +} + +void qse_cnd_wait (qse_cnd_t* cnd, qse_mtx_t* mutex, qse_ntime_t* waiting_time) +{ +#ifdef _WIN32 + unsigned int was_waiting, was_gone; + int signaled; + + WaitForSingleObject ((HANDLE)cnd->gate, INFINITE); + ++cnd->blocked; + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + + qse_mtx_unlock (mutex); + + if (waiting_time) + { + signaled = (WaitForSingleObject((HANDLE)cnd->queue, (DWORD)waiting_time) == WAIT_OBJECT_0); + } + else + { + WaitForSingleObject ((HANDLE)cnd->queue, INFINITE); + signaled = 1; + } + + was_waiting = 0; + was_gone = 0; + + WaitForSingleObject ((HANDLE)cnd->mutex, INFINITE); + + was_waiting = cnd->waiting; + was_gone = cnd->gone; + + if (was_waiting != 0) + { + if (!signaled) + { + /* timed out */ + if (cnd->blocked != 0) --cnd->blocked; + else ++cnd->gone; + } + + if (--cnd->waiting == 0) + { + if (cnd->blocked != 0) + { + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + was_waiting = 0; + } + else if (cnd->gone != 0) + { + cnd->gone = 0; + } + } + } + else if (++cnd->gone == QSE_TYPE_MAX(unsigned int) / 2) + { + WaitForSingleObject ((HANDLE)cnd->gate, INFINITE); + cnd->blocked -= cnd->gone; + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + cnd->gone = 0; + } + + ReleaseMutex ((HANDLE)cnd->mutex); + + if (was_waiting == 1) + { + for (;was_gone; --was_gone) + { + WaitForSingleObject ((HANDLE)cnd->queue, INFINITE); + } + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + } + + qse_mtx_lock (mutex); +#else + if (waiting_time) + { + qse_ntime_t t; + struct timespec ts; + + qse_gettime (&t); + qse_addtime (&t, waiting_time, &t); + + ts.tv_sec = t.sec; + ts.tv_nsec = t.nsec; + + pthread_cond_timedwait ((pthread_cond_t*)&cnd->hnd, (pthread_mutex_t*)&mutex->hnd, &ts); + } + else + { + /* no waiting */ + pthread_cond_wait ((pthread_cond_t*)&cnd->hnd, (pthread_mutex_t*)&mutex->hnd); + } +#endif +} + +#if 0 +void qse_cnd_twait ( + qse_cnd_t* cnd, qse_mtx_t* mutex, qse_time_t waiting_time) +{ +#ifdef _WIN32 + qse_bool_t signaled; + unsigned int was_waiting, was_gone; + + WaitForSingleObject ((HANDLE)cnd->gate, INFINITE); + ++cnd->blocked; + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + + qse_mtx_unlock (mutex); + + signaled = (WaitForSingleObject((HANDLE)cnd->queue, (DWORD)waiting_time) == WAIT_OBJECT_0); + + was_waiting = 0; + was_gone = 0; + + WaitForSingleObject ((HANDLE)cnd->mutex, INFINITE); + + was_waiting = cnd->waiting; + was_gone = cnd->gone; + + if (was_waiting != 0) + { + if (!signaled) + { /* timed out */ + if (cnd->blocked != 0) --(cnd->blocked); + else ++(cnd->gone); + } + if (--(cnd->waiting) == 0) + { + if (cnd->blocked != 0) + { + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + was_waiting = 0; + } + else if (cnd->gone != 0) cnd->gone = 0; + } + } + else if (++(cnd->gone) == QSE_TYPE_MAX(unsigned int) / 2) + { + WaitForSingleObject ((HANDLE)cnd->gate, INFINITE); + cnd->blocked -= cnd->gone; + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + cnd->gone = 0; + } + + ReleaseMutex ((HANDLE)cnd->mutex); + + if (was_waiting == 1) + { + for (;was_gone; --was_gone) + { + WaitForSingleObject ((HANDLE)cnd->queue, INFINITE); + } + ReleaseSemaphore ((HANDLE)cnd->gate, 1, QSE_NULL); + } + + qse_mtx_lock (mutex); +#else + qse_time_t now; + qse_timespec_t timeout; + + qse_gettime (&now); + now += waiting_time; + + QSE_TIME_TO_TIMESPEC (now, &timeout); + + QSE_ASSERT (QSE_SIZEOF(timeout) == QSE_SIZEOF(struct timespec)); + pthread_cond_timedwait (&cnd->hnd, &mutex->hnd, &timeout); +#endif +} + +#endif + + +#endif diff --git a/qse/lib/sys/mtx.c b/qse/lib/sys/mtx.c index 9baccf74..b0f5f9bc 100644 --- a/qse/lib/sys/mtx.c +++ b/qse/lib/sys/mtx.c @@ -31,6 +31,10 @@ #if defined(_WIN32) #include +#elif defined(__OS2__) + /* implement this */ +#elif defined(__DOS__) + /* implement this */ #elif defined(__BEOS__) #include #else @@ -41,7 +45,6 @@ #include #endif - qse_mtx_t* qse_mtx_open (qse_mmgr_t* mmgr, qse_size_t xtnsize) { qse_mtx_t* mtx; @@ -66,7 +69,6 @@ void qse_mtx_close (qse_mtx_t* mtx) QSE_MMGR_FREE (mtx->mmgr, mtx); } - int qse_mtx_init (qse_mtx_t* mtx, qse_mmgr_t* mmgr) { QSE_MEMSET (mtx, 0, QSE_SIZEOF(*mtx)); @@ -100,7 +102,7 @@ int qse_mtx_init (qse_mtx_t* mtx, qse_mmgr_t* mmgr) qse_ensure (pthread_mutex_init (&mtx->hnd, &attr) == 0); qse_ensure (pthread_mutexattr_destroy (&attr) == 0); */ - if (pthread_mutex_init (&mtx->hnd, QSE_NULL) != 0) return -1; + if (pthread_mutex_init ((pthread_mutex_t*)&mtx->hnd, QSE_NULL) != 0) return -1; #endif return 0; @@ -122,7 +124,7 @@ void qse_mtx_fini (qse_mtx_t* mtx) delete_sem(mtx->hnd); #else - pthread_mutex_destroy(&mtx->hnd); + pthread_mutex_destroy((pthread_mutex_t*)&mtx->hnd); #endif } @@ -160,7 +162,7 @@ int qse_mtx_lock (qse_mtx_t* mtx) #elif defined(__BEOS__) if (acquire_sem(mtx->hnd) != B_NO_ERROR) return -1; #else - if (pthread_mutex_lock (&mtx->hnd) != 0) return -1; + if (pthread_mutex_lock ((pthread_mutex_t*)&mtx->hnd) != 0) return -1; #endif return 0; } @@ -168,15 +170,11 @@ int qse_mtx_lock (qse_mtx_t* mtx) int qse_mtx_unlock (qse_mtx_t* mtx) { #if defined(_WIN32) - if (ReleaseMutex (mtx->hnd) == FALSE) - { - qse_seterrno (qse_maperrno(GetLastError())); - return -1; - } + if (ReleaseMutex (mtx->hnd) == FALSE) return -1; #elif defined(__BEOS__) if (release_sem(mtx->hnd) != B_NO_ERROR) return -1; #else - if (pthread_mutex_unlock (&mtx->hnd) != 0) return -1; + if (pthread_mutex_unlock ((pthread_mutex_t*)&mtx->hnd) != 0) return -1; #endif return 0; } @@ -184,19 +182,15 @@ int qse_mtx_unlock (qse_mtx_t* mtx) int qse_mtx_trylock (qse_mtx_t* mtx) { #if defined(_WIN32) - if (WaitForSingleObject(mtx->hnd,0) != WAIT_OBJECT_0) - { - qse_seterrno (qse_maperrno(GetLastError())); - return -1; - } + if (WaitForSingleObject(mtx->hnd, 0) != WAIT_OBJECT_0) return -1; #elif defined(__BEOS__) - if (acquire_sem_etc(mtx->hnd,1,B_ABSOLUTE_TIMEOUT,0) != B_NO_ERROR) + if (acquire_sem_etc(mtx->hnd, 1, B_ABSOLUTE_TIMEOUT, 0) != B_NO_ERROR) { /* TODO: check for B_WOULD_BLOCK */ return -1; } #else - if (pthread_mutex_trylock(&mtx->hnd) != 0) return -1; + if (pthread_mutex_trylock((pthread_mutex_t*)&mtx->hnd) != 0) return -1; #endif return 0; }