Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.num.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, num_get
32
33#include <cstring> // for strlen()
34
35#include <rw_locale.h>
36#include <rw_thread.h> // for rw_get_processors (), rw_thread_pool()
37#include <rw_driver.h>
38#include <rw_valcmp.h>
39
40#define MAX_THREADS 32
41#define MAX_LOOPS 100000
42
43// default number of threads (will be adjusted to the number
44// of processors/cores later)
46
47// the number of times each thread should iterate
49
50#if !defined (_RWSTD_OS_HP_UX) || defined (_ILP32)
51
52// number of locales to use
54
55#else // HP-UX in LP64 mode
56
57// work around an inefficiency (small cache size?) on HP-UX
58// in LP64 mode (see STDCXX-812)
59int opt_nlocales = 10;
60
61#endif // HP-UX 32/64 bit mode
62
63// should all threads share the same set of locale objects instead
64// of creating their own?
66
67// default timeout used by each threaded section of this test
68int opt_timeout = 60;
69
70
72// array of locale names to use for testing
73static const char*
75
76// number of locale names in the array
77static std::size_t
79
80
81struct MyNumData {
82
83 enum { BufferSize = 32 };
84
85 enum PutId {
89
90#ifndef _RWSTD_NO_LONG_LONG
91
94
95#endif // _RWSTD_NO_LONG_LONG
96
98
99#ifndef _RWSTD_NO_LONG_DOUBLE
100
102
103#endif // _RWSTD_NO_LONG_DOUBLE
104
106 put_max
107 };
108
109 // name of the locale the data corresponds to
110 const char* locale_name_;
111
112 // optionally set to the named locale for threads to share
113 std::locale locale_;
114
115 // the value that we will be formatting
116 double value_;
117
118 // the type of the data we get
120
121 // holds the narrow/wide character representation of value_ and
122 // the number of used 'charT' in each buffer.
124 std::size_t nlen_; // number of valid characters in buffer
125
126#ifndef _RWSTD_NO_WCHAR_T
127
128 wchar_t wcs_ [BufferSize];
129 std::size_t wlen_; // number of valid characters in buffer
130
131#endif // _RWSTD_NO_WCHAR_T
132
134
135
137template <class charT, class Traits>
138struct MyIos: std::basic_ios<charT, Traits>
139{
140 MyIos () {
141 this->init (0);
142 }
143};
144
145template <class charT, class Traits>
146struct MyStreambuf: std::basic_streambuf<charT, Traits>
147{
148 typedef std::basic_streambuf<charT, Traits> Base;
149
151 : Base () {
152 }
153
154 void pubsetg (const charT *gbeg, std::streamsize n) {
155 this->setg (_RWSTD_CONST_CAST (charT*, gbeg),
156 _RWSTD_CONST_CAST (charT*, gbeg),
157 _RWSTD_CONST_CAST (charT*, gbeg) + n);
158 }
159
160 void pubsetp (charT *pbeg, std::streamsize n) {
161 this->setp (pbeg, pbeg + n);
162 }
163};
164
165template <class charT, class Traits>
166void
168 const std::num_put<charT> &np,
169 const std::ostreambuf_iterator<charT, Traits> &iter,
170 std::basic_ios<charT, Traits> &io,
171 charT fill,
172 charT term)
173{
174 switch (data.type_) {
176 *np.put (iter, io, fill,
177 data.value_ < 1.f) = term;
178 break;
180 *np.put (iter, io, fill,
181 (long)data.value_) = term;
182 break;
184 *np.put (iter, io, fill,
185 (unsigned long)data.value_) = term;
186 break;
187
188#ifndef _RWSTD_NO_LONG_LONG
189
191 *np.put (iter, io, fill,
192 (_RWSTD_LONG_LONG)data.value_) = term;
193 break;
195 *np.put (iter, io, fill,
196 (unsigned _RWSTD_LONG_LONG)data.value_) = term;
197 break;
198
199#endif // _RWSTD_NO_LONG_LONG
200
202 *np.put (iter, io, fill,
203 (double)data.value_) = term;
204
205 break;
206
207#ifndef _RWSTD_NO_LONG_DOUBLE
208
210 *np.put (iter, io, fill,
211 (long double)data.value_) = term;
212 break;
213
214#endif // _RWSTD_NO_LONG_DOUBLE
215
217 *np.put (iter, io, fill,
218 (const void*)&data.value_) = term;
219 break;
220
222 // avoid enumeration value `put_max' not handled in switch
223 // this case should never happen
224 break;
225 }
226}
227
228
229template <class charT, class Traits>
230void
232 const std::num_get<charT> &ng,
233 const std::istreambuf_iterator<charT, Traits> &iter,
234 const std::istreambuf_iterator<charT, Traits> &end,
235 std::basic_ios<charT, Traits> &io)
236{
237 std::ios_base::iostate state = std::ios_base::goodbit;
238
239 switch (data.type_) {
240 case MyNumData::put_bool: {
241 const bool expected = data.value_ < 1.f;
242 bool checked;
243 ng.get (iter, end, io, state, checked);
244 RW_ASSERT (! (state & std::ios_base::failbit));
245 RW_ASSERT (checked == expected);
246 }
247 break;
248 case MyNumData::put_long: {
249 const long expected = (long)data.value_;
250 long checked;
251 ng.get (iter, end, io, state, checked);
252 RW_ASSERT (! (state & std::ios_base::failbit));
253 RW_ASSERT (checked == expected);
254 }
255 break;
257 const unsigned long expected = (unsigned long)data.value_;
258 unsigned long checked;
259 ng.get (iter, end, io, state, checked);
260 RW_ASSERT (! (state & std::ios_base::failbit));
261 RW_ASSERT (checked == expected);
262 }
263 break;
264
265#ifndef _RWSTD_NO_LONG_LONG
266
268 const _RWSTD_LONG_LONG expected = (_RWSTD_LONG_LONG)data.value_;
269 _RWSTD_LONG_LONG checked;
270 ng.get (iter, end, io, state, checked);
271 RW_ASSERT (! (state & std::ios_base::failbit));
272 RW_ASSERT (checked == expected);
273 }
274 break;
276 const unsigned _RWSTD_LONG_LONG expected
277 = (unsigned _RWSTD_LONG_LONG)data.value_;
278 unsigned _RWSTD_LONG_LONG checked;
279 ng.get (iter, end, io, state, checked);
280 RW_ASSERT (! (state & std::ios_base::failbit));
281 RW_ASSERT (checked == expected);
282 }
283 break;
284
285#endif // _RWSTD_NO_LONG_LONG
286
287 case MyNumData::put_dbl: {
288 const double expected = (double)data.value_;
289 double checked;
290 ng.get (iter, end, io, state, checked);
291 RW_ASSERT (! (state & std::ios_base::failbit));
292 RW_ASSERT (checked == expected);
293 }
294 break;
295
296#ifndef _RWSTD_NO_LONG_DOUBLE
297
298 case MyNumData::put_ldbl: {
299 const long double expected = (long double)data.value_;
300 long double checked;
301 ng.get (iter, end, io, state, checked);
302 RW_ASSERT (! (state & std::ios_base::failbit));
303 RW_ASSERT (checked == expected);
304 }
305 break;
306
307#endif // _RWSTD_NO_LONG_DOUBLE
308
309 case MyNumData::put_ptr: {
310 const void* expected = (const void*)&data.value_;
311 void* checked;
312 ng.get (iter, end, io, state, checked);
313 RW_ASSERT (! (state & std::ios_base::failbit));
314 RW_ASSERT (checked == expected);
315 }
316 break;
317
319 // avoid enumeration value `put_max' not handled in switch
320 // this case should never happen
321 break;
322 }
323}
324
325extern "C" {
326
327bool test_char; // exercise num_get<char>
328bool test_wchar; // exercise num_get<wchar_t>
329
330
331static void*
332thread_func (void*)
333{
334 typedef std::char_traits<char> Traits;
337 nio.rdbuf (&nsb);
338
339#ifndef _RWSTD_NO_WCHAR_T
340 typedef std::char_traits<wchar_t> WTraits;
343 wio.rdbuf (&wsb);
344#endif // _RWSTD_NO_WCHAR_T
345
346 for (int i = 0; i != opt_nloops; ++i) {
347
349 break;
350
351 // fill in the value and results for this locale
352 const MyNumData& data = my_num_data [i % nlocales];
353
354 // construct a named locale and imbue it in the ios object
355 // so that the locale is used not only by the num_put facet
356 const std::locale loc =
358 : std::locale (data.locale_name_);
359
360 if (test_char) {
361 // exercise the narrow char specialization of the facet
362
363 const std::num_get<char> &ng =
364 std::use_facet<std::num_get<char> >(loc);
365
366 nio.imbue (loc);
367 nsb.pubsetg (data.ncs_, data.nlen_);
368
369 test_get_data (data, ng,
370 std::istreambuf_iterator<char>(&nsb),
371 std::istreambuf_iterator<char>(),
372 nio);
373
374 RW_ASSERT (!nio.fail ());
375 }
376
377 // both specializations may be tested at the same time
378
379 if (test_wchar) {
380 // exercise the wide char specialization of the facet
381
382#ifndef _RWSTD_NO_WCHAR_T
383
384 const std::num_get<wchar_t> &wp =
385 std::use_facet<std::num_get<wchar_t> >(loc);
386
387 wio.imbue (loc);
388 wsb.pubsetg (data.wcs_, data.wlen_);
389
390 test_get_data (data, wp,
391 std::istreambuf_iterator<wchar_t>(&wsb),
392 std::istreambuf_iterator<wchar_t>(),
393 wio);
394
395 RW_ASSERT (!wio.fail ());
396
397#endif // _RWSTD_NO_WCHAR_T
398
399 }
400 }
401
402 return 0;
403}
404
405} // extern "C"
406
407
410static int
411run_test (int, char**)
412{
415 nio.rdbuf (&nsb);
416
417#ifndef _RWSTD_NO_WCHAR_T
420 wio.rdbuf (&wsb);
421#endif // _RWSTD_NO_WCHAR_T
422
423 // find all installed locales for which setlocale(LC_ALL) succeeds
424 const char* const locale_list =
425 rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
426
427 const std::size_t maxinx = RW_COUNT_OF (locales);
428
429 for (const char *name = locale_list;
430 *name;
431 name += std::strlen (name) + 1) {
432
433 const std::size_t inx = nlocales;
434 locales [inx] = name;
435
436 // fill in the value and results for this locale
439
440 try {
441 const std::locale loc (data.locale_name_);
442
443 data.value_ = nlocales & 1 ? -1.f * nlocales : 1.f * nlocales;
444 data.type_ = MyNumData::PutId (nlocales % MyNumData::put_max);
445
446 // format data into buffers
447 const std::num_put<char> &np =
448 std::use_facet<std::num_put<char> >(loc);
449
450 nio.imbue (loc);
451 nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
452
453 test_put_data (data, np, std::ostreambuf_iterator<char>(&nsb),
454 nio, ' ', '\0');
455
456 data.nlen_ = std::char_traits<char>::length (data.ncs_);
457
458 rw_fatal (!nio.fail (), __FILE__, __LINE__,
459 "num_put<char>::put(...) failed for locale(%#s)",
460 data.locale_name_);
461
462#ifndef _RWSTD_NO_WCHAR_T
463
464 const std::num_put<wchar_t> &wp =
465 std::use_facet<std::num_put<wchar_t> >(loc);
466
467 wio.imbue (loc);
468 wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
469
470 test_put_data (data, wp, std::ostreambuf_iterator<wchar_t>(&wsb),
471 wio, L' ', L'\0');
472
473 data.wlen_ = std::char_traits<wchar_t>::length (data.wcs_);
474
475 rw_fatal (!wio.fail (), __FILE__, __LINE__,
476 "num_put<wchar_t>::put(...) failed for locale(%#s)",
477 data.locale_name_);
478
479#endif // _RWSTD_NO_WCHAR_T
480
482 data.locale_ = loc;
483
484 nlocales += 1;
485 }
486 catch (...) {
487 rw_warn (!rw_opt_locales, 0, __LINE__,
488 "failed to create locale(%#s)", name);
489 }
490
491 if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
492 break;
493 }
494
495 // avoid divide by zero in thread if there are no locales to test
496 rw_fatal (nlocales != 0, 0, __LINE__,
497 "failed to create one or more usable locales!");
498
499 rw_info (0, 0, 0,
500 "testing std::num_get<charT> with %d thread%{?}s%{;}, "
501 "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
504 nlocales, int (nlocales), "%#s", locales);
505
506 rw_info (0, 0, 0, "exercising std::num_get<char>");
507
508 test_char = true;
509 test_wchar = false;
510
511 // create and start a pool of threads and wait for them to finish
512 int result =
513 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
514 thread_func, 0, std::size_t (opt_timeout));
515
516 rw_error (result == 0, 0, __LINE__,
517 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
518 opt_nthreads, thread_func);
519
520#ifndef _RWSTD_NO_WCHAR_T
521
522 rw_info (0, 0, 0, "exercising std::num_get<wchar_t>");
523
524 test_char = false;
525 test_wchar = true;
526
527 // start a pool of threads to exercise wstring thread safety
528 result =
529 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
530 thread_func, 0, std::size_t (opt_timeout));
531
532 rw_error (result == 0, 0, __LINE__,
533 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
534 opt_nthreads, thread_func);
535
536 // exercise both the char and the wchar_t specializations
537 // at the same time
538
539 rw_info (0, 0, 0,
540 "exercising both std::num_get<char> and std::num_get<wchar_t>");
541
542 test_char = true;
543 test_wchar = true;
544
545 // start a pool of threads to exercise wstring thread safety
546 result =
547 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
548 thread_func, 0, std::size_t (opt_timeout));
549
550 rw_error (result == 0, 0, __LINE__,
551 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
552 opt_nthreads, thread_func);
553
554#endif // _RWSTD_NO_WCHAR_T
555
556 return result;
557}
558
559
561int main (int argc, char *argv [])
562{
563#ifdef _RWSTD_REENTRANT
564
565 // set nthreads to the greater of the number of processors
566 // and 2 (for uniprocessor systems) by default
568 if (opt_nthreads < 2)
569 opt_nthreads = 2;
570
571#endif // _RWSTD_REENTRANT
572
573 return rw_test (argc, argv, __FILE__,
574 "lib.locale.num.get",
575 "thread safety", run_test,
576 "|-soft-timeout#0 " // must be non-negative
577 "|-nloops#0 " // must be non-negative
578 "|-nthreads#0-* " // must be in [0, MAX_THREADS]
579 "|-nlocales#0 " // arg must be non-negative
580 "|-locales= " // must be provided
581 "|-shared-locale# ",
583 &opt_nloops,
584 int (MAX_THREADS),
589}
#define i
Definition 17.names.cpp:126
#define loc
Definition 17.names.cpp:492
#define Traits
Definition 17.names.cpp:556
#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
void test_get_data(const MyNumData &data, const std::num_get< charT > &ng, const std::istreambuf_iterator< charT, Traits > &iter, const std::istreambuf_iterator< charT, Traits > &end, std::basic_ios< charT, Traits > &io)
int opt_timeout
int opt_nloops
int opt_shared_locale
int opt_nlocales
#define MAX_THREADS
void test_put_data(const MyNumData &data, const std::num_put< charT > &np, const std::ostreambuf_iterator< charT, Traits > &iter, std::basic_ios< charT, Traits > &io, charT fill, charT term)
struct MyNumData my_num_data[MAX_THREADS]
bool test_wchar
int opt_nthreads
bool test_char
#define MAX_LOOPS
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
const int end
#define main
const unsigned nlocales
#define _RWSTD_LONG_LONG
#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
_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
wchar_t wcs_[BufferSize]
const char * locale_name_
char ncs_[BufferSize]
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)