[libcxx] r302474 - Refactor <locale> RAII guards to aid upcoming Windows locale changes.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Mon May 8 15:02:44 PDT 2017


Author: ericwf
Date: Mon May  8 17:02:43 2017
New Revision: 302474

URL: http://llvm.org/viewvc/llvm-project?rev=302474&view=rev
Log:
Refactor <locale> RAII guards to aid upcoming Windows locale changes.

Previously <locale> used std::unique_ptr<remove_ptr<locale_t>, locale-mgmt-function>
as a scope guard for (A) creating new locales, and (B) setting the thread specific locale
in RAII safe manner.

However using unique_ptr has some problems, first it requires that locale_t is a pointer
type, which may not be the case (Windows will need a non-pointer locale_t type that emulates _locale_t).

The second problem is that users of the guards had to supply the locale management function to the custom
deleter at every call site. However these locale management functions don't exist natively Windows, making
a good Windows implementation of locale more difficult.

This patch creates distinct and simply RAII guards that replace unique_ptr. These guards handle calling
the correct locale management function so that callers don't have too. This simplification will
aid in upcoming Windows fixes.

Modified:
    libcxx/trunk/include/__bsd_locale_fallbacks.h
    libcxx/trunk/include/__locale
    libcxx/trunk/include/locale
    libcxx/trunk/src/locale.cpp
    libcxx/trunk/src/support/win32/locale_win32.cpp

Modified: libcxx/trunk/include/__bsd_locale_fallbacks.h
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__bsd_locale_fallbacks.h?rev=302474&r1=302473&r2=302474&view=diff
==============================================================================
--- libcxx/trunk/include/__bsd_locale_fallbacks.h (original)
+++ libcxx/trunk/include/__bsd_locale_fallbacks.h Mon May  8 17:02:43 2017
@@ -19,27 +19,24 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
-typedef _VSTD::remove_pointer<locale_t>::type __use_locale_struct;
-typedef _VSTD::unique_ptr<__use_locale_struct, decltype(&uselocale)> __locale_raii;
-
 inline _LIBCPP_ALWAYS_INLINE
 decltype(MB_CUR_MAX) __libcpp_mb_cur_max_l(locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return MB_CUR_MAX;
 }
 
 inline _LIBCPP_ALWAYS_INLINE
 wint_t __libcpp_btowc_l(int __c, locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return btowc(__c);
 }
 
 inline _LIBCPP_ALWAYS_INLINE
 int __libcpp_wctob_l(wint_t __c, locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return wctob(__c);
 }
 
@@ -47,14 +44,14 @@ inline _LIBCPP_ALWAYS_INLINE
 size_t __libcpp_wcsnrtombs_l(char *__dest, const wchar_t **__src, size_t __nwc,
                          size_t __len, mbstate_t *__ps, locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return wcsnrtombs(__dest, __src, __nwc, __len, __ps);
 }
 
 inline _LIBCPP_ALWAYS_INLINE
 size_t __libcpp_wcrtomb_l(char *__s, wchar_t __wc, mbstate_t *__ps, locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return wcrtomb(__s, __wc, __ps);
 }
 
@@ -62,7 +59,7 @@ inline _LIBCPP_ALWAYS_INLINE
 size_t __libcpp_mbsnrtowcs_l(wchar_t * __dest, const char **__src, size_t __nms,
                       size_t __len, mbstate_t *__ps, locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return mbsnrtowcs(__dest, __src, __nms, __len, __ps);
 }
 
@@ -70,28 +67,28 @@ inline _LIBCPP_ALWAYS_INLINE
 size_t __libcpp_mbrtowc_l(wchar_t *__pwc, const char *__s, size_t __n,
                    mbstate_t *__ps, locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return mbrtowc(__pwc, __s, __n, __ps);
 }
 
 inline _LIBCPP_ALWAYS_INLINE
 int __libcpp_mbtowc_l(wchar_t *__pwc, const char *__pmb, size_t __max, locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return mbtowc(__pwc, __pmb, __max);
 }
 
 inline _LIBCPP_ALWAYS_INLINE
 size_t __libcpp_mbrlen_l(const char *__s, size_t __n, mbstate_t *__ps, locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return mbrlen(__s, __n, __ps);
 }
 
 inline _LIBCPP_ALWAYS_INLINE
 lconv *__libcpp_localeconv_l(locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return localeconv();
 }
 
@@ -99,7 +96,7 @@ inline _LIBCPP_ALWAYS_INLINE
 size_t __libcpp_mbsrtowcs_l(wchar_t *__dest, const char **__src, size_t __len,
                      mbstate_t *__ps, locale_t __l)
 {
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     return mbsrtowcs(__dest, __src, __len, __ps);
 }
 
@@ -107,7 +104,7 @@ inline
 int __libcpp_snprintf_l(char *__s, size_t __n, locale_t __l, const char *__format, ...) {
     va_list __va;
     va_start(__va, __format);
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     int __res = vsnprintf(__s, __n, __format, __va);
     va_end(__va);
     return __res;
@@ -117,7 +114,7 @@ inline
 int __libcpp_asprintf_l(char **__s, locale_t __l, const char *__format, ...) {
     va_list __va;
     va_start(__va, __format);
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     int __res = vasprintf(__s, __format, __va);
     va_end(__va);
     return __res;
@@ -127,7 +124,7 @@ inline
 int __libcpp_sscanf_l(const char *__s, locale_t __l, const char *__format, ...) {
     va_list __va;
     va_start(__va, __format);
-    __locale_raii __current( uselocale(__l), uselocale );
+    __libcpp_locale_guard __current(__l);
     int __res = vsscanf(__s, __format, __va);
     va_end(__va);
     return __res;

Modified: libcxx/trunk/include/__locale
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__locale?rev=302474&r1=302473&r2=302474&view=diff
==============================================================================
--- libcxx/trunk/include/__locale (original)
+++ libcxx/trunk/include/__locale Mon May  8 17:02:43 2017
@@ -49,6 +49,25 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+#if !defined(_LIBCPP_LOCALE__L_EXTENSIONS) || defined(_LIBCPP_MSVCRT)
+struct __libcpp_locale_guard {
+  _LIBCPP_INLINE_VISIBILITY
+  __libcpp_locale_guard(locale_t& __loc) : __old_loc_(uselocale(__loc)) {}
+
+  _LIBCPP_INLINE_VISIBILITY
+  ~__libcpp_locale_guard() {
+    if (__old_loc_)
+      uselocale(__old_loc_);
+  }
+
+  locale_t __old_loc_;
+private:
+  __libcpp_locale_guard(__libcpp_locale_guard const&);
+  __libcpp_locale_guard& operator=(__libcpp_locale_guard const&);
+};
+#endif
+
+
 class _LIBCPP_TYPE_VIS locale;
 
 template <class _Facet>

Modified: libcxx/trunk/include/locale
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/locale?rev=302474&r1=302473&r2=302474&view=diff
==============================================================================
--- libcxx/trunk/include/locale (original)
+++ libcxx/trunk/include/locale Mon May  8 17:02:43 2017
@@ -233,9 +233,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 #define __cloc_defined
 #endif
 
-typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
-typedef _VSTD::unique_ptr<__locale_struct, decltype(&freelocale)> __locale_unique_ptr;
-
 // __scan_keyword
 // Scans [__b, __e) until a match is found in the basic_strings range
 //  [__kb, __ke) or until it can be shown that there is no match in [__kb, __ke).

Modified: libcxx/trunk/src/locale.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/locale.cpp?rev=302474&r1=302473&r2=302474&view=diff
==============================================================================
--- libcxx/trunk/src/locale.cpp (original)
+++ libcxx/trunk/src/locale.cpp Mon May  8 17:02:43 2017
@@ -45,6 +45,24 @@
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
+struct __libcpp_unique_locale {
+  __libcpp_unique_locale(const char* nm) : __loc_(newlocale(LC_ALL_MASK, nm, 0)) {}
+
+  ~__libcpp_unique_locale() {
+    if (__loc_)
+      freelocale(__loc_);
+  }
+
+  explicit operator bool() const { return __loc_; }
+
+  locale_t& get() { return __loc_; }
+
+  locale_t __loc_;
+private:
+  __libcpp_unique_locale(__libcpp_unique_locale const&);
+  __libcpp_unique_locale& operator=(__libcpp_unique_locale const&);
+};
+
 #ifdef __cloc_defined
 locale_t __cloc() {
   // In theory this could create a race condition. In practice
@@ -4185,7 +4203,7 @@ __widen_from_utf8<32>::~__widen_from_utf
 
 static bool checked_string_to_wchar_convert(wchar_t& dest,
                                             const char* ptr,
-                                            __locale_struct* loc) {
+                                            locale_t loc) {
   if (*ptr == '\0')
     return false;
   mbstate_t mb = {};
@@ -4200,7 +4218,7 @@ static bool checked_string_to_wchar_conv
 
 static bool checked_string_to_char_convert(char& dest,
                                            const char* ptr,
-                                           __locale_struct* __loc) {
+                                           locale_t __loc) {
   if (*ptr == '\0')
     return false;
   if (!ptr[1]) {
@@ -4295,8 +4313,8 @@ numpunct_byname<char>::__init(const char
 {
     if (strcmp(nm, "C") != 0)
     {
-        __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-        if (loc == nullptr)
+        __libcpp_unique_locale loc(nm);
+        if (!loc)
             __throw_runtime_error("numpunct_byname<char>::numpunct_byname"
                                 " failed to construct for " + string(nm));
 
@@ -4333,8 +4351,8 @@ numpunct_byname<wchar_t>::__init(const c
 {
     if (strcmp(nm, "C") != 0)
     {
-        __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-        if (loc == nullptr)
+        __libcpp_unique_locale loc(nm);
+        if (!loc)
             __throw_runtime_error("numpunct_byname<wchar_t>::numpunct_byname"
                                 " failed to construct for " + string(nm));
 
@@ -5820,8 +5838,8 @@ void
 moneypunct_byname<char, false>::init(const char* nm)
 {
     typedef moneypunct<char, false> base;
-    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-    if (loc == nullptr)
+    __libcpp_unique_locale loc(nm);
+    if (!loc)
         __throw_runtime_error("moneypunct_byname"
                             " failed to construct for " + string(nm));
 
@@ -5864,8 +5882,8 @@ void
 moneypunct_byname<char, true>::init(const char* nm)
 {
     typedef moneypunct<char, true> base;
-    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-    if (loc == nullptr)
+    __libcpp_unique_locale loc(nm);
+    if (!loc)
         __throw_runtime_error("moneypunct_byname"
                             " failed to construct for " + string(nm));
 
@@ -5924,8 +5942,8 @@ void
 moneypunct_byname<wchar_t, false>::init(const char* nm)
 {
     typedef moneypunct<wchar_t, false> base;
-    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-    if (loc == nullptr)
+    __libcpp_unique_locale loc(nm);
+    if (!loc)
         __throw_runtime_error("moneypunct_byname"
                             " failed to construct for " + string(nm));
     lconv* lc = __libcpp_localeconv_l(loc.get());
@@ -5989,8 +6007,8 @@ void
 moneypunct_byname<wchar_t, true>::init(const char* nm)
 {
     typedef moneypunct<wchar_t, true> base;
-    __locale_unique_ptr loc(newlocale(LC_ALL_MASK, nm, 0), freelocale);
-    if (loc == nullptr)
+    __libcpp_unique_locale loc(nm);
+    if (!loc)
         __throw_runtime_error("moneypunct_byname"
                             " failed to construct for " + string(nm));
 

Modified: libcxx/trunk/src/support/win32/locale_win32.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/support/win32/locale_win32.cpp?rev=302474&r1=302473&r2=302474&view=diff
==============================================================================
--- libcxx/trunk/src/support/win32/locale_win32.cpp (original)
+++ libcxx/trunk/src/support/win32/locale_win32.cpp Mon May  8 17:02:43 2017
@@ -13,14 +13,14 @@
 #include <memory>
 #include <type_traits>
 
-typedef _VSTD::remove_pointer<locale_t>::type __locale_struct;
-typedef _VSTD::unique_ptr<__locale_struct, decltype(&uselocale)> __locale_raii;
+using std::__libcpp_locale_guard;
 
 // FIXME: base currently unused. Needs manual work to construct the new locale
 locale_t newlocale( int mask, const char * locale, locale_t /*base*/ )
 {
     return _create_locale( mask, locale );
 }
+
 locale_t uselocale( locale_t newloc )
 {
     locale_t old_locale = _get_current_locale();
@@ -36,59 +36,59 @@ locale_t uselocale( locale_t newloc )
 }
 lconv *localeconv_l( locale_t loc )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return localeconv();
 }
 size_t mbrlen_l( const char *__restrict s, size_t n,
                  mbstate_t *__restrict ps, locale_t loc )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return mbrlen( s, n, ps );
 }
 size_t mbsrtowcs_l( wchar_t *__restrict dst, const char **__restrict src,
                     size_t len, mbstate_t *__restrict ps, locale_t loc )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return mbsrtowcs( dst, src, len, ps );
 }
 size_t wcrtomb_l( char *__restrict s, wchar_t wc, mbstate_t *__restrict ps,
                   locale_t loc )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return wcrtomb( s, wc, ps );
 }
 size_t mbrtowc_l( wchar_t *__restrict pwc, const char *__restrict s,
                   size_t n, mbstate_t *__restrict ps, locale_t loc )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return mbrtowc( pwc, s, n, ps );
 }
 size_t mbsnrtowcs_l( wchar_t *__restrict dst, const char **__restrict src,
                      size_t nms, size_t len, mbstate_t *__restrict ps, locale_t loc )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return mbsnrtowcs( dst, src, nms, len, ps );
 }
 size_t wcsnrtombs_l( char *__restrict dst, const wchar_t **__restrict src,
                      size_t nwc, size_t len, mbstate_t *__restrict ps, locale_t loc )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return wcsnrtombs( dst, src, nwc, len, ps );
 }
 wint_t btowc_l( int c, locale_t loc )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return btowc( c );
 }
 int wctob_l( wint_t c, locale_t loc )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return wctob( c );
 }
 
 int snprintf_l(char *ret, size_t n, locale_t loc, const char *format, ...)
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     va_list ap;
     va_start( ap, format );
     int result = vsnprintf( ret, n, format, ap );
@@ -106,6 +106,6 @@ int asprintf_l( char **ret, locale_t loc
 }
 int vasprintf_l( char **ret, locale_t loc, const char *format, va_list ap )
 {
-    __locale_raii __current( uselocale(loc), uselocale );
+    __libcpp_locale_guard __current(loc);
     return vasprintf( ret, format, ap );
 }




More information about the cfe-commits mailing list