Do the Windows oldnames workaround through the C++ GNULIB_NAMESPACE.
[gnulib.git] / lib / pthread-cond.c
blob99270665bbadfcf66bb90dcb6aee3839a1e46546
1 /* POSIX condition variables.
2 Copyright (C) 2010-2020 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Paul Eggert, 2010, and Bruno Haible <bruno@clisp.org>, 2019. */
19 #include <config.h>
21 /* Specification. */
22 #include <pthread.h>
24 #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS
25 # include "windows-thread.h"
26 #else
27 # include <errno.h>
28 # include <limits.h>
29 # include <sys/time.h>
30 # include <time.h>
31 #endif
33 #if ((defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS) || !HAVE_PTHREAD_H
35 int
36 pthread_condattr_init (pthread_condattr_t *attr)
38 *attr = 0;
39 return 0;
42 int
43 pthread_condattr_destroy (pthread_condattr_t *attr _GL_UNUSED)
45 return 0;
48 #endif
50 #if (defined _WIN32 && ! defined __CYGWIN__) && USE_WINDOWS_THREADS
51 /* Use Windows threads. */
53 int
54 pthread_cond_init (pthread_cond_t *cond,
55 const pthread_condattr_t *attr _GL_UNUSED)
57 return glwthread_cond_init (cond);
60 int
61 pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
63 return glwthread_cond_wait (cond, mutex,
64 (int (*) (void *)) pthread_mutex_lock,
65 (int (*) (void *)) pthread_mutex_unlock);
68 int
69 pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
70 const struct timespec *abstime)
72 return glwthread_cond_timedwait (cond, mutex,
73 (int (*) (void *)) pthread_mutex_lock,
74 (int (*) (void *)) pthread_mutex_unlock,
75 abstime);
78 int
79 pthread_cond_signal (pthread_cond_t *cond)
81 return glwthread_cond_signal (cond);
84 int
85 pthread_cond_broadcast (pthread_cond_t *cond)
87 return glwthread_cond_broadcast (cond);
90 int
91 pthread_cond_destroy (pthread_cond_t *cond)
93 return glwthread_cond_destroy (cond);
96 #elif HAVE_PTHREAD_H
97 /* Provide workarounds for POSIX threads. */
99 #else
100 /* Provide a dummy implementation for single-threaded applications. */
103 pthread_cond_init (pthread_cond_t *cond _GL_UNUSED,
104 const pthread_condattr_t *attr _GL_UNUSED)
106 /* COND is never seriously used. */
107 return 0;
111 pthread_cond_wait (pthread_cond_t *cond _GL_UNUSED,
112 pthread_mutex_t *mutex _GL_UNUSED)
114 /* No other thread can signal this condition variable.
115 Wait endlessly. */
116 for (;;)
118 struct timespec duration;
120 duration.tv_sec = 86400;
121 duration.tv_usec = 0;
122 nanosleep (&duration, NULL);
127 pthread_cond_timedwait (pthread_cond_t *cond _GL_UNUSED,
128 pthread_mutex_t *mutex _GL_UNUSED,
129 const struct timespec *abstime)
131 /* No other thread can signal this condition variable.
132 Wait until ABSTIME is reached. */
133 for (;;)
135 struct timeval currtime;
136 unsigned long remaining;
137 struct timespec duration;
139 gettimeofday (&currtime, NULL);
141 if (currtime.tv_sec > abstime->tv_sec)
142 remaining = 0;
143 else
145 unsigned long seconds = abstime->tv_sec - currtime.tv_sec;
146 remaining = seconds * 1000000000;
147 if (remaining / 1000000000 != seconds) /* overflow? */
148 remaining = ULONG_MAX;
149 else
151 long nanoseconds =
152 abstime->tv_nsec - currtime.tv_usec * 1000;
153 if (nanoseconds >= 0)
155 remaining += nanoseconds;
156 if (remaining < nanoseconds) /* overflow? */
157 remaining = ULONG_MAX;
159 else
161 if (remaining >= - nanoseconds)
162 remaining -= (- nanoseconds);
163 else
164 remaining = 0;
168 if (remaining == 0)
169 return ETIMEDOUT;
171 /* Sleep up to REMAINING ns. */
172 duration.tv_sec = remaining / 1000000000;
173 duration.tv_nsec = remaining % 1000000000;
174 nanosleep (&duration, NULL);
179 pthread_cond_signal (pthread_cond_t *cond _GL_UNUSED)
181 /* No threads can currently be blocked on COND. */
182 return 0;
186 pthread_cond_broadcast (pthread_cond_t *cond _GL_UNUSED)
188 /* No threads can currently be blocked on COND. */
189 return 0;
193 pthread_cond_destroy (pthread_cond_t *cond _GL_UNUSED)
195 /* COND is never seriously used. */
196 return 0;
199 #endif