Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.messages.mt.cpp
Go to the documentation of this file.
1
29#include <locale>
30
31#include <rw_driver.h> // for rw_test()
32#include <rw_locale.h> // for rw_create_catalog()
33#include <rw_thread.h> // for rw_thread_pool()
34#include <rw_process.h> // for rw_system()
35#include <rw_file.h> // for SHELL_RM_F
36#include <rw_valcmp.h> // for rw_strncmp ()
37
38#include <cstring> // for strlen()
39#include <cstdio> // for remove()
40
41// maximum number of threads allowed by the command line interface
42#define MAX_CATALOGS 32
43#define MAX_THREADS 32
44#define MAX_LOOPS 100000
45
46// deault number of catalogs
48
49// default number of threads (will be adjusted to the number
50// of processors/cores later)
52
53// the number of times each thread should iterate (unless specified
54// otherwise on the command line)
55int opt_nloops = 10000;
56
57#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
58
59// number of locales to use
61
62#else // HP-UX in LP64 mode
63
64// work around a small cache size on HP-UX in LP64 mode
65// in LP64 mode (see STDCXX-812)
66int opt_nlocales = 9;
67
68#endif // HP-UX 32/64 bit mode
69
70// should all threads share the same set of locale objects instead
71// of creating their own?
73
74// default timeout used by each threaded section of this test
75int opt_timeout = 60;
76
77
79// array of locale names to use for testing
80static const char*
82
83// number of locale names in the array
84static std::size_t
86
87
89//
91{
92 // name of the locale the data corresponds to
93 const char* locale_name_;
94
95 // optionally set to the named locale for threads to share
96 std::locale locale_;
97
99
101
102
104#define MAX_SETS 5
105#define MAX_MESSAGES 5
106
107
108int msg_id (int set, int id)
109{
110#ifdef _WIN32
111
112 return (set - 1) * 5 + id;
113
114#else
115
116 _RWSTD_UNUSED (set);
117 return id;
118
119#endif
120}
121
122
124static const char* const
125messages [MAX_SETS][MAX_MESSAGES] = {
126 { "First set, first message",
127 "First set, second message",
128 "First set, third message",
129 "First set, fourth message",
130 "First set, fifth message"
131 },
132 { "Second set, first message",
133 "Second set, second message",
134 "Second set, third message",
135 "Second set, fourth message",
136 "Second set, fifth message"
137 },
138 { "Third set, first message",
139 "Third set, second message",
140 "Third set, third message",
141 "Third set, fourth message",
142 "Third set, fifth message"
143 },
144 { "Fourth set, first message",
145 "Fourth set, second message",
146 "Fourth set, third message",
147 "Fourth set, fourth message",
148 "Fourth set, fifth message"
149 },
150 { "Fifth set, first message",
151 "Fifth set, second message",
152 "Fifth set, third message",
153 "Fifth set, fourth message",
154 "Fifth set, fifth message"
155 }
156};
157
158
160extern "C" {
161
162bool test_char; // exercise messages<char>
163bool test_wchar; // exercise messages<wchar_t>
164
165static void*
166thread_func (void*)
167{
168 const std::string ndflt ("\1\2\3\4");
169
170 struct {
171 std::messages_base::catalog cat;
172 std::locale loc;
173 } ncatalogs [4];
174
175 const unsigned n_ncatalogs = sizeof (ncatalogs) / sizeof (*ncatalogs);
176
177 // 22.2.7.1.2 says values less than 0 returned if catalog can't
178 // be opened, so we use -1 as a sentinel.
179 for (unsigned c = 0; c < n_ncatalogs; ++c)
180 ncatalogs [c].cat = -1;
181
182#ifndef _RWSTD_NO_WCHAR_T
183
184 const std::wstring wdflt (L"\1\2\3\4");
185
186 struct {
187 std::messages_base::catalog cat;
188 std::locale loc;
189 } wcatalogs [5];
190
191 const unsigned n_wcatalogs = sizeof (wcatalogs) / sizeof (*wcatalogs);
192
193 for (unsigned c = 0; c < n_wcatalogs; ++c)
194 wcatalogs [c].cat = -1;
195
196#endif // _RWSTD_NO_WCHAR_T
197
199
200 for (int i = 0; i < opt_nloops; ++i) {
201
203 break;
204
206
207 // construct a named locale, get a reference to the money_get
208 // facet from it and use it to format a random money value
209 const std::locale loc =
211 : std::locale (data.locale_name_);
212
213 const int set = 1 + i % MAX_SETS;
214 const int msgid = 1 + i % MAX_MESSAGES;
215
216 if (test_char) {
217 // exercise the narrow char specialization of the facet
218
219 const std::messages<char> &nm =
220 std::use_facet<std::messages<char> >(loc);
221
222 const unsigned cat_idx = i % n_ncatalogs;
223 if (! (ncatalogs [cat_idx].cat < 0)) {
224 (nm.close)(ncatalogs [cat_idx].cat);
225 }
226
227 const unsigned name_idx = i % opt_ncatalogs;
228
229 const std::messages_base::catalog cat =
230 (nm.open)(my_catalog_names [name_idx], loc);
231
232 ncatalogs [cat_idx].cat = cat;
233 ncatalogs [cat_idx].loc = loc;
234
235 if (i & 1) {
236
237 // get a message from the catalog every odd iteration
238 const std::messages<char>::string_type res =
239 nm.get (cat, set, msg_id (set, msgid), ndflt);
240
241 }
242 }
243
244#ifndef _RWSTD_NO_WCHAR_T
245
246 if (test_wchar) {
247 // exercise the wide char specialization of the facet
248
249 const std::messages<wchar_t> &wm =
250 std::use_facet<std::messages<wchar_t> >(loc);
251
252 const unsigned cat_idx = i % n_wcatalogs;
253 if (! (wcatalogs [cat_idx].cat < 0)) {
254 (wm.close)(wcatalogs [cat_idx].cat);
255 }
256
257 const unsigned name_idx = i % opt_ncatalogs;
258
259 const std::messages_base::catalog cat =
260 (wm.open)(my_catalog_names [name_idx], loc);
261
262 RW_ASSERT (! (cat < 0));
263
264 wcatalogs [cat_idx].cat = cat;
265 wcatalogs [cat_idx].loc = loc;
266
267 if (! (i & 1)) {
268
269 // get a message from the catalog every even iteration
270 const std::messages<wchar_t>::string_type res =
271 wm.get (cat, set, msg_id (set, msgid), wdflt);
272
273 }
274 }
275
276#endif // _RWSTD_NO_WCHAR_T
277
278 }
279
281
282 // close any catalogs that are still open
283
284 for (unsigned c = 0; c < n_ncatalogs; ++c) {
285 if (! (ncatalogs [c].cat < 0)) {
286
287 const std::messages<char> &nm =
288 std::use_facet<std::messages<char> >(ncatalogs[c].loc);
289
290 (nm.close)(ncatalogs [c].cat);
291 }
292 }
293
294#ifndef _RWSTD_NO_WCHAR_T
295
296 for (unsigned c = 0; c < n_wcatalogs; ++c) {
297 if (! (wcatalogs [c].cat < 0)) {
298
299 const std::messages<wchar_t> &wm =
300 std::use_facet<std::messages<wchar_t> >(wcatalogs[c].loc);
301
302 (wm.close)(wcatalogs [c].cat);
303 }
304 }
305
306#endif // _RWSTD_NO_WCHAR_T
307
308 return 0;
309}
310
311} // extern "C"
312
313
315static int
316run_test (int, char**)
317{
318 std::string catalog;
319
320 // initialize the catalog data
321 for (int i = 0; i < MAX_SETS; ++i) {
322
323 for (int j = 0; j < MAX_MESSAGES; ++j) {
324 catalog.append (messages [i][j],
325 std::strlen (messages [i][j]) + 1);
326 }
327
328 catalog.append (1, '\0');
329 }
330
332
333 // create the catalogs and initialize array of catalog names
334 for (int i = 0; i < opt_ncatalogs; ++i) {
335
336 char* msg_name = my_catalog_names [i];
337
338#ifndef _WIN32
339 std::sprintf (msg_name, "rwstdmessages_%d.msg", i);
340#else
341 std::sprintf (msg_name, "rwstdmessages_%d.rc", i);
342#endif
343
344 const int failed = rw_create_catalog (msg_name, catalog.c_str ());
345 rw_fatal (!failed, 0, __LINE__,
346 "failed to create message catalog from %s",
347 msg_name);
348
349#ifndef _WIN32
350 std::sprintf (msg_name, "./rwstdmessages_%d.cat", i);
351#else
352 std::sprintf (msg_name, "rwstdmessages_%d.dll", i);
353#endif
354 }
355
357
358 // find all installed locales for which setlocale (LC_ALL) succeeds
359 const char* const locale_list =
360 rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
361
362 const std::size_t maxinx = RW_COUNT_OF (locales);
363
364 for (const char* name = locale_list;
365 *name;
366 name += std::strlen (name) + 1) {
367
368 const std::size_t inx = nlocales;
369 locales [inx] = name;
370
371 // fill in the money and results for this locale
374
375 try {
376 const std::locale loc (data.locale_name_);
377
378 {
379 const std::messages<char>& nm =
380 std::use_facet<std::messages<char> >(loc);
381
382 _RWSTD_UNUSED (nm);
383 }
384
385#ifndef _RWSTD_NO_WCHAR_T
386
387 {
388 const std::messages<wchar_t>& wm =
389 std::use_facet<std::messages<wchar_t> >(loc);
390
391 _RWSTD_UNUSED (wm);
392 }
393
394#endif // _RWSTD_NO_WCHAR_T
395
397 data.locale_ = loc;
398
399 nlocales += 1;
400
401 }
402 catch (...) {
403 rw_warn (!rw_opt_locales, 0, __LINE__,
404 "unable to use locale(%#s)", name);
405 }
406
407 if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
408 break;
409 }
410
411 rw_info (0, 0, 0,
412 "testing std::messages<charT> with %d thread%{?}s%{;}, "
413 "%d iteration%{?}s%{;} each",
415 opt_nloops, 1 != opt_nloops);
416
418
419 test_char = true;
420 test_wchar = false;
421
422 rw_info (0, 0, 0, "exercising std::messages<char>");
423
424 int result =
425 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
426 thread_func, 0, std::size_t (opt_timeout));
427
428 rw_error (result == 0, 0, __LINE__,
429 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
430 opt_nthreads, thread_func);
431
433
434#ifndef _RWSTD_NO_WCHAR_T
435
436 test_char = false;
437 test_wchar = true;
438
439 rw_info (0, 0, 0, "exercising std::messages<wchar_t>");
440
441 result =
442 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
443 thread_func, 0, std::size_t (opt_timeout));
444
445 rw_error (result == 0, 0, __LINE__,
446 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
447 opt_nthreads, thread_func);
448
450
451 test_char = true;
452 test_wchar = true;
453
454 rw_info (0, 0, 0, "exercising std::messages<char> and "
455 "std::messages<wchar_t>");
456
457 result =
458 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
459 thread_func, 0, std::size_t (opt_timeout));
460
461 rw_error (result == 0, 0, __LINE__,
462 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
463 opt_nthreads, thread_func);
464
465#endif // _RWSTD_NO_WCHAR_T
466
468
469 rw_system (SHELL_RM_F "rwstdmessages_*");
470
471 return result;
472}
473
474
476int main (int argc, char *argv[])
477{
478#ifdef _RWSTD_REENTRANT
479
480 // set nthreads to the greater of the number of processors
481 // and 2 (for uniprocessor systems) by default
483 if (opt_nthreads < 2)
484 opt_nthreads = 2;
485
486#endif // _RWSTD_REENTRANT
487
488 return rw_test (argc, argv, __FILE__,
489 "lib.locale.messages",
490 "thread safety", run_test,
491 "|-soft-timeout#0 " // must be non-negative
492 "|-nloops#0 " // must be non-negative
493 "|-ncatalogs#0-* " // must be non-negative
494 "|-nthreads#0-* ", // must be in [0, MAX_THREADS]
496 &opt_nloops,
497 int (MAX_CATALOGS),
499 int (MAX_THREADS),
500 &opt_nthreads);
501}
#define i
Definition 17.names.cpp:126
#define res
Definition 17.names.cpp:531
#define loc
Definition 17.names.cpp:492
#define j
Definition 17.names.cpp:127
#define c
Definition 17.names.cpp:111
#define inx
Definition 17.names.cpp:484
volatile int result
const char *const data[]
const char * locale_list
int opt_ncatalogs
int opt_timeout
#define MAX_MESSAGES
int msg_id(int set, int id)
int opt_shared_locale
int opt_nlocales
struct MyMessageData my_message_data[MAX_THREADS]
#define MAX_THREADS
#define MAX_CATALOGS
char my_catalog_names[64][MAX_CATALOGS]
bool test_wchar
#define MAX_SETS
int opt_nthreads
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
const unsigned nlocales
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
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
#define SHELL_RM_F
Definition rw_file.h:57
_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
_TEST_EXPORT int rw_create_catalog(const char *, const char *)
Definition locale.cpp:920
_TEST_EXPORT int rw_system(const char *,...)
Definition process.cpp:328
#define RW_ASSERT(expr)
#define RW_COUNT_OF(x)
_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