Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.money.get.mt.cpp
Go to the documentation of this file.
1
29#include <ios> // for ios
30#include <iterator> // for ostreambuf_iterator
31#include <locale> // for locale, money_get
32
33#include <cstring> // for strlen()
34
35#include <rw_locale.h>
36#include <rw_thread.h>
37#include <rw_driver.h>
38#include <rw_valcmp.h> // for rw_strncmp ()
39
40
41// maximum number of threads allowed by the command line interface
42#define MAX_THREADS 32
43#define MAX_LOOPS 100000
44
45// the number of times each thread should iterate (unless specified
46// otherwise on the command line)
47int opt_nloops = 100000;
48
49// default number of threads (will be adjusted to the number
50// of processors/cores later)
52
53#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
54
55// number of locales to use
57
58#else // HP-UX in LP64 mode
59
60// work around a small cache size on HP-UX in LP64 mode
61// in LP64 mode (see STDCXX-812)
62int opt_nlocales = 9;
63
64#endif // HP-UX 32/64 bit mode
65
66// should all threads share the same set of locale objects instead
67// of creating their own?
69
70// default timeout used by each threaded section of this test
71int opt_timeout = 60;
72
73
75// array of locale names to use for testing
76static const char*
78
79// number of locale names in the array
80static std::size_t
82
83
85//
87{
88 enum { BufferSize = 16 };
89
90 enum GetId {
94 };
95
96 // name of the locale the data corresponds to
97 const char* locale_name_;
98
99 // optionally set to the named locale for threads to share
100 std::locale locale_;
101
102 // international or domestic format flag
103 bool intl_;
104
105 //
106 long double units_;
107
108 // narrow locale specific representations of units_
110 std::string ncs_digits_;
111
112#ifndef _RWSTD_NO_WCHAR_T
113
114 // wide locale specific representations of units_
115 wchar_t wcs_ [BufferSize];
116 std::wstring wcs_digits_;
117
118#endif // _RWSTD_NO_WCHAR_T
119
121
122
123template <class charT, class Traits>
124struct MyIos: std::basic_ios<charT, Traits>
125{
126 MyIos () {
127 this->init (0);
128 }
129};
130
131
132template <class charT, class Traits>
133struct MyStreambuf: std::basic_streambuf<charT, Traits>
134{
135 typedef std::basic_streambuf<charT, Traits> Base;
136
138 : Base () {
139 }
140
141 void pubsetg (const charT *gbeg, std::streamsize n) {
142 this->setg (_RWSTD_CONST_CAST (charT*, gbeg),
143 _RWSTD_CONST_CAST (charT*, gbeg),
144 _RWSTD_CONST_CAST (charT*, gbeg) + n);
145 }
146
147 void pubsetp (charT *pbeg, std::streamsize n) {
148 this->setp (pbeg, pbeg + n);
149 }
150};
151
152
153extern "C" {
154
155bool test_char; // exercise money_get<char>
156bool test_wchar; // exercise money_get<wchar_t>
157
158
159static void*
160thread_func (void*)
161{
164 std::basic_string<char, std::char_traits<char> > str;
165 nio.rdbuf (&nsb);
166
167#ifndef _RWSTD_NO_WCHAR_T
170 std::basic_string<wchar_t, std::char_traits<wchar_t> > wstr;
171 wio.rdbuf (&wsb);
172#endif // _RWSTD_NO_WCHAR_T
173
174 std::ios_base::iostate state = std::ios_base::goodbit;
175
176#ifndef _RWSTD_NO_LONG_DOUBLE
177 long double ldbl = 0.;
178#endif // _RWSTD_NO_LONG_DOUBLE
179
180 for (int i = 0; i != opt_nloops; ++i) {
181
183 break;
184
185 // save the name of the locale
187
188 // construct a named locale, get a reference to the money_get
189 // facet from it and use it to format a random money value
190 const std::locale loc =
192 : std::locale (data.locale_name_);
193
194 if (test_char) {
195 // exercise the narrow char specialization of the facet
196
197 const std::money_get<char> &ng =
198 std::use_facet<std::money_get<char> >(loc);
199
200 nio.imbue (loc);
201 nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_));
202
203 if (i & 1) {
204 ng.get (std::istreambuf_iterator<char>(&nsb),
205 std::istreambuf_iterator<char>(),
206 data.intl_, nio, state, ldbl);
207 RW_ASSERT (! (state & std::ios_base::failbit));
208 RW_ASSERT (! rw_ldblcmp (ldbl, data.units_));
209 }
210 else {
211 ng.get (std::istreambuf_iterator<char>(&nsb),
212 std::istreambuf_iterator<char>(),
213 data.intl_, nio, state, str);
214 RW_ASSERT (! (state & std::ios_base::failbit));
215 RW_ASSERT (! rw_strncmp (str.c_str (),
216 data.ncs_digits_.c_str ()));
217 }
218 }
219
220 // both specializations may be tested at the same time
221
222 if (test_wchar) {
223 // exercise the wide char specialization of the facet
224
225#ifndef _RWSTD_NO_WCHAR_T
226
227 const std::money_get<wchar_t> &wg =
228 std::use_facet<std::money_get<wchar_t> >(loc);
229
230 wio.imbue (loc);
231 wsb.pubsetg (data.wcs_, RW_COUNT_OF (data.wcs_));
232
233 if (i & 1) {
234 wg.get (std::istreambuf_iterator<wchar_t>(&wsb),
235 std::istreambuf_iterator<wchar_t>(),
236 data.intl_, wio, state, ldbl);
237 RW_ASSERT (! (state & std::ios_base::failbit));
238 RW_ASSERT (! rw_ldblcmp (ldbl, data.units_));
239 }
240 else {
241 wg.get (std::istreambuf_iterator<wchar_t>(&wsb),
242 std::istreambuf_iterator<wchar_t>(),
243 data.intl_, wio, state, wstr);
244 RW_ASSERT (! (state & std::ios_base::failbit));
245 RW_ASSERT (! rw_strncmp(wstr.c_str (),
246 data.wcs_digits_.c_str ()));
247 }
248
249#endif // _RWSTD_NO_WCHAR_T
250
251 }
252 }
253
254 return 0;
255}
256
257} // extern "C"
258
259
261static int
262run_test (int, char**)
263{
266 nio.rdbuf (&nsb);
267
268#ifndef _RWSTD_NO_WCHAR_T
271 wio.rdbuf (&wsb);
272#endif // _RWSTD_NO_WCHAR_T
273
274 // find all installed locales for which setlocale (LC_ALL) succeeds
275 const char* const locale_list =
276 rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
277
278 const std::size_t maxinx = RW_COUNT_OF (locales);
279
280 for (const char* name = locale_list;
281 *name;
282 name += std::strlen (name) + 1) {
283
284 const std::size_t inx = nlocales;
285 locales [inx] = name;
286
287 // fill in the money and results for this locale
290
291 try {
292 const std::locale loc (data.locale_name_);
293
294 // exercise domestic formats every other iteration
295 // and international formats the rest
296 data.intl_ = 0 == (inx & 5);
297
298 // initialize with random but valid values
299 long double units = 1.f + inx;
300
301 // exercise postive and negative values
302 if (inx & 1)
303 units += (units * 3.14159);
304 else
305 units -= (units * 2.71828);
306
307 // local scope
308 {
309 const std::money_put<char> &np =
310 std::use_facet<std::money_put<char> >(loc);
311
312 const std::money_get<char> &ng =
313 std::use_facet<std::money_get<char> >(loc);
314
315 std::ios::iostate state = std::ios::goodbit;
316
317 nio.imbue (loc);
318
319 // write the value to buffer from long double
320 nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
321 *np.put (std::ostreambuf_iterator<char>(&nsb),
322 data.intl_, nio, ' ', units) = '\0';
323
324 rw_fatal (!nio.fail (), __FILE__, __LINE__,
325 "money_put<char>::put(...) "
326 "failed for locale(%#s)", data.locale_name_);
327
328 // read the value back so threads know what to expect
329 nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_));
330 ng.get (std::istreambuf_iterator<char>(&nsb),
331 std::istreambuf_iterator<char>(),
332 data.intl_, nio, state, data.units_);
333
334 // read back as string, again for threads
335 nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_));
336 ng.get (std::istreambuf_iterator<char>(&nsb),
337 std::istreambuf_iterator<char>(),
338 data.intl_, nio, state, data.ncs_digits_);
339
340 if (state & std::ios_base::failbit)
341 continue;
342 }
343
344#ifndef _RWSTD_NO_WCHAR_T
345
346 // local scope
347 {
348 const std::money_put<wchar_t> &wp =
349 std::use_facet<std::money_put<wchar_t> >(loc);
350
351 const std::money_get<wchar_t> &wg =
352 std::use_facet<std::money_get<wchar_t> >(loc);
353
354 std::ios::iostate state = std::ios::goodbit;
355
356 wio.imbue (loc);
357
358 // write the value to buffer from long double
359 wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
360 *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
361 data.intl_, wio, L' ', units) = L'\0';
362
363 rw_fatal (!nio.fail (), __FILE__, __LINE__,
364 "money_put<wchar_t>::put(...) "
365 "failed for locale(%#s)", data.locale_name_);
366
367 // read back as string, again for threads
368 wsb.pubsetg (data.wcs_, RW_COUNT_OF (data.wcs_));
369 wg.get (std::istreambuf_iterator<wchar_t>(&wsb),
370 std::istreambuf_iterator<wchar_t>(),
371 data.intl_, wio, state, data.wcs_digits_);
372
373 if (state & std::ios_base::failbit)
374 continue;
375 }
376
377#endif // _RWSTD_NO_WCHAR_T
378
380 data.locale_ = loc;
381
382 nlocales += 1;
383
384 }
385 catch (...) {
386 rw_warn (!rw_opt_locales, 0, __LINE__,
387 "failed to create locale(%#s)", name);
388 }
389
390 if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
391 break;
392 }
393
394 // avoid divide by zero in thread if there are no locales to test
395 rw_fatal (nlocales != 0, 0, __LINE__,
396 "failed to create one or more usable locales!");
397
398 rw_info (0, 0, 0,
399 "testing std::money_get<charT> with %d thread%{?}s%{;}, "
400 "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
403 nlocales, int (nlocales), "%#s", locales);
404
405 rw_info (0, 0, 0, "exercising std::money_get<char>");
406
407 test_char = true;
408 test_wchar = false;
409
410 // create and start a pool of threads and wait for them to finish
411 int result =
412 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
413 thread_func, 0, std::size_t (opt_timeout));
414
415 rw_error (result == 0, 0, __LINE__,
416 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
417 opt_nthreads, thread_func);
418
419#ifndef _RWSTD_NO_WCHAR_T
420
421 rw_info (0, 0, 0, "exercising std::money_get<wchar_t>");
422
423 test_char = false;
424 test_wchar = true;
425
426 // start a pool of threads to exercise wstring thread safety
427 result =
428 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
429 thread_func, 0, std::size_t (opt_timeout));
430
431 rw_error (result == 0, 0, __LINE__,
432 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
433 opt_nthreads, thread_func);
434
435 // exercise both the char and the wchar_t specializations
436 // at the same time
437
438 rw_info (0, 0, 0,
439 "exercising both std::money_get<char> "
440 "and std::money_get<wchar_t>");
441
442 test_char = true;
443 test_wchar = true;
444
445 // start a pool of threads to exercise wstring thread safety
446 result =
447 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
448 thread_func, 0, std::size_t (opt_timeout));
449
450 rw_error (result == 0, 0, __LINE__,
451 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
452 opt_nthreads, thread_func);
453
454#endif // _RWSTD_NO_WCHAR_T
455
456 return result;
457}
458
459
461int main (int argc, char *argv[])
462{
463#ifdef _RWSTD_REENTRANT
464
465 // set nthreads to the greater of the number of processors
466 // and 2 (for uniprocessor systems) by default
468 if (opt_nthreads < 2)
469 opt_nthreads = 2;
470
471#endif // _RWSTD_REENTRANT
472
473 return rw_test (argc, argv, __FILE__,
474 "lib.locale.money.get",
475 "thread safety", run_test,
476 "|-soft-timeout#0 " // must be non-negative
477 "|-nloops#0 " // must be non-negative
478 "|-nthreads#0-* " // must be in [0, MAX_THREADS]
479 "|-nlocales#0 " // arg must be non-negative
480 "|-locales= " // must be provided
481 "|-shared-locale# ",
483 &opt_nloops,
484 int (MAX_THREADS),
489}
#define i
Definition 17.names.cpp:126
#define loc
Definition 17.names.cpp:492
#define charT
Definition 17.names.cpp:456
#define n
Definition 17.names.cpp:130
#define inx
Definition 17.names.cpp:484
volatile int result
const char *const data[]
const char * locale_list
int opt_shared_locale
#define MAX_THREADS
struct MyMoneyData my_money_data[MAX_THREADS]
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
const unsigned nlocales
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
const struct @19 locales[]
const char * name
Definition codecvt1.cpp:72
std::mbstate_t init
Definition codecvt1.cpp:80
const char * str
Definition exec.cpp:170
_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)
#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
_TEST_EXPORT int rw_strncmp(const char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, int=CMP_NULTERM)
_TEST_EXPORT int rw_ldblcmp(long double x, long double y)
Definition valcmp.cpp:816
char ncs_[BufferSize]
wchar_t wcs_[BufferSize]
const char * locale_name_
void pubsetg(charT *beg, charT *cur, charT *end)
std::basic_streambuf< charT, Traits > Base
void pubsetp(charT *beg, charT *cur, charT *end)
void pubsetp(charT *pbeg, std::streamsize n)
void pubsetg(const charT *gbeg, std::streamsize n)