Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.numpunct.mt.cpp
Go to the documentation of this file.
1
29#include <locale> // for locale, numpunct
30
31#include <clocale> // for lconv, localeconv()
32#include <cstdlib> // for mbstowcs()
33#include <cstring> // for size_t, strcpy()
34
35#include <rw_locale.h>
36#include <rw_thread.h>
37#include <rw_driver.h>
38#include <rw_valcmp.h>
39
40
41// maximum number of threads allowed by the command line interface
42#define MAX_THREADS 32
43
44// default number of threads (will be adjusted to the number
45// of processors/cores later)
47
48// the number of times each thread should iterate (unless specified
49// otherwise on the command line)
50int opt_nloops = 200000;
51
52#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
53
54// number of locales to use
56
57#else // HP-UX in LP64 mode
58
59// work around an inefficiency (small cache size?) on HP-UX
60// in LP64 mode (see STDCXX-812)
61int opt_nlocales = 10;
62
63#endif // HP-UX 32/64 bit mode
64
65// should all threads share the same set of locale objects instead
66// of creating their own?
68
69// default timeout used by each threaded section of this test
70int opt_timeout = 60;
71
72
74// array of locale names to use for testing
75static const char*
77
78// number of locale names in the array
79static std::size_t
81
82
85{
86 const char* locale_name_;
87 std::locale locale_;
88
89 std::string grouping_;
90
93 std::string truename_;
94 std::string falsename_;
95
96#ifndef _RWSTD_NO_WCHAR_T
97
100 std::wstring wtruename_;
101 std::wstring wfalsename_;
102
103#endif // _RWSTD_NO_WCHAR_T
104
106
107
108extern "C" {
109
110bool test_char; // exercise num_put<char>
111bool test_wchar; // exercise num_put<wchar_t>
112
113
114static void*
115thread_func (void*)
116{
117 for (int i = 0; i != opt_nloops; ++i) {
118
120 break;
121
122 const std::size_t inx = std::size_t (i) % nlocales;
123
125
126 // construct a named locale
127 const std::locale loc =
129 : std::locale (data.locale_name_);
130
131 if (test_char) {
132 // exercise the narrow char specialization of the facet
133
134 const std::numpunct<char> &np =
135 std::use_facet<std::numpunct<char> >(loc);
136
137 const char dp = np.decimal_point ();
138 const char ts = np.thousands_sep ();
139 const std::string grp = np.grouping ();
140 const std::string tn = np.truename ();
141 const std::string fn = np.falsename ();
142
143 RW_ASSERT (dp == data.decimal_point_);
144 RW_ASSERT (ts == data.thousands_sep_);
145 RW_ASSERT (0 == rw_strncmp (grp.c_str (),
146 data.grouping_.c_str ()));
147 RW_ASSERT (0 == rw_strncmp (tn.c_str (),
148 data.truename_.c_str ()));
149 RW_ASSERT (0 == rw_strncmp (fn.c_str (),
150 data.falsename_.c_str ()));
151 }
152
153 // both specializations may be tested at the same time
154
155 if (test_wchar) {
156 // exercise the wide char specialization of the facet
157
158#ifndef _RWSTD_NO_WCHAR_T
159
160 const std::numpunct<wchar_t> &wp =
161 std::use_facet<std::numpunct<wchar_t> >(loc);
162
163 const wchar_t dp = wp.decimal_point ();
164 const wchar_t ts = wp.thousands_sep ();
165 const std::string grp = wp.grouping ();
166 const std::wstring tn = wp.truename ();
167 const std::wstring fn = wp.falsename ();
168
169 RW_ASSERT (dp == data.wdecimal_point_);
170 RW_ASSERT (ts == data.wthousands_sep_);
171 RW_ASSERT (0 == rw_strncmp (grp.c_str (),
172 data.grouping_.c_str ()));
173 RW_ASSERT (0 == rw_strncmp (tn.c_str (),
174 data.wtruename_.c_str ()));
175 RW_ASSERT (0 == rw_strncmp (fn.c_str (),
176 data.wfalsename_.c_str ()));
177
178#endif // _RWSTD_NO_WCHAR_T
179
180 }
181 }
182
183 return 0;
184}
185
186} // extern "C"
187
188
190static int
191run_test (int, char**)
192{
193 // find all installed locales for which setlocale(LC_ALL) succeeds
194 const char* const locale_list =
195 rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
196
197 const std::size_t maxinx = sizeof punct_data / sizeof *punct_data;
198
199 // iterate over locales, initializing a global punct_data array
200 for (const char *name = locale_list;
201 *name;
202 name += std::strlen (name) +1) {
203
204 const std::size_t inx = nlocales;
205 locales [inx] = name;
206
208
209 try {
210 std::locale loc(name);
211 data.locale_name_ = name;
212
213 const std::numpunct<char> &np =
214 std::use_facet<std::numpunct<char> >(loc);
215
216 data.grouping_ = np.grouping ();
217
218 data.decimal_point_ = np.decimal_point ();
219 data.thousands_sep_ = np.thousands_sep ();
220
221 data.truename_ = np.truename ();
222 data.falsename_ = np.falsename ();
223
224#ifndef _RWSTD_NO_WCHAR_T
225
226 const std::numpunct<wchar_t> &wp =
227 std::use_facet<std::numpunct<wchar_t> >(loc);
228
229 data.wdecimal_point_ = wp.decimal_point ();
230 data.wthousands_sep_ = wp.thousands_sep ();
231
232 data.wtruename_ = wp.truename ();
233 data.wfalsename_ = wp.falsename ();
234
235#endif
236
238 data.locale_ = loc;
239
240 nlocales += 1;
241 }
242 catch (...) {
243 rw_warn (!rw_opt_locales, 0, __LINE__,
244 "failed to create locale(%#s)", name);
245 }
246
247 if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
248 break;
249 }
250
251 // avoid divide by zero in thread if there are no locales to test
252 rw_fatal (nlocales != 0, 0, __LINE__,
253 "failed to create one or more usable locales!");
254
255 rw_info (0, 0, 0,
256 "testing std::numpunct<charT> with %d thread%{?}s%{;}, "
257 "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
260 nlocales, int (nlocales), "%#s", locales);
261
262 rw_info (0, 0, 0, "exercising std::numpunct<char>");
263
264 test_char = true;
265 test_wchar = false;
266
267 // create and start a pool of threads and wait for them to finish
268 int result =
269 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
270 thread_func, 0, std::size_t (opt_timeout));
271
272 rw_error (result == 0, 0, __LINE__,
273 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
274 opt_nthreads, thread_func);
275
276#ifndef _RWSTD_NO_WCHAR_T
277
278 rw_info (0, 0, 0, "exercising std::numpunct<wchar_t>");
279
280 test_char = false;
281 test_wchar = true;
282
283 // start a pool of threads to exercise the thread safety
284 // of the wchar_t specialization
285 result =
286 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
287 thread_func, 0, std::size_t (opt_timeout));
288
289 rw_error (result == 0, 0, __LINE__,
290 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
291 opt_nthreads, thread_func);
292
293 // exercise both the char and the wchar_t specializations
294 // at the same time
295
296 rw_info (0, 0, 0,
297 "exercising both std::numpunct<char> and std::numpunct<wchar_t>");
298
299 test_char = true;
300 test_wchar = true;
301
302 // start a pool of threads to exercise wstring thread safety
303 result =
304 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
305 thread_func, 0, std::size_t (opt_timeout));
306
307 rw_error (result == 0, 0, __LINE__,
308 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
309 opt_nthreads, thread_func);
310
311#endif // _RWSTD_NO_WCHAR_T
312
313 return result;
314}
315
316
318int main (int argc, char *argv[])
319{
320#ifdef _RWSTD_REENTRANT
321
322 // set nthreads to the greater of the number of processors
323 // and 2 (for uniprocessor systems) by default
325 if (opt_nthreads < 2)
326 opt_nthreads = 2;
327
328#endif // _RWSTD_REENTRANT
329
330 return rw_test (argc, argv, __FILE__,
331 "lib.locale.numpunct",
332 "thread safety", run_test,
333 "|-soft-timeout#0 " // must be non-negative
334 "|-nloops#0 " // must be non-negative
335 "|-nthreads#0-* " // must be in [0, MAX_THREADS]
336 "|-nlocales#0 " // arg must be non-negative
337 "|-locales= " // must be provided
338 "|-shared-locale# ",
340 &opt_nloops,
341 int (MAX_THREADS),
346}
#define i
Definition 17.names.cpp:126
#define loc
Definition 17.names.cpp:492
#define inx
Definition 17.names.cpp:484
volatile int result
const char *const data[]
const char * locale_list
int opt_timeout
struct NumPunctData punct_data[MAX_THREADS]
int opt_shared_locale
int opt_nlocales
#define MAX_THREADS
bool test_wchar
int opt_nthreads
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
const unsigned nlocales
const struct @19 locales[]
const char * name
Definition codecvt1.cpp:72
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_fatal(int expr, const char *filename, int line, const char *fmtspec,...)
Definition driver.cpp:1596
_TEST_EXPORT int rw_error(int, const char *, int, const char *,...)
Definition driver.cpp:1613
_TEST_EXPORT int rw_warn(int, const char *, int, const char *,...)
Definition driver.cpp:1647
_TEST_EXPORT int rw_opt_setlocales(int, char *[])
Definition locale.cpp:866
_TEST_EXPORT const char *const & rw_opt_locales
Definition locale.cpp:862
_TEST_EXPORT char * rw_locales(int=_UNUSED_CAT, const char *=0, bool=true)
Definition locale.cpp:368
#define RW_ASSERT(expr)
_TEST_EXPORT int rw_thread_pool(rw_thread_t *, _RWSTD_SIZE_T, rw_thread_attr_t *, rw_thread_proc *, void **, _RWSTD_SIZE_T=0)
_TEST_EXPORT int rw_get_cpus()
Definition thread.cpp:402
_TEST_EXPORT int rw_thread_pool_timeout_expired()
Definition thread.cpp:65
_TEST_EXPORT int rw_strncmp(const char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, int=CMP_NULTERM)
const char * locale_name_