stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From vi...@apache.org
Subject svn commit: r653946 - in /stdcxx/branches/4.2.x: src/catalog.cpp src/messages.cpp tests/localization/22.locale.messages.mt.cpp
Date Tue, 06 May 2008 22:51:32 GMT
Author: vitek
Date: Tue May  6 15:51:31 2008
New Revision: 653946

URL: http://svn.apache.org/viewvc?rev=653946&view=rev
Log:
2008-05-06  Travis Vitek  <vitek@roguewave.com>

	STDCXX-845
	* src/messages.cpp (__rw_manage_cat_data): Employ a simple paging
	scheme and one level of indirection to avoid moving catalog data
	around when adding or removing message catalogs from the cache.
	Ensure that we do cleanup when closing last catalog regardless of
	the order that catalogs are closed.
	* src/catalog.cpp (catclose): Fix off-by-one error exposed with
	updated test.
	* tests/localization/22.locale.messages.mt.cpp: Updated to test
	multiple catalogs with multiple locales simultaneously.

Modified:
    stdcxx/branches/4.2.x/src/catalog.cpp
    stdcxx/branches/4.2.x/src/messages.cpp
    stdcxx/branches/4.2.x/tests/localization/22.locale.messages.mt.cpp

Modified: stdcxx/branches/4.2.x/src/catalog.cpp
URL: http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/src/catalog.cpp?rev=653946&r1=653945&r2=653946&view=diff
==============================================================================
--- stdcxx/branches/4.2.x/src/catalog.cpp (original)
+++ stdcxx/branches/4.2.x/src/catalog.cpp Tue May  6 15:51:31 2008
@@ -140,6 +140,8 @@
       __rw_catlist[j-1] = __rw_catlist[j];
     if (j < __rw_catlist.size())
       __rw_catlist[j] = 0;
+    else
+      __rw_catlist[__rw_catlist.size () - 1] = 0;
     return 0;
   }
   return -1;

Modified: stdcxx/branches/4.2.x/src/messages.cpp
URL: http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/src/messages.cpp?rev=653946&r1=653945&r2=653946&view=diff
==============================================================================
--- stdcxx/branches/4.2.x/src/messages.cpp (original)
+++ stdcxx/branches/4.2.x/src/messages.cpp Tue May  6 15:51:31 2008
@@ -70,6 +70,14 @@
     } loc;
 };
 
+struct __rw_open_cat_page
+{
+    static const size_t _C_size = 8;
+
+    __rw_open_cat_page* _C_next; // next page
+    __rw_open_cat_data _C_data [_C_size];
+};
+
 
 // manages a global, per-process repository of open catalogs according
 // to the following table:
@@ -90,21 +98,25 @@
 static __rw_open_cat_data*
 __rw_manage_cat_data (int &cat,  __rw_open_cat_data *pcat_data)
 {
-    // a per-process array of catalog data structs
-    static __rw_open_cat_data  catalog_buf [8];
-    static __rw_open_cat_data* catalogs = catalog_buf;
+    // a per-process array of pointers to catalog data structs
+    static __rw_open_cat_data* catalog_buf [__rw_open_cat_page::_C_size];
+    static __rw_open_cat_data** catalogs = 0;
+
+    // first page of a per-process list of pages of catalog data structs
+    static __rw_open_cat_page  catalog_page;
 
     static size_t n_catalogs      = 0;
     static size_t catalog_bufsize = sizeof catalog_buf / sizeof *catalog_buf;
     static size_t largest_cat     = 0;
-    static int    init            = 0;
 
- 
-    if (0 == init) {
+    if (!catalogs) {
+        
         for (size_t i = 0; i < catalog_bufsize; ++i) {
-            catalogs [i].catd = _RWSTD_BAD_CATD;
+            catalog_page._C_data [i].catd = _RWSTD_BAD_CATD;
+            catalog_buf [i] = &catalog_page._C_data [i];
         }
-        init = 1;
+
+        catalogs = catalog_buf;
     }
 
     if (-1 == cat) {
@@ -115,27 +127,40 @@
         if (pcat_data) {
              if (n_catalogs == catalog_bufsize) {
 
-                // reallocate buffer of facet pointers
-                __rw_open_cat_data* const tmp =
-                    new __rw_open_cat_data[n_catalogs * 2];
+                // allocate new page of catalog data
+                __rw_open_cat_page* const page =
+                    new __rw_open_cat_page;
+
+                // insert new page into singly-linked page list
+                page->_C_next = catalog_page._C_next;
+                catalog_page._C_next = page;
+
+                // initialize new page
+                for (size_t i = 0; i < __rw_open_cat_page::_C_size; ++i) {
+                    page->_C_data [i].catd = _RWSTD_BAD_CATD;
+                }
+
+                // rwallocate buffer of catalog data pointers
+                __rw_open_cat_data** const data =
+                    new __rw_open_cat_data* [n_catalogs + __rw_open_cat_page::_C_size];
 
-                memcpy (tmp, catalogs, n_catalogs * sizeof *tmp);
+                memcpy (data, catalogs, n_catalogs * sizeof *data);
                  
                 if (catalogs != catalog_buf)
                     delete[] catalogs;
 
-                catalogs         = tmp;
-                catalog_bufsize *= 2;
+                catalogs         = data;
+                catalog_bufsize += __rw_open_cat_page::_C_size;
 
-                for (size_t i = n_catalogs; i < catalog_bufsize; ++i) {
-                    catalogs [i].catd = _RWSTD_BAD_CATD;
+                for (size_t i = 0; i < __rw_open_cat_page::_C_size; ++i) {
+                    catalogs [n_catalogs + i] = &page->_C_data [i];
                 }
 
                 cat = int (n_catalogs);
-                memcpy (&catalogs [cat].loc, &pcat_data->loc,
-                        sizeof (_STD::locale));
 
-                catalogs [cat].catd = pcat_data->catd;
+                catalogs [cat]->catd = pcat_data->catd;
+                memcpy (&catalogs [cat]->loc, &pcat_data->loc,
+                        sizeof (_STD::locale));
 
                 if (size_t (cat) > largest_cat)
                     largest_cat = size_t (cat);
@@ -145,38 +170,42 @@
             else {
                 // find the first open slot and use it.
                 cat = 0;
-                while (catalogs [cat].catd != _RWSTD_BAD_CATD) {
+                while (catalogs [cat]->catd != _RWSTD_BAD_CATD) {
                     ++cat;
                 }
 
+                catalogs [cat]->catd = pcat_data->catd;
+                memcpy (&catalogs [cat]->loc, &pcat_data->loc,
+                        sizeof (_STD::locale));
+
                 if (size_t (cat) > largest_cat)
                     largest_cat = size_t (cat);
 
-                memcpy (&catalogs [cat].loc, &pcat_data->loc,
-                        sizeof (_STD::locale));
-
-                catalogs [cat].catd = pcat_data->catd;
                 ++n_catalogs;
             }
         }
     }
     else {
+
         if (0 == pcat_data) {
             // find struct and return it
             if (size_t (cat) < catalog_bufsize)
-                return catalogs + cat;
+                return catalogs [cat];
 
             return 0;
         }
 
         // initialize the struct to an invalid state
         --n_catalogs;
-        catalogs [cat].catd = _RWSTD_BAD_CATD;
+        catalogs [cat]->catd = _RWSTD_BAD_CATD;
+
         if (size_t (cat) == largest_cat) {
 
             // find the next smallest valid slot
+            largest_cat = 0;
+
             for (int i = cat; i >= 0; --i) {
-                if (catalogs [i].catd != _RWSTD_BAD_CATD) {
+                if (catalogs [i]->catd != _RWSTD_BAD_CATD) {
                     largest_cat = size_t (i);
                     break;
                 }
@@ -186,11 +215,9 @@
                 sizeof catalog_buf / sizeof *catalog_buf;
 
             if ((largest_cat < bufsize / 2) && (catalogs != catalog_buf)) {
-
                 // when there are no more open catalogs indexed beyond
-                // second half of the statically allocated repository, copy
-                // the open catalogs back into the statically allocated
-                // repository.
+                // second half of the static pointer repository, copy
+                // the open catalog pointers back into the repository.
 
                 catalog_bufsize = bufsize;
 
@@ -198,7 +225,19 @@
                         catalog_bufsize * sizeof (*catalogs));
 
                 delete[] catalogs;
+
                 catalogs = catalog_buf;
+
+                // remove all pages, they're not in use
+                while (catalog_page._C_next)
+                {
+                    // remove next page from page list
+                    __rw_open_cat_page* page = catalog_page._C_next;
+                    catalog_page._C_next = page->_C_next;
+
+                    // deallocate that page
+                    delete page;
+                }
             }
         }
     }

Modified: stdcxx/branches/4.2.x/tests/localization/22.locale.messages.mt.cpp
URL: http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/tests/localization/22.locale.messages.mt.cpp?rev=653946&r1=653945&r2=653946&view=diff
==============================================================================
--- stdcxx/branches/4.2.x/tests/localization/22.locale.messages.mt.cpp (original)
+++ stdcxx/branches/4.2.x/tests/localization/22.locale.messages.mt.cpp Tue May  6 15:51:31
2008
@@ -30,44 +30,73 @@
 
 #include <driver.h>      // for rw_test()
 #include <rw_locale.h>   // for rw_create_catalog()
-#include <rw_thread.h>
+#include <rw_thread.h>   // for rw_thread_pool()
+#include <rw_process.h>  // for rw_system()
+#include <file.h>        // for SHELL_RM_F
 #include <valcmp.h>      // for rw_strncmp ()
 
 #include <cstring>   // for strlen()
 #include <cstdio>    // for remove()
 
 // maximum number of threads allowed by the command line interface
+#define MAX_CATALOGS     32
 #define MAX_THREADS      32
 #define MAX_LOOPS    100000
 
+// deault number of catalogs
+int opt_ncatalogs = 11;
+
 // default number of threads (will be adjusted to the number
 // of processors/cores later)
-int rw_opt_nthreads = 1;
+int opt_nthreads = 1;
 
 // the number of times each thread should iterate (unless specified
 // otherwise on the command line)
-int rw_opt_nloops = 100000;
+int opt_nloops = 10000;
+
+#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
+
+// number of locales to use
+int opt_nlocales = MAX_THREADS;
+
+#else   // HP-UX in LP64 mode
 
-// locale for threads to share
-static const
-std::locale locale;
-
-// message catalog for threads to share
-static
-std::messages_base::catalog catalog;
+// work around a small cache size on HP-UX in LP64 mode
+// in LP64 mode (see STDCXX-812)
+int opt_nlocales = 9;
 
-static
-std::messages_base::catalog wcatalog;
+#endif   // HP-UX 32/64 bit mode
+
+// should all threads share the same set of locale objects instead
+// of creating their own?
+int opt_shared_locale;
 
 /**************************************************************************/
 
-#ifndef _WIN32
-#  define CAT_NAME "./rwstdmessages.cat"
-#  define MSG_NAME "rwstdmessages.msg"
-#else
-#  define CAT_NAME "rwstdmessages.dll"
-#  define MSG_NAME "rwstdmessages.rc"
-#endif
+// array of locale names to use for testing
+static const char*
+locales [MAX_THREADS];
+
+// number of locale names in the array
+static std::size_t
+nlocales;
+
+/**************************************************************************/
+
+//
+struct MyMessageData
+{
+    // name of the locale the data corresponds to
+    const char* locale_name_;
+
+    // optionally set to the named locale for threads to share
+    std::locale locale_;
+
+} my_message_data [MAX_THREADS];
+
+char my_catalog_names [64][MAX_CATALOGS];
+
+/**************************************************************************/
 
 #define MAX_SETS 5
 #define MAX_MESSAGES  5
@@ -123,38 +152,6 @@
     }
 };
 
-static std::string str_messages;
-
-/**************************************************************************/
-
-template <class T>
-void test_open_close (const std::locale& loc,
-                      const std::messages<T>& msgs,
-                      const std::string& name)
-{
-    std::messages_base::catalog cat =
-        (msgs.open) (name, loc);
-
-    RW_ASSERT (! (cat < 0));
-
-    (msgs.close) (cat);
-}
-
-template <class T>
-void test_get (const std::messages<T>& msgs,
-               const std::messages_base::catalog cat,
-               int set, int msgid,
-               const std::basic_string<T>& dflt)
-{
-    // the msg_id() thing seems like a bug to me. if anything, the user
-    // should never need to write or call msg_id().
-
-    const typename std::messages<T>::string_type res =
-        msgs.get (cat, set, msg_id (set, msgid), dflt);
-
-    RW_ASSERT (!rw_strncmp (messages [set-1][msgid-1], res.c_str ()));
-}
-
 /**************************************************************************/
 
 extern "C" {
@@ -165,50 +162,143 @@
 static void*
 thread_func (void*)
 {
-    const std::string name (CAT_NAME);
-
-    const std::messages<char>& nmsgs =
-        std::use_facet<std::messages<char> >(locale);
-
     const std::string ndflt ("\1\2\3\4");
 
+    struct {
+        std::messages_base::catalog cat;
+        std::locale loc;
+    } ncatalogs [4];
+
+    const unsigned n_ncatalogs = sizeof (ncatalogs) / sizeof (*ncatalogs);
+
+    // 22.2.7.1.2 says values less than 0 returned if catalog can't
+    // be opened, so we use -1 as a sentinel.
+    for (unsigned c = 0; c < n_ncatalogs; ++c)
+        ncatalogs [c].cat = -1;
+
 #ifndef _RWSTD_NO_WCHAR_T
-    const std::messages<wchar_t>& wmsgs =
-        std::use_facet<std::messages<wchar_t> >(locale);
 
     const std::wstring wdflt (L"\1\2\3\4");
-#endif // _RWSTD_NO_WCHAR_T
 
-    for (int i = 0; i != rw_opt_nloops; ++i) {
+    struct {
+        std::messages_base::catalog cat;
+        std::locale loc;
+    } wcatalogs [5];
 
-        int set   = 1 + i % MAX_SETS;
-        int msgid = 1 + i % MAX_MESSAGES;
+    const unsigned n_wcatalogs = sizeof (wcatalogs) / sizeof (*wcatalogs);
+
+    for (unsigned c = 0; c < n_wcatalogs; ++c)
+        wcatalogs [c].cat = -1;
+
+#endif   // _RWSTD_NO_WCHAR_T
+
+    ///////////////////////////////////////////////////////////////////////
+
+    for (int i = 0; i < opt_nloops; ++i) {
+
+        const MyMessageData& data = my_message_data [i % nlocales];
+
+        // construct a named locale, get a reference to the money_get
+        // facet from it and use it to format a random money value
+        const std::locale loc = 
+            opt_shared_locale ? data.locale_
+                              : std::locale (data.locale_name_);
+
+        const int set   = 1 + i % MAX_SETS;
+        const int msgid = 1 + i % MAX_MESSAGES;
 
         if (test_char) {
-            if (i & 1) {
-                test_get<char>(nmsgs, catalog, set, msgid, ndflt);
+            // exercise the narrow char specialization of the facet
+
+            const std::messages<char> &nm =
+                std::use_facet<std::messages<char> >(loc);
+
+            const unsigned cat_idx = i % n_ncatalogs;
+            if (! (ncatalogs [cat_idx].cat < 0)) {
+                (nm.close)(ncatalogs [cat_idx].cat);
             }
-            else {
-                test_open_close<char>(locale, nmsgs, name);
+
+            const unsigned name_idx = i % opt_ncatalogs;
+
+            const std::messages_base::catalog cat = 
+                (nm.open)(my_catalog_names [name_idx], loc);
+
+            ncatalogs [cat_idx].cat = cat;
+            ncatalogs [cat_idx].loc = loc;
+
+            if (i & 1) {
+
+                // get a message from the catalog every odd iteration
+                const std::messages<char>::string_type res =
+                        nm.get (cat, set, msg_id (set, msgid), ndflt);
+
             }
         }
 
+#ifndef _RWSTD_NO_WCHAR_T
+
         if (test_wchar) {
+            // exercise the wide char specialization of the facet
 
-#ifndef _RWSTD_NO_WCHAR_T
+            const std::messages<wchar_t> &wm =
+                std::use_facet<std::messages<wchar_t> >(loc);
 
-            if (i & 1) {
-                test_get<wchar_t>(wmsgs, wcatalog, set, msgid, wdflt);
+            const unsigned cat_idx = i % n_wcatalogs;
+            if (! (wcatalogs [cat_idx].cat < 0)) {
+                (wm.close)(wcatalogs [cat_idx].cat);
             }
-            else {
-                test_open_close<wchar_t>(locale, wmsgs, name);
+
+            const unsigned name_idx = i % opt_ncatalogs;
+
+            const std::messages_base::catalog cat = 
+                (wm.open)(my_catalog_names [name_idx], loc);
+
+            RW_ASSERT (! (cat < 0));
+
+            wcatalogs [cat_idx].cat = cat;
+            wcatalogs [cat_idx].loc = loc;
+
+            if (! (i & 1)) {
+
+                // get a message from the catalog every even iteration
+                const std::messages<wchar_t>::string_type res =
+                        wm.get (cat, set, msg_id (set, msgid), wdflt);
+
             }
+        }
 
-#endif // _RWSTD_NO_WCHAR_T
+#endif   // _RWSTD_NO_WCHAR_T
+
+    }
 
+    ///////////////////////////////////////////////////////////////////////
+
+    // close any catalogs that are still open
+
+    for (unsigned c = 0; c < n_ncatalogs; ++c) {
+        if (! (ncatalogs [c].cat < 0)) {
+
+            const std::messages<char> &nm =
+                std::use_facet<std::messages<char> >(ncatalogs[c].loc);
+
+            (nm.close)(ncatalogs [c].cat);
         }
     }
 
+#ifndef _RWSTD_NO_WCHAR_T
+
+    for (unsigned c = 0; c < n_wcatalogs; ++c) {
+        if (! (wcatalogs [c].cat < 0)) {
+
+            const std::messages<wchar_t> &wm =
+                std::use_facet<std::messages<wchar_t> >(wcatalogs[c].loc);
+
+            (wm.close)(wcatalogs [c].cat);
+        }
+    }
+
+#endif   // _RWSTD_NO_WCHAR_T
+
     return 0;
 }
 
@@ -219,36 +309,96 @@
 static int
 run_test (int, char**)
 {
+    std::string catalog;
+
+    // initialize the catalog data
     for (int i = 0; i < MAX_SETS; ++i) {
-        for (int j = 0; j < MAX_MESSAGES; ++j)
-            str_messages.append (messages [i][j], std::strlen (messages [i][j]) + 1);
 
-        str_messages.append (1, '\0');
+        for (int j = 0; j < MAX_MESSAGES; ++j) {
+            catalog.append (messages [i][j],
+                            std::strlen (messages [i][j]) + 1);
+        }
+
+        catalog.append (1, '\0');
     }
 
-    // generate a message catalog
-    rw_create_catalog (MSG_NAME, str_messages.c_str ());
-    const std::string name (CAT_NAME);
+    ///////////////////////////////////////////////////////////////////////
 
-    const std::messages<char>& nmsgs =
-        std::use_facet<std::messages<char> >(locale);
+    // create the catalogs and initialize array of catalog names
+    for (int i = 0; i < opt_ncatalogs; ++i) {
 
-    catalog = (nmsgs.open) (name, locale);
+        char* msg_name = my_catalog_names [i];
 
-#ifndef _RWSTD_NO_WCHAR_T
-
-    const std::messages<wchar_t>& wmsgs =
-        std::use_facet<std::messages<wchar_t> >(locale);
+#ifndef _WIN32
+        std::sprintf (msg_name, "rwstdmessages_%d.msg", i);
+#else
+        std::sprintf (msg_name, "rwstdmessages_%d.rc", i);
+#endif
 
-    wcatalog = (wmsgs.open) (name, locale);
+        const int failed = rw_create_catalog (msg_name, catalog.c_str ());
+        rw_fatal (!failed, 0, __LINE__,
+                  "failed to create message catalog from %s",
+                  msg_name);
 
+#ifndef _WIN32
+        std::sprintf (msg_name, "./rwstdmessages_%d.cat", i);
+#else
+        std::sprintf (msg_name, "rwstdmessages_%d.dll", i);
 #endif
+    }
+
+    ///////////////////////////////////////////////////////////////////////
+
+    // find all installed locales for which setlocale (LC_ALL) succeeds
+    const char* const locale_list =
+        rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
+
+    const std::size_t maxinx = RW_COUNT_OF (locales);
+
+    for (const char* name = locale_list;
+         *name;
+         name += std::strlen (name) + 1) {
+
+        const std::size_t inx = nlocales;
+        locales [inx] = name;
+
+        // fill in the money and results for this locale
+        MyMessageData& data = my_message_data [inx];
+        data.locale_name_ = name;
+
+        try {
+            const std::locale loc (data.locale_name_);
+
+            const std::messages<char>& nm =
+                std::use_facet<std::messages<char> >(loc);
+
+#ifdef _RWSTD_NO_WCHAR_T
+
+            const std::messages<wchar_t>& nm =
+                std::use_facet<std::messages<wchar_t> >(loc);
+
+#endif // _RWSTD_NO_WCHAR_T
+
+            if (opt_shared_locale)
+                data.locale_ = loc;
+
+            nlocales += 1;
+
+        }
+        catch (...) {
+            rw_warn (!rw_opt_locales, 0, __LINE__,
+                     "unable to use locale(%#s)", name);
+        }
+
+        if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
+            break;
+    }
 
     rw_info (0, 0, 0,
              "testing std::messages<charT> with %d thread%{?}s%{;}, "
              "%d iteration%{?}s%{;} each",
-             rw_opt_nthreads, 1 != rw_opt_nthreads,
-             rw_opt_nloops, 1 != rw_opt_nloops);
+             opt_nthreads, 1 != opt_nthreads,
+             opt_nloops, 1 != opt_nloops);
 
     ///////////////////////////////////////////////////////////////////////
 
@@ -258,12 +408,12 @@
     rw_info (0, 0, 0, "exercising std::messages<char>");
 
     int result = 
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0,
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
                         thread_func, 0);
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     ///////////////////////////////////////////////////////////////////////
 
@@ -275,12 +425,12 @@
     rw_info (0, 0, 0, "exercising std::messages<wchar_t>");
 
     result = 
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0,
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
                         thread_func, 0);
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
     ///////////////////////////////////////////////////////////////////////
 
@@ -291,26 +441,18 @@
                       "std::messages<wchar_t>");
 
     result = 
-        rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0,
+        rw_thread_pool (0, std::size_t (opt_nthreads), 0,
                         thread_func, 0);
 
     rw_error (result == 0, 0, __LINE__,
               "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
-              rw_opt_nthreads, thread_func);
+              opt_nthreads, thread_func);
 
 #endif // _RWSTD_NO_WCHAR_T
 
     ///////////////////////////////////////////////////////////////////////
 
-    (nmsgs.close) (catalog);
-
-#ifndef _RWSTD_NO_WCHAR_T
-
-    (wmsgs.close) (wcatalog);
-    
-#endif // _RWSTD_NO_WCHAR_T
-
-    std::remove (CAT_NAME);
+    rw_system (SHELL_RM_F "rwstdmessages_*");
 
     return result;
 }
@@ -323,9 +465,9 @@
 
     // set nthreads to the greater of the number of processors
     // and 2 (for uniprocessor systems) by default
-    rw_opt_nthreads = rw_get_cpus ();
-    if (rw_opt_nthreads < 2)
-        rw_opt_nthreads = 2;
+    opt_nthreads = rw_get_cpus ();
+    if (opt_nthreads < 2)
+        opt_nthreads = 2;
 
 #endif   // _RWSTD_REENTRANT
 
@@ -333,8 +475,11 @@
                     "lib.locale.messages",
                     "thread safety", run_test,
                     "|-nloops#0 "        // must be non-negative
+                    "|-ncatalogs#0-* "   // must be non-negative
                     "|-nthreads#0-* ",    // must be in [0, MAX_THREADS]
-                    &rw_opt_nloops,
+                    &opt_nloops,
+                    int (MAX_CATALOGS),
+                    &opt_ncatalogs,
                     int (MAX_THREADS),
-                    &rw_opt_nthreads);
+                    &opt_nthreads);
 }



Mime
View raw message