Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.num.put.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_put
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
97 put_dbl,
98
99#ifndef _RWSTD_NO_LONG_DOUBLE
100
101 put_ldbl,
102
103#endif // _RWSTD_NO_LONG_DOUBLE
104
105 put_ptr,
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 put
119 PutId type_;
120
121 // holds the narrow/wide character representation of value_ and
122 // the number of used 'charT' in each buffer.
123 char ncs_ [BufferSize];
124
125#ifndef _RWSTD_NO_WCHAR_T
126
127 wchar_t wcs_ [BufferSize];
128
129#endif // _RWSTD_NO_WCHAR_T
130
132
133
135template <class charT, class Traits>
136struct MyIos: std::basic_ios<charT, Traits>
137{
138 MyIos () {
139 this->init (0);
140 }
141};
142
143template <class charT, class Traits>
144struct MyStreambuf: std::basic_streambuf<charT, Traits>
145{
146 typedef std::basic_streambuf<charT, Traits> Base;
147
149 : Base () {
150 }
151
152 void pubsetp (charT *pbeg, std::streamsize n) {
153 this->setp (pbeg, pbeg + n);
154 }
155};
156
157template <class charT, class Traits>
158void
160 const std::num_put<charT> &np,
161 const std::ostreambuf_iterator<charT, Traits> &iter,
162 std::basic_ios<charT, Traits> &io,
163 charT fill,
164 charT term)
165{
166 switch (data.type_) {
168 *np.put (iter, io, fill,
169 data.value_ < 1.f) = term;
170 break;
172 *np.put (iter, io, fill,
173 (long)data.value_) = term;
174 break;
176 *np.put (iter, io, fill,
177 (unsigned long)data.value_) = term;
178 break;
179
180#ifndef _RWSTD_NO_LONG_LONG
181
183 *np.put (iter, io, fill,
184 (_RWSTD_LONG_LONG)data.value_) = term;
185 break;
187 *np.put (iter, io, fill,
188 (unsigned _RWSTD_LONG_LONG)data.value_) = term;
189 break;
190
191#endif // _RWSTD_NO_LONG_LONG
192
194 *np.put (iter, io, fill,
195 (double)data.value_) = term;
196
197 break;
198
199#ifndef _RWSTD_NO_LONG_DOUBLE
200
202 *np.put (iter, io, fill,
203 (long double)data.value_) = term;
204 break;
205
206#endif // _RWSTD_NO_LONG_DOUBLE
207
209 *np.put (iter, io, fill,
210 (const void*)&data.value_) = term;
211 break;
212
214 // avoid enumeration value `put_max' not handled in switch
215 // this case should never happen
216 break;
217 }
218
219}
220
221extern "C" {
222
223bool test_char; // exercise num_put<char>
224bool test_wchar; // exercise num_put<wchar_t>
225
226
227static void*
228thread_func (void*)
229{
230 char ncs [MyNumData::BufferSize];
233 nio.rdbuf (&nsb);
234
235#ifndef _RWSTD_NO_WCHAR_T
236 wchar_t wcs [MyNumData::BufferSize];
239 wio.rdbuf (&wsb);
240#endif // _RWSTD_NO_WCHAR_T
241
242 for (int i = 0; i != opt_nloops; ++i) {
243
245 break;
246
247 // fill in the value and results for this locale
248 const MyNumData& data = my_num_data [i % nlocales];
249
250 // construct a named locale and imbue it in the ios object
251 // so that the locale is used not only by the num_put facet
252 const std::locale loc =
254 : std::locale (data.locale_name_);
255
256 if (test_char) {
257 // exercise the narrow char specialization of the facet
258
259 const std::num_put<char> &np =
260 std::use_facet<std::num_put<char> >(loc);
261
262 nio.imbue (loc);
263 nsb.pubsetp (ncs, RW_COUNT_OF (ncs));
264
265 put_data (data, np, std::ostreambuf_iterator<char>(&nsb),
266 nio, ' ', '\0');
267
268 RW_ASSERT (!nio.fail ());
269 RW_ASSERT (!rw_strncmp (ncs, data.ncs_));
270 }
271
272 // both specializations may be tested at the same time
273
274 if (test_wchar) {
275 // exercise the wide char specialization of the facet
276
277#ifndef _RWSTD_NO_WCHAR_T
278
279 const std::num_put<wchar_t> &wp =
280 std::use_facet<std::num_put<wchar_t> >(loc);
281
282 wio.imbue (loc);
283 wsb.pubsetp (wcs, RW_COUNT_OF (wcs));
284
285 put_data (data, wp, std::ostreambuf_iterator<wchar_t>(&wsb),
286 wio, L' ', L'\0');
287
288 RW_ASSERT (!wio.fail ());
289 RW_ASSERT (!rw_strncmp (wcs, data.wcs_));
290
291#endif // _RWSTD_NO_WCHAR_T
292
293 }
294 }
295
296 return 0;
297}
298
299} // extern "C"
300
301
304static int
305run_test (int, char**)
306{
309 nio.rdbuf (&nsb);
310
311#ifndef _RWSTD_NO_WCHAR_T
314 wio.rdbuf (&wsb);
315#endif // _RWSTD_NO_WCHAR_T
316
317 // find all installed locales for which setlocale(LC_ALL) succeeds
318 const char* const locale_list =
319 rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
320
321 const std::size_t maxinx = RW_COUNT_OF (locales);
322
323 for (const char *name = locale_list;
324 *name;
325 name += std::strlen (name) + 1) {
326
327 const std::size_t inx = nlocales;
328 locales [inx] = name;
329
330 // fill in the value and results for this locale
333
334 try {
335 const std::locale loc (data.locale_name_);
336
337 data.value_ = nlocales & 1 ? -1 * nlocales : nlocales;
338 data.type_ = MyNumData::PutId (nlocales % MyNumData::put_max);
339
340 // format data into buffers
341 const std::num_put<char> &np =
342 std::use_facet<std::num_put<char> >(loc);
343
344 nio.imbue (loc);
345 nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
346
347 put_data (data, np, std::ostreambuf_iterator<char>(&nsb),
348 nio, ' ', '\0');
349
350 rw_fatal (!nio.fail (), __FILE__, __LINE__,
351 "num_put<char>::put(...) failed for locale(%#s)",
352 data.locale_name_);
353
354#ifndef _RWSTD_NO_WCHAR_T
355
356 const std::num_put<wchar_t> &wp =
357 std::use_facet<std::num_put<wchar_t> >(loc);
358
359 wio.imbue (loc);
360 wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
361
362 put_data (data, wp, std::ostreambuf_iterator<wchar_t>(&wsb),
363 wio, L' ', L'\0');
364
365 rw_fatal (!wio.fail (), __FILE__, __LINE__,
366 "num_put<wchar_t>::put(...) failed for locale(%#s)",
367 data.locale_name_);
368
369#endif // _RWSTD_NO_WCHAR_T
370
372 data.locale_ = loc;
373
374 nlocales += 1;
375 }
376 catch (...) {
377 rw_warn (!rw_opt_locales, 0, __LINE__,
378 "failed to create locale(%#s)", name);
379 }
380
381 if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
382 break;
383 }
384
385 // avoid divide by zero in thread if there are no locales to test
386 rw_fatal (nlocales != 0, 0, __LINE__,
387 "failed to create one or more usable locales!");
388
389 rw_info (0, 0, 0,
390 "testing std::num_put<charT> with %d thread%{?}s%{;}, "
391 "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
394 nlocales, int (nlocales), "%#s", locales);
395
396 rw_info (0, 0, 0, "exercising std::num_put<char>");
397
398 test_char = true;
399 test_wchar = false;
400
401 // create and start a pool of threads and wait for them to finish
402 int result =
403 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
404 thread_func, 0, std::size_t (opt_timeout));
405
406 rw_error (result == 0, 0, __LINE__,
407 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
408 opt_nthreads, thread_func);
409
410#ifndef _RWSTD_NO_WCHAR_T
411
412 rw_info (0, 0, 0, "exercising std::num_put<wchar_t>");
413
414 test_char = false;
415 test_wchar = true;
416
417 // start a pool of threads to exercise wstring thread safety
418 result =
419 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
420 thread_func, 0, std::size_t (opt_timeout));
421
422 rw_error (result == 0, 0, __LINE__,
423 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
424 opt_nthreads, thread_func);
425
426 // exercise both the char and the wchar_t specializations
427 // at the same time
428
429 rw_info (0, 0, 0,
430 "exercising both std::num_put<char> and std::num_put<wchar_t>");
431
432 test_char = true;
433 test_wchar = true;
434
435 // start a pool of threads to exercise wstring thread safety
436 result =
437 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
438 thread_func, 0, std::size_t (opt_timeout));
439
440 rw_error (result == 0, 0, __LINE__,
441 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
442 opt_nthreads, thread_func);
443
444#endif // _RWSTD_NO_WCHAR_T
445
446 return result;
447}
448
449
451int main (int argc, char *argv[])
452{
453#ifdef _RWSTD_REENTRANT
454
455 // set nthreads to the greater of the number of processors
456 // and 2 (for uniprocessor systems) by default
458 if (opt_nthreads < 2)
459 opt_nthreads = 2;
460
461#endif // _RWSTD_REENTRANT
462
463 return rw_test (argc, argv, __FILE__,
464 "lib.locale.num.put",
465 "thread safety", run_test,
466 "|-soft-timeout#0 " // must be non-negative
467 "|-nloops#0 " // must be non-negative
468 "|-nthreads#0-* " // must be in [0, MAX_THREADS]
469 "|-nlocales#0 " // arg must be non-negative
470 "|-locales= " // must be provided
471 "|-shared-locale# ",
473 &opt_nloops,
474 int (MAX_THREADS),
479}
#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_timeout
int opt_nloops
void 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)
int opt_shared_locale
int opt_nlocales
#define MAX_THREADS
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)
#define main
const unsigned nlocales
#define _RWSTD_LONG_LONG
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
_TEST_EXPORT int rw_strncmp(const char *, const char *, _RWSTD_SIZE_T=_RWSTD_SIZE_MAX, int=CMP_NULTERM)
wchar_t wcs_[BufferSize]
const char * locale_name_
char ncs_[BufferSize]
std::basic_streambuf< charT, Traits > Base
void pubsetp(charT *beg, charT *cur, charT *end)
void pubsetp(charT *pbeg, std::streamsize n)