# HG changeset patch # User Yoann Vandoorselaere # Date 1218986495 -7200 # Node ID 44cc53e4b3f9fd2f8a824178247ed9426b977abe # Parent 794059e94b3693299804e370f5f5100c933c1305 New module 'cond'. diff -r 794059e94b36 -r 44cc53e4b3f9 ChangeLog --- a/ChangeLog Sun Aug 17 16:26:05 2008 +0200 +++ b/ChangeLog Sun Aug 17 17:21:35 2008 +0200 @@ -1,3 +1,11 @@ +2008-08-17 Yoann Vandoorselaere + + New module 'cond'. + * modules/cond: New file. + * lib/glthread/cond.h: New file. + * lib/glthread/cond.c: New file. + * m4/cond.m4: New file. + 2008-08-16 Eric Blake c-stack: fix regression on Irix 5.3 from 2008-06-21 diff -r 794059e94b36 -r 44cc53e4b3f9 lib/glthread/cond.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/glthread/cond.c Sun Aug 17 17:21:35 2008 +0200 @@ -0,0 +1,52 @@ +/* Condition variables for multithreading. + Copyright (C) 2008 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Yoann Vandoorselaere , 2008. */ + +#include + +#include "glthread/cond.h" + +/* ========================================================================= */ + +#if USE_PTH_THREADS + +/* -------------------------- gl_cond_t datatype -------------------------- */ + +int +glthread_cond_timedwait_multithreaded (gl_cond_t *cond, + gl_lock_t *lock, + struct timespec *abstime) +{ + int ret, status; + pth_event_t ev; + + ev = pth_event (PTH_EVENT_TIME, pth_time (abstime->tv_sec, abstime->tv_nsec / 1000)); + ret = pth_cond_await (cond, lock, ev); + + status = pth_event_status (ev); + pth_event_free (ev, PTH_FREE_THIS); + + if (status == PTH_STATUS_OCCURRED) + return ETIMEDOUT; + + return ret; +} + +#endif + +/* ========================================================================= */ diff -r 794059e94b36 -r 44cc53e4b3f9 lib/glthread/cond.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/glthread/cond.h Sun Aug 17 17:21:35 2008 +0200 @@ -0,0 +1,330 @@ +/* Condition variables for multithreading. + Copyright (C) 2005-2008 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Written by Yoann Vandoorselaere , 2008. + Based on Bruno Haible lock.h */ + +/* + Condition variables can be used for waiting until a condition + becomes true. In this respect, they are similar to wait queues. But + contrary to wait queues, condition variables have different + semantics that allows events to be lost when there is no thread + waiting for them. + + Condition variable: + Type: gl_cond_t + Declaration: gl_cond_define(extern, name) + Initializer: gl_cond_define_initialized(, name) + Initialization: gl_cond_init (name); + Waiting: gl_cond_wait (name, lock); + Timed wait: bool timedout = gl_cond_timedwait (name, lock, abstime); + where lock is a gl_lock_t variable (cf. ) + Signaling: gl_cond_signal (name); + Broadcasting: gl_cond_broadcast (name); + De-initialization: gl_cond_destroy (name); + Equivalent functions with control of error handling: + Initialization: err = glthread_cond_init (&name); + Waiting: err = glthread_cond_wait (&name); + Timed wait: err = glthread_cond_timedwait (&name, &lock, abstime); + Signaling: err = glthread_cond_signal (&name); + Broadcasting: err = glthread_cond_broadcast (&name); + De-initialization: err = glthread_cond_destroy (&name); +*/ + + +#ifndef _GLTHREAD_COND_H +#define _GLTHREAD_COND_H + +#include +#include + +#include "glthread/lock.h" + +/* ========================================================================= */ + +#if USE_POSIX_THREADS + +/* Use the POSIX threads library. */ + +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +# if PTHREAD_IN_USE_DETECTION_HARD + +/* The pthread_in_use() detection needs to be done at runtime. */ +# define pthread_in_use() \ + glthread_in_use () +extern int glthread_in_use (void); + +# endif + +# if USE_POSIX_THREADS_WEAK + +/* Use weak references to the POSIX threads library. */ + +/* Weak references avoid dragging in external libraries if the other parts + of the program don't use them. Here we use them, because we don't want + every program that uses libintl to depend on libpthread. This assumes + that libpthread would not be loaded after libintl; i.e. if libintl is + loaded first, by an executable that does not depend on libpthread, and + then a module is dynamically loaded that depends on libpthread, libintl + will not be multithread-safe. */ + +/* The way to test at runtime whether libpthread is present is to test + whether a function pointer's value, such as &pthread_mutex_init, is + non-NULL. However, some versions of GCC have a bug through which, in + PIC mode, &foo != NULL always evaluates to true if there is a direct + call to foo(...) in the same function. To avoid this, we test the + address of a function in libpthread that we don't use. */ + +# pragma weak pthread_cond_init +# pragma weak pthread_cond_wait +# pragma weak pthread_cond_timedwait +# pragma weak pthread_cond_signal +# pragma weak pthread_cond_broadcast +# pragma weak pthread_cond_destroy +# ifndef pthread_self +# pragma weak pthread_self +# endif + +# if !PTHREAD_IN_USE_DETECTION_HARD +# pragma weak pthread_cancel +# define pthread_in_use() (pthread_cancel != NULL) +# endif + +# else + +# if !PTHREAD_IN_USE_DETECTION_HARD +# define pthread_in_use() 1 +# endif + +# endif + +/* -------------------------- gl_cond_t datatype -------------------------- */ + +typedef pthread_cond_t gl_cond_t; +# define gl_cond_define(STORAGECLASS, NAME) \ + STORAGECLASS pthread_cond_t NAME; +# define gl_cond_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pthread_cond_t NAME = gl_cond_initializer; +# define gl_cond_initializer \ + PTHREAD_COND_INITIALIZER +# define glthread_cond_init(COND) \ + (pthread_in_use () ? pthread_cond_init (COND, NULL) : 0) +# define glthread_cond_wait(COND, LOCK) \ + (pthread_in_use () ? pthread_cond_wait (COND, LOCK) : 0) +# define glthread_cond_timedwait(COND, LOCK, ABSTIME) \ + (pthread_in_use () ? pthread_cond_timedwait (COND, LOCK, ABSTIME) : 0) +# define glthread_cond_signal(COND) \ + (pthread_in_use () ? pthread_cond_signal (COND) : 0) +# define glthread_cond_broadcast(COND) \ + (pthread_in_use () ? pthread_cond_broadcast (COND) : 0) +# define glthread_cond_destroy(COND) \ + (pthread_in_use () ? pthread_cond_destroy (COND) : 0) + +#endif + +/* ========================================================================= */ + +#if USE_PTH_THREADS + +/* Use the GNU Pth threads library. */ + +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +# if USE_PTH_THREADS_WEAK + +/* Use weak references to the GNU Pth threads library. */ + +# pragma weak pth_cond_init +# pragma weak pth_cond_await +# pragma weak pth_cond_notify +# pragma weak pth_event +# pragma weak pth_timeout + +# pragma weak pth_cancel +# define pth_in_use() (pth_cancel != NULL) + +# else + +# define pth_in_use() 1 + +# endif + +/* -------------------------- gl_cond_t datatype -------------------------- */ + +typedef pth_cond_t gl_cond_t; +# define gl_cond_define(STORAGECLASS, NAME) \ + STORAGECLASS pth_cond_t NAME; +# define gl_cond_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS pth_cond_t NAME = gl_cond_initializer; +# define gl_cond_initializer \ + PTH_COND_INIT +# define glthread_cond_init(COND) \ + (pth_in_use () && !pth_cond_init (COND) ? errno : 0) +# define glthread_cond_wait(COND, LOCK) \ + (pth_in_use () && !pth_cond_await (COND, LOCK, NULL) ? errno : 0) +# define glthread_cond_timedwait(COND, LOCK, ABSTIME) \ + (pth_in_use () ? glthread_cond_timedwait_multithreaded (COND, LOCK, ABSTIME) : 0) +# define glthread_cond_signal(COND) \ + (pth_in_use () && !pth_cond_notify (COND, FALSE) ? errno : 0) +# define glthread_cond_broadcast(COND) \ + (pth_in_use () && !pth_cond_notify (COND, TRUE) ? errno : 0) +# define glthread_cond_destroy(COND) 0 +extern int glthread_cond_timedwait_multithreaded (gl_cond_t *cond, gl_lock_t *lock, struct timespec *abstime); + +#endif + +/* ========================================================================= */ + +#if USE_SOLARIS_THREADS + +/* Use the old Solaris threads library. */ + +# include +# include +# include + +# ifdef __cplusplus +extern "C" { +# endif + +# if USE_SOLARIS_THREADS_WEAK + +/* Use weak references to the old Solaris threads library. */ + +# pragma weak cond_init +# pragma weak cond_wait +# pragma weak cond_timedwait +# pragma weak cond_signal +# pragma weak cond_broadcast +# pragma weak cond_destroy +# pragma weak thr_suspend +# define thread_in_use() (thr_suspend != NULL) + +# else + +# define thread_in_use() 1 + +# endif + +/* -------------------------- gl_cond_t datatype -------------------------- */ + +#define ETIMEDOUT ETIME + +typedef pthread_cond_t gl_cond_t; +# define gl_cond_define(STORAGECLASS, NAME) \ + STORAGECLASS cond_t NAME; +# define gl_cond_define_initialized(STORAGECLASS, NAME) \ + STORAGECLASS cond_t NAME = gl_cond_initializer; +# define gl_cond_initializer \ + DEFAULTCV +# define glthread_cond_init(COND) \ + (pthread_in_use () ? cond_init (COND, USYNC_THREAD, NULL) : 0) +# define glthread_cond_wait(COND, LOCK) \ + (pthread_in_use () ? cond_wait (COND, LOCK) : 0) +# define glthread_cond_timedwait(COND, LOCK, ABSTIME) \ + (pthread_in_use () ? cond_timedwait (COND, LOCK, ABSTIME) : 0) +# define glthread_cond_signal(COND) \ + (pthread_in_use () ? cond_signal (COND) : 0) +# define glthread_cond_broadcast(COND) \ + (pthread_in_use () ? cond_broadcast (COND) : 0) +# define glthread_cond_destroy(COND) \ + (pthread_in_use () ? cond_destroy (COND) : 0) + +#endif + +/* ========================================================================= */ + +#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS) + +/* Provide dummy implementation if threads are not supported. */ + +typedef int gl_cond_t; +# define gl_cond_define(STORAGECLASS, NAME) +# define gl_cond_define_initialized(STORAGECLASS, NAME) +# define glthread_cond_init(COND) 0 +# define glthread_cond_wait(COND, LOCK) 0 +# define glthread_cond_timedwait(COND, LOCK, ABSTIME) 0 +# define glthread_cond_signal(COND) 0 +# define glthread_cond_broadcast(COND) 0 +# define glthread_cond_destroy(COND) 0 + +#endif + +/* ========================================================================= */ + +/* Macros with built-in error handling. */ + +#define gl_cond_init(COND) \ + do \ + { \ + if (glthread_cond_init (&COND)) \ + abort (); \ + } \ + while (0) +#define gl_cond_wait(COND, LOCK) \ + do \ + { \ + if (glthread_cond_wait (&COND, &LOCK)) \ + abort (); \ + } \ + while (0) +#define gl_cond_timedwait(COND, LOCK, ABSTIME) \ + gl_cond_timedwait_func (&COND, &LOCK, ABSTIME) +static inline bool +gl_cond_timedwait_func (gl_cond_t *cond, gl_lock_t *lock, struct timespec *abstime) +{ + int err = glthread_cond_timedwait (cond, lock, abstime); + if (err == ETIMEDOUT) + return true; + if (err != 0) + abort (); + return false; +} +#define gl_cond_signal(COND) \ + do \ + { \ + if (glthread_cond_signal (&COND)) \ + abort (); \ + } \ + while (0) +#define gl_cond_broadcast(COND) \ + do \ + { \ + if (glthread_cond_broadcast (&COND)) \ + abort (); \ + } \ + while (0) +#define gl_cond_destroy(COND) \ + do \ + { \ + if (glthread_cond_destroy (&COND)) \ + abort (); \ + } \ + while (0) + +#endif /* _GLTHREAD_COND_H */ diff -r 794059e94b36 -r 44cc53e4b3f9 m4/cond.m4 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/m4/cond.m4 Sun Aug 17 17:21:35 2008 +0200 @@ -0,0 +1,11 @@ +# cond.m4 serial 1 +dnl Copyright (C) 2008 Free Software Foundation, Inc. +dnl This file is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +AC_DEFUN([gl_COND], +[ + AC_REQUIRE([gl_THREADLIB]) + AC_C_INLINE +]) diff -r 794059e94b36 -r 44cc53e4b3f9 modules/cond --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/cond Sun Aug 17 17:21:35 2008 +0200 @@ -0,0 +1,28 @@ +Description: +Condition variables for multithreading. + +Files: +lib/glthread/cond.h +lib/glthread/cond.c +m4/cond.m4 + +Depends-on: +threadlib +lock +stdbool + +configure.ac: +gl_COND + +Makefile.am: +lib_SOURCES += glthread/cond.h glthread/cond.c + +Include: +"glthread/cond.h" + +License: +LGPLv2+ + +Maintainer: +Yoann Vandoorselaere +