1 /* Use the internal lock used by mbrtowc and mbrtoc32.
2 Copyright (C) 2019-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file 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 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2019-2020. */
19 /* Use a lock, so that no two threads can invoke mbtowc at the same time. */
22 mbtowc_unlocked (wchar_t *pwc
, const char *p
, size_t m
)
24 /* Put the hidden internal state of mbtowc into an initial state.
25 This is needed at least with glibc, uClibc, and MSVC CRT.
26 See <https://sourceware.org/bugzilla/show_bug.cgi?id=9674>. */
27 mbtowc (NULL
, NULL
, 0);
29 return mbtowc (pwc
, p
, m
);
32 /* Prohibit renaming this symbol. */
33 #undef gl_get_mbtowc_lock
35 #if AVOID_ANY_THREADS || GNULIB_MBRTOWC_SINGLE_THREAD
37 /* All uses of this function are in a single thread. No locking needed. */
40 mbtowc_with_lock (wchar_t *pwc
, const char *p
, size_t m
)
42 return mbtowc_unlocked (pwc
, p
, m
);
45 #elif defined _WIN32 && !defined __CYGWIN__
47 extern __declspec(dllimport
) CRITICAL_SECTION
*gl_get_mbtowc_lock (void);
50 mbtowc_with_lock (wchar_t *pwc
, const char *p
, size_t m
)
52 CRITICAL_SECTION
*lock
= gl_get_mbtowc_lock ();
55 EnterCriticalSection (lock
);
56 ret
= mbtowc_unlocked (pwc
, p
, m
);
57 LeaveCriticalSection (lock
);
62 #elif HAVE_PTHREAD_API /* AIX, IRIX, Cygwin */
65 # if defined _WIN32 || defined __CYGWIN__
68 pthread_mutex_t
*gl_get_mbtowc_lock (void);
70 # if HAVE_WEAK_SYMBOLS /* IRIX */
72 /* Avoid the need to link with '-lpthread'. */
73 # pragma weak pthread_mutex_lock
74 # pragma weak pthread_mutex_unlock
76 /* Determine whether libpthread is in use. */
77 # pragma weak pthread_mutexattr_gettype
78 /* See the comments in lock.h. */
79 # define pthread_in_use() \
80 (pthread_mutexattr_gettype != NULL || c11_threads_in_use ())
83 # define pthread_in_use() 1
87 mbtowc_with_lock (wchar_t *pwc
, const char *p
, size_t m
)
91 pthread_mutex_t
*lock
= gl_get_mbtowc_lock ();
94 if (pthread_mutex_lock (lock
))
96 ret
= mbtowc_unlocked (pwc
, p
, m
);
97 if (pthread_mutex_unlock (lock
))
103 return mbtowc_unlocked (pwc
, p
, m
);
108 extern mtx_t
*gl_get_mbtowc_lock (void);
111 mbtowc_with_lock (wchar_t *pwc
, const char *p
, size_t m
)
113 mtx_t
*lock
= gl_get_mbtowc_lock ();
116 if (mtx_lock (lock
) != thrd_success
)
118 ret
= mbtowc_unlocked (pwc
, p
, m
);
119 if (mtx_unlock (lock
) != thrd_success
)