[libcxx-commits] [libcxx] r357104 - Fix and speedup __libcpp_locale_guard on Windows
Thomas Anderson via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Mar 27 11:09:30 PDT 2019
Author: thomasanderson
Date: Wed Mar 27 11:09:30 2019
New Revision: 357104
URL: http://llvm.org/viewvc/llvm-project?rev=357104&view=rev
Log:
Fix and speedup __libcpp_locale_guard on Windows
The old implementation assumed the POSIX `setlocale()` API where the old
locale is returned. On Windows, the _new_ locale is returned. This meant
that `__libcpp_locale_guard` wasn't resetting the locale on destruction.
The new implementation fixes the above issue and takes advantage of
`setlocale(LC_ALL)` to reduce the number of calls, and also avoids setting
the locale at all if it's not necessary.
Differential Revision: https://reviews.llvm.org/D59572
Modified:
libcxx/trunk/include/__locale
Modified: libcxx/trunk/include/__locale
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__locale?rev=357104&r1=357103&r2=357104&view=diff
==============================================================================
--- libcxx/trunk/include/__locale (original)
+++ libcxx/trunk/include/__locale Wed Mar 27 11:09:30 2019
@@ -19,6 +19,7 @@
#include <cctype>
#include <locale.h>
#if defined(_LIBCPP_MSVCRT_LIKE)
+# include <cstring>
# include <support/win32/locale_win32.h>
#elif defined(_AIX)
# include <support/ibm/xlocale.h>
@@ -63,28 +64,41 @@ private:
#elif defined(_LIBCPP_MSVCRT_LIKE)
struct __libcpp_locale_guard {
__libcpp_locale_guard(locale_t __l) :
- __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)),
- __locale_collate(setlocale(LC_COLLATE, __l.__get_locale())),
- __locale_ctype(setlocale(LC_CTYPE, __l.__get_locale())),
- __locale_monetary(setlocale(LC_MONETARY, __l.__get_locale())),
- __locale_numeric(setlocale(LC_NUMERIC, __l.__get_locale())),
- __locale_time(setlocale(LC_TIME, __l.__get_locale()))
- // LC_MESSAGES is not supported on Windows.
- {}
+ __status(_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)) {
+ // Setting the locale can be expensive even when the locale given is
+ // already the current locale, so do an explicit check to see if the
+ // current locale is already the one we want.
+ const char* __lc = __setlocale(nullptr);
+ // If every category is the same, the locale string will simply be the
+ // locale name, otherwise it will be a semicolon-separated string listing
+ // each category. In the second case, we know at least one category won't
+ // be what we want, so we only have to check the first case.
+ if (strcmp(__l.__get_locale(), __lc) != 0) {
+ __locale_all = _strdup(__lc);
+ if (__locale_all == nullptr)
+ __throw_bad_alloc();
+ __setlocale(__l.__get_locale());
+ }
+ }
~__libcpp_locale_guard() {
- setlocale(LC_COLLATE, __locale_collate);
- setlocale(LC_CTYPE, __locale_ctype);
- setlocale(LC_MONETARY, __locale_monetary);
- setlocale(LC_NUMERIC, __locale_numeric);
- setlocale(LC_TIME, __locale_time);
- _configthreadlocale(__status);
+ // The CRT documentation doesn't explicitly say, but setlocale() does the
+ // right thing when given a semicolon-separated list of locale settings
+ // for the different categories in the same format as returned by
+ // setlocale(LC_ALL, nullptr).
+ if (__locale_all != nullptr) {
+ __setlocale(__locale_all);
+ free(__locale_all);
+ }
+ _configthreadlocale(__status);
+ }
+ static const char* __setlocale(const char* __locale) {
+ const char* __new_locale = setlocale(LC_ALL, __locale);
+ if (__new_locale == nullptr)
+ __throw_bad_alloc();
+ return __new_locale;
}
int __status;
- char* __locale_collate;
- char* __locale_ctype;
- char* __locale_monetary;
- char* __locale_numeric;
- char* __locale_time;
+ char* __locale_all = nullptr;
};
#endif
More information about the libcxx-commits
mailing list