In ISO C 23,
  - the type 'once_flag',
  - the macro ONCE_FLAG_INIT,
  - the declaration of function 'call_once'
are all available from <stdlib.h>, not only from <threads.h>.

1) This makes it clear that often call_once is needed in an application
without also needing mutexes. For this reason, I'm moving the 'call_once'
function definition out of the 'mtx' module, into a module of its own.

2) The requirement to have 'once_flag' defined in <stdlib.h> would mean
that Gnulib's stdlib.h replacement would have
  - to include <pthread.h> on Unix platforms, and
  - to include <windows.h> on native Windows.

Each of the two includes would cause a lot of trouble to users:
  - for <pthread.h>, by having many more cases of header file recursion
    (we had that often, and the workarounds were always ad-hoc),
  - for <windows.h>, by defining lots of identifiers in the namespace.

This is not worth the trouble, given that the workaround — include
<threads.h> instead of <stdlib.h> — is in the realm of ISO C and
very simple. I'm therefore not implementing ISO C 23 compatibility
on this point. We can revisit it in 10 years or so; then hopefully
some platforms will have restructured their header files and will
define 'once_flag' in <stdlib.h>.


2023-03-25  Bruno Haible  <br...@clisp.org>

        stdlib: ISO C 23: Document issue with once_flag and call_once.
        * doc/posix-headers/stdlib.texi: Document issue and workaround.

2023-03-25  Bruno Haible  <br...@clisp.org>

        call_once: New module, separate from mtx.
        * lib/threads.in.h (call_once): Declare as part of module 'call_once',
        not module 'mtx'.
        * lib/call_once.c: New file, extracted from lib/mtx.c.
        * lib/mtx.c (call_once): Remove function.
        * m4/threads_h.m4 (gl_THREADS_H_REQUIRE_DEFAULTS): Inititalize
        GNULIB_CALL_ONCE.
        * modules/threads-h (Makefile.am): Substitute GNULIB_CALL_ONCE.
        * modules/call_once: New file, based on modules/mtx.
        * modules/threads (Depends-on): Add call_once.
        * tests/test-threads-c++.cc: Update accordingly.
        * modules/call_once-tests: New file, based on modules/mtx-tests.
        * modules/mtx-tests (Files): Remove tests/test-call_once.c.
        (Makefile.am): Don't compile test-call_once.
        * doc/posix-functions/call_once.texi: Document that the relevant module
        is now 'call_once'.
        * NEWS: Mention the change.

>From 53370c23642eb6256dafd7b6abca8cc93581b7c2 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 25 Mar 2023 20:54:29 +0100
Subject: [PATCH 1/2] call_once: New module, separate from mtx.

* lib/threads.in.h (call_once): Declare as part of module 'call_once',
not module 'mtx'.
* lib/call_once.c: New file, extracted from lib/mtx.c.
* lib/mtx.c (call_once): Remove function.
* m4/threads_h.m4 (gl_THREADS_H_REQUIRE_DEFAULTS): Inititalize
GNULIB_CALL_ONCE.
* modules/threads-h (Makefile.am): Substitute GNULIB_CALL_ONCE.
* modules/call_once: New file, based on modules/mtx.
* modules/threads (Depends-on): Add call_once.
* tests/test-threads-c++.cc: Update accordingly.
* modules/call_once-tests: New file, based on modules/mtx-tests.
* modules/mtx-tests (Files): Remove tests/test-call_once.c.
(Makefile.am): Don't compile test-call_once.
* doc/posix-functions/call_once.texi: Document that the relevant module
is now 'call_once'.
* NEWS: Mention the change.
---
 ChangeLog                          | 20 ++++++++++
 NEWS                               |  4 ++
 doc/posix-functions/call_once.texi |  2 +-
 lib/call_once.c                    | 59 ++++++++++++++++++++++++++++++
 lib/mtx.c                          | 12 ------
 lib/threads.in.h                   |  2 +-
 m4/threads_h.m4                    |  3 +-
 modules/call_once                  | 31 ++++++++++++++++
 modules/call_once-tests            | 12 ++++++
 modules/mtx-tests                  |  6 +--
 modules/threads                    |  1 +
 modules/threads-h                  |  1 +
 tests/test-threads-c++.cc          |  3 ++
 13 files changed, 137 insertions(+), 19 deletions(-)
 create mode 100644 lib/call_once.c
 create mode 100644 modules/call_once
 create mode 100644 modules/call_once-tests

diff --git a/ChangeLog b/ChangeLog
index 9dd1b50086..07b96d5860 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2023-03-25  Bruno Haible  <br...@clisp.org>
+
+	call_once: New module, separate from mtx.
+	* lib/threads.in.h (call_once): Declare as part of module 'call_once',
+	not module 'mtx'.
+	* lib/call_once.c: New file, extracted from lib/mtx.c.
+	* lib/mtx.c (call_once): Remove function.
+	* m4/threads_h.m4 (gl_THREADS_H_REQUIRE_DEFAULTS): Inititalize
+	GNULIB_CALL_ONCE.
+	* modules/threads-h (Makefile.am): Substitute GNULIB_CALL_ONCE.
+	* modules/call_once: New file, based on modules/mtx.
+	* modules/threads (Depends-on): Add call_once.
+	* tests/test-threads-c++.cc: Update accordingly.
+	* modules/call_once-tests: New file, based on modules/mtx-tests.
+	* modules/mtx-tests (Files): Remove tests/test-call_once.c.
+	(Makefile.am): Don't compile test-call_once.
+	* doc/posix-functions/call_once.texi: Document that the relevant module
+	is now 'call_once'.
+	* NEWS: Mention the change.
+
 2023-03-25  Bruno Haible  <br...@clisp.org>
 
 	stdio: ISO C 23: Define _PRINTF_NAN_LEN_MAX.
diff --git a/NEWS b/NEWS
index 7863514118..fcfaf4906b 100644
--- a/NEWS
+++ b/NEWS
@@ -74,6 +74,10 @@ User visible incompatible changes
 
 Date        Modules         Changes
 
+2023-03-25  mtx             This module no longer provides the function
+                            call_once.  To get this function, use the new
+                            separate module 'call_once'.
+
 2023-03-08  time            This module is renamed to 'time-h'.
                             The new 'time' module now also works around an
                             inconsistency in glibc 2.31+ on Linux.
diff --git a/doc/posix-functions/call_once.texi b/doc/posix-functions/call_once.texi
index ee798db963..e7c6f07542 100644
--- a/doc/posix-functions/call_once.texi
+++ b/doc/posix-functions/call_once.texi
@@ -10,7 +10,7 @@
 @url{https://www.gnu.org/software/libc/manual/html_node/Call-Once.html}.
 @end ifnotinfo
 
-Gnulib module: mtx
+Gnulib module: call_once
 
 Portability problems fixed by Gnulib:
 @itemize
diff --git a/lib/call_once.c b/lib/call_once.c
new file mode 100644
index 0000000000..d11d9506fb
--- /dev/null
+++ b/lib/call_once.c
@@ -0,0 +1,59 @@
+/* ISO C 11 once-only initialization.
+   Copyright (C) 2005-2023 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation; either version 2.1 of the
+   License, or (at your option) any later version.
+
+   This file 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>, 2005, 2019.
+   Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-win32.h.  */
+
+#include <config.h>
+
+#include <threads.h>
+
+#include <errno.h>
+
+#if defined _WIN32 && ! defined __CYGWIN__
+/* Use Windows threads.  */
+
+# define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+# include <windows.h>
+
+# include <stdlib.h>
+
+#else
+/* Use POSIX threads.  */
+
+# include <pthread.h>
+
+#endif
+
+#if defined _WIN32 && ! defined __CYGWIN__
+/* Use Windows threads.  */
+
+void
+call_once (once_flag *flagp, void (*func) (void))
+{
+  glwthread_once (flagp, func);
+}
+
+#else
+/* Use POSIX threads.  */
+
+void
+call_once (once_flag *flagp, void (*func) (void))
+{
+  pthread_once (flagp, func);
+}
+
+#endif
diff --git a/lib/mtx.c b/lib/mtx.c
index fe15b69494..9292773cf4 100644
--- a/lib/mtx.c
+++ b/lib/mtx.c
@@ -187,12 +187,6 @@ mtx_destroy (mtx_t *mutex)
     }
 }
 
-void
-call_once (once_flag *flagp, void (*func) (void))
-{
-  glwthread_once (flagp, func);
-}
-
 #else
 /* Use POSIX threads.  */
 
@@ -279,10 +273,4 @@ mtx_destroy (mtx_t *mutex)
   pthread_mutex_destroy (mutex);
 }
 
-void
-call_once (once_flag *flagp, void (*func) (void))
-{
-  pthread_once (flagp, func);
-}
-
 #endif
diff --git a/lib/threads.in.h b/lib/threads.in.h
index e34c39de3f..2bc0f23b32 100644
--- a/lib/threads.in.h
+++ b/lib/threads.in.h
@@ -459,7 +459,7 @@ typedef pthread_once_t once_flag;
 
 #endif
 
-#if @GNULIB_MTX@
+#if @GNULIB_CALL_ONCE@
 # if !@HAVE_THREADS_H@
 _GL_FUNCDECL_SYS (call_once, void, (once_flag *, void (*) (void))
                                    _GL_ARG_NONNULL ((1, 2)));
diff --git a/m4/threads_h.m4 b/m4/threads_h.m4
index 77fe20d279..851490c123 100644
--- a/m4/threads_h.m4
+++ b/m4/threads_h.m4
@@ -1,4 +1,4 @@
-# threads_h.m4 serial 10
+# threads_h.m4 serial 11
 dnl Copyright (C) 2019-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -156,6 +156,7 @@ AC_DEFUN([gl_THREADS_MODULE_INDICATOR]
 AC_DEFUN([gl_THREADS_H_REQUIRE_DEFAULTS],
 [
   m4_defun(GL_MODULE_INDICATOR_PREFIX[_THREADS_H_MODULE_INDICATOR_DEFAULTS], [
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_CALL_ONCE])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_CND])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MTX])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_THRD])
diff --git a/modules/call_once b/modules/call_once
new file mode 100644
index 0000000000..3efc3f3736
--- /dev/null
+++ b/modules/call_once
@@ -0,0 +1,31 @@
+Description:
+call_once() function: ISO C 11 once-only initialization.
+
+Files:
+lib/call_once.c
+
+Depends-on:
+threads-h
+windows-once
+
+configure.ac:
+AC_REQUIRE([gl_THREADS_H])
+gl_CONDITIONAL([GL_COND_OBJ_CALL_ONCE], [test $HAVE_THREADS_H = 0])
+gl_THREADS_MODULE_INDICATOR([call_once])
+
+Makefile.am:
+if GL_COND_OBJ_CALL_ONCE
+lib_SOURCES += call_once.c
+endif
+
+Include:
+<threads.h>
+
+Link:
+$(LIBSTDTHREAD)
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/call_once-tests b/modules/call_once-tests
new file mode 100644
index 0000000000..70bae25eb3
--- /dev/null
+++ b/modules/call_once-tests
@@ -0,0 +1,12 @@
+Files:
+tests/test-call_once.c
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-call_once
+check_PROGRAMS += test-call_once
+test_call_once_LDADD = $(LDADD) @LIBSTDTHREAD@
diff --git a/modules/mtx-tests b/modules/mtx-tests
index 52310625a5..4a021d22fa 100644
--- a/modules/mtx-tests
+++ b/modules/mtx-tests
@@ -1,6 +1,5 @@
 Files:
 tests/test-mtx.c
-tests/test-call_once.c
 tests/atomic-int-isoc.h
 tests/macros.h
 
@@ -14,7 +13,6 @@ AC_CHECK_HEADERS_ONCE([semaphore.h])
 AC_CHECK_DECLS_ONCE([alarm])
 
 Makefile.am:
-TESTS += test-mtx test-call_once
-check_PROGRAMS += test-mtx test-call_once
+TESTS += test-mtx
+check_PROGRAMS += test-mtx
 test_mtx_LDADD = $(LDADD) @LIBSTDTHREAD@ @LIBTHREAD@
-test_call_once_LDADD = $(LDADD) @LIBSTDTHREAD@
diff --git a/modules/threads b/modules/threads
index 18391c1c2d..c5bed1c328 100644
--- a/modules/threads
+++ b/modules/threads
@@ -6,6 +6,7 @@ Files:
 Depends-on:
 threads-h
 thrd
+call_once
 mtx
 cnd
 tss
diff --git a/modules/threads-h b/modules/threads-h
index 50a60dfdab..1a2b83a354 100644
--- a/modules/threads-h
+++ b/modules/threads-h
@@ -50,6 +50,7 @@ threads.h: threads.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(_NORETURN_H
 	      -e 's|@''PRAGMA_COLUMNS''@|@PRAGMA_COLUMNS@|g' \
 	      -e 's|@''NEXT_AS_FIRST_DIRECTIVE_THREADS_H''@|$(NEXT_AS_FIRST_DIRECTIVE_THREADS_H)|g' \
 	      -e 's|@''NEXT_THREADS_H''@|$(NEXT_THREADS_H)|g' \
+	      -e 's/@''GNULIB_CALL_ONCE''@/$(GNULIB_CALL_ONCE)/g' \
 	      -e 's/@''GNULIB_CND''@/$(GNULIB_CND)/g' \
 	      -e 's/@''GNULIB_MTX''@/$(GNULIB_MTX)/g' \
 	      -e 's/@''GNULIB_THRD''@/$(GNULIB_THRD)/g' \
diff --git a/tests/test-threads-c++.cc b/tests/test-threads-c++.cc
index 7c3bcb80b1..d82b526458 100644
--- a/tests/test-threads-c++.cc
+++ b/tests/test-threads-c++.cc
@@ -45,6 +45,9 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_timedlock, int,
                  (mtx_t *, const struct timespec *));
 SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_unlock, int, (mtx_t *));
 SIGNATURE_CHECK (GNULIB_NAMESPACE::mtx_destroy, void, (mtx_t *));
+#endif
+
+#if GNULIB_TEST_CALL_ONCE
 SIGNATURE_CHECK (GNULIB_NAMESPACE::call_once, void,
                  (once_flag *, void (*) (void)));
 #endif
-- 
2.34.1

>From 55a1207abc196655b9ef7c34b3cb7d736e6e7fe7 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 25 Mar 2023 21:48:31 +0100
Subject: [PATCH 2/2] stdlib: ISO C 23: Document issue with once_flag and
 call_once.

* doc/posix-headers/stdlib.texi: Document issue and workaround.
---
 ChangeLog                     | 5 +++++
 doc/posix-headers/stdlib.texi | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 07b96d5860..a0de338759 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2023-03-25  Bruno Haible  <br...@clisp.org>
+
+	stdlib: ISO C 23: Document issue with once_flag and call_once.
+	* doc/posix-headers/stdlib.texi: Document issue and workaround.
+
 2023-03-25  Bruno Haible  <br...@clisp.org>
 
 	call_once: New module, separate from mtx.
diff --git a/doc/posix-headers/stdlib.texi b/doc/posix-headers/stdlib.texi
index e7145b7dcc..612e794068 100644
--- a/doc/posix-headers/stdlib.texi
+++ b/doc/posix-headers/stdlib.texi
@@ -29,6 +29,12 @@
 Portability problems not fixed by Gnulib:
 @itemize
 @item
+The definition of the type @code{once_flag}, of the macro
+@code{ONCE_FLAG_INIT}, and the declaration of the function
+@code{call_once}, that are required by ISO C 23, are not provided.
+To get them, import Gnulib module @code{call_once} and include
+@code{<threads.h>} rather than @code{<stdlib.h>}.
+@item
 System status macros such as @code{WEXITSTATUS} require an lvalue
 argument on some platforms.
 macOS 11.1.
-- 
2.34.1

Reply via email to