Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.time.put.mt.cpp
Go to the documentation of this file.
1
31#include <ios> // for ios
32#include <iterator> // for ostreambuf_iterator
33#include <locale> // for locale, time_put
34
35#include <cstring> // for strlen ()
36#include <ctime> // for tm
37
38#include <rw_locale.h>
39#include <rw_thread.h>
40#include <rw_driver.h> // for rw_assert ()
41#include <rw_valcmp.h> // for rw_strncmp ()
42
43#define MAX_THREADS 32
44#define MAX_LOOPS 100000
45
46// default number of threads (will be adjusted to the number
47// of processors/cores later)
49
50// the number of times each thread should iterate
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 an inefficiency (small cache size?) on HP-UX
61// in LP64 mode (see STDCXX-812)
62int opt_nlocales = 10;
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//
86struct MyTimeData
87{
88 enum { BufferSize = 64 };
89
90 // name of the locale the data corresponds to
91 const char* locale_name_;
92
93 // optionally set to the named locale for threads to share
94 std::locale locale_;
95
96 // the time struct used to generate strings below
97 std::tm time_;
98
99 // the format specifier
100 char format_;
101
102 // narrow representations of time_ given the
103 // locale_name_ and the format_
104 char ncs_ [BufferSize];
105
106#ifndef _RWSTD_NO_WCHAR_T
107
108 // wide representations of time_
109 wchar_t wcs_ [BufferSize];
110
111#endif // _RWSTD_NO_WCHAR_T
112
114
115
116template <class charT, class Traits>
117struct MyIos: std::basic_ios<charT, Traits>
118{
119 MyIos () {
120 this->init (0);
121 }
122};
123
124
125template <class charT, class Traits>
126struct MyStreambuf: std::basic_streambuf<charT, Traits>
127{
128 typedef std::basic_streambuf<charT, Traits> Base;
129
131 : Base () {
132 }
133
134 void pubsetp (charT *pbeg, std::streamsize n) {
135 this->setp (pbeg, pbeg + n);
136 }
137};
138
139
140extern "C" {
141
142bool test_char; // exercise time_put<char>
143bool test_wchar; // exercise time_put<wchar_t>
144
145
146static void*
147thread_func (void*)
148{
149 char ncs [MyTimeData::BufferSize];
152 nio.rdbuf (&nsb);
153
154#ifndef _RWSTD_NO_WCHAR_T
155 wchar_t wcs [MyTimeData::BufferSize];
158 wio.rdbuf (&wsb);
159#endif // _RWSTD_NO_WCHAR_T
160
161 for (int i = 0; i != opt_nloops; ++i) {
162
164 break;
165
166 // save the name of the locale
168
169 // construct a named locale, get a reference to the time_put
170 // facet from it and use it to format a random time value
171 // using a random conversion specifier
172 const std::locale loc =
174 : std::locale (data.locale_name_);
175
176 if (test_char) {
177 // exercise the narrow char specialization of the facet
178
179 const std::time_put<char> &tp =
180 std::use_facet<std::time_put<char> >(loc);
181
182 nio.imbue (loc);
183 nsb.pubsetp (ncs, RW_COUNT_OF (ncs));
184
185 // format time using provided format specifier
186 *tp.put (std::ostreambuf_iterator<char>(&nsb),
187 nio, ' ', &data.time_, data.format_) = '\0';
188
189 RW_ASSERT (!nio.fail ());
190 RW_ASSERT (!rw_strncmp(ncs, data.ncs_));
191
192 }
193
194 // both specializations may be tested at the same time
195
196 if (test_wchar) {
197 // exercise the wide char specialization of the facet
198
199#ifndef _RWSTD_NO_WCHAR_T
200
201 const std::time_put<wchar_t> &wp =
202 std::use_facet<std::time_put<wchar_t> >(loc);
203
204 wio.imbue (loc);
205 wsb.pubsetp (wcs, RW_COUNT_OF (wcs));
206
207 *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
208 wio, L' ', &data.time_, data.format_) = L'\0';
209
210 RW_ASSERT (!wio.fail ());
211 RW_ASSERT (!rw_strncmp(wcs, data.wcs_));
212
213#endif // _RWSTD_NO_WCHAR_T
214
215 }
216 }
217
218 return 0;
219}
220
221} // extern "C"
222
223
225static int
226run_test (int, char**)
227{
230 nio.rdbuf (&nsb);
231
232#ifndef _RWSTD_NO_WCHAR_T
235 wio.rdbuf (&wsb);
236#endif // _RWSTD_NO_WCHAR_T
237
238 // find all installed locales for which setlocale (LC_ALL) succeeds
239 const char* const locale_list =
240 rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
241
242 const std::size_t maxinx = RW_COUNT_OF (locales);
243
244 int j = 0;
245 for (const char* name = locale_list;
246 *name;
247 name += std::strlen (name) + 1) {
248
249 const std::size_t inx = nlocales;
250 locales [inx] = name;
251
252 // fill in the time and results for this locale
255
256 // initialize tm with random but valid values
257 data.time_.tm_sec = ++j % 61;
258 data.time_.tm_min = ++j % 60;
259 data.time_.tm_hour = ++j % 12;
260 data.time_.tm_wday = ++j % 7;
261 data.time_.tm_mon = ++j % 12;
262 data.time_.tm_mday = ++j % 31;
263 data.time_.tm_yday = ++j % 366;
264 data.time_.tm_year = ++j;
265
266 const char cvtspecs[] = "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%";
267
268 // get the "random" conversion specifier used to generate
269 // the result string
270 data.format_ = cvtspecs [nlocales % (sizeof cvtspecs - 1)];
271
272 try {
273 const std::locale loc (data.locale_name_);
274
275 const std::time_put<char> &np =
276 std::use_facet<std::time_put<char> >(loc);
277
278 nio.imbue (loc);
279 nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_));
280
281 *np.put (std::ostreambuf_iterator<char>(&nsb),
282 nio, ' ', &data.time_, data.format_) = '\0';
283
284 rw_fatal (!nio.fail (), __FILE__, __LINE__,
285 "time_put<char>::put(..., %c) "
286 "failed for locale(%#s)",
287 data.format_, data.locale_name_);
288
289#ifndef _RWSTD_NO_WCHAR_T
290
291 const std::time_put<wchar_t> &wp =
292 std::use_facet<std::time_put<wchar_t> >(loc);
293
294 wio.imbue (loc);
295 wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_));
296
297 *wp.put (std::ostreambuf_iterator<wchar_t>(&wsb),
298 wio, L' ', &data.time_, data.format_) = L'\0';
299
300 rw_fatal (!wio.fail (), __FILE__, __LINE__,
301 "time_put<wchar_t>::put(..., %c) "
302 "failed for locale(%#s)",
303 data.format_, data.locale_name_);
304
305#endif // _RWSTD_NO_WCHAR_T
306
308 data.locale_ = loc;
309
310 nlocales += 1;
311
312 }
313 catch (...) {
314 rw_warn (!rw_opt_locales, 0, __LINE__,
315 "failed to create locale(%#s)", name);
316 }
317
318 if (nlocales == maxinx || nlocales == std::size_t (opt_nlocales))
319 break;
320 }
321
322 // avoid divide by zero in thread if there are no locales to test
323 rw_fatal (nlocales != 0, 0, __LINE__,
324 "failed to create one or more usable locales!");
325
326 rw_info (0, 0, 0,
327 "testing std::time_put<charT> with %d thread%{?}s%{;}, "
328 "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
331 nlocales, int (nlocales), "%#s", locales);
332
333 rw_info (0, 0, 0, "exercising std::time_put<char>");
334
335 test_char = true;
336 test_wchar = false;
337
338 // create and start a pool of threads and wait for them to finish
339 int result =
340 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
341 thread_func, 0, std::size_t (opt_timeout));
342
343 rw_error (result == 0, 0, __LINE__,
344 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
345 opt_nthreads, thread_func);
346
347#ifndef _RWSTD_NO_WCHAR_T
348
349 rw_info (0, 0, 0, "exercising std::time_put<wchar_t>");
350
351 test_char = false;
352 test_wchar = true;
353
354 // start a pool of threads to exercise wstring thread safety
355 result =
356 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
357 thread_func, 0, std::size_t (opt_timeout));
358
359 rw_error (result == 0, 0, __LINE__,
360 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
361 opt_nthreads, thread_func);
362
363 // exercise both the char and the wchar_t specializations
364 // at the same time
365
366 rw_info (0, 0, 0,
367 "exercising both std::time_put<char> and std::time_put<wchar_t>");
368
369 test_char = true;
370 test_wchar = true;
371
372 // start a pool of threads to exercise wstring thread safety
373 result =
374 rw_thread_pool (0, std::size_t (opt_nthreads), 0,
375 thread_func, 0, std::size_t (opt_timeout));
376
377 rw_error (result == 0, 0, __LINE__,
378 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
379 opt_nthreads, thread_func);
380
381#endif // _RWSTD_NO_WCHAR_T
382
383 return result;
384}
385
386
388int main (int argc, char *argv[])
389{
390#ifdef _RWSTD_REENTRANT
391
392 // set nthreads to the greater of the number of processors
393 // and 2 (for uniprocessor systems) by default
395 if (opt_nthreads < 2)
396 opt_nthreads = 2;
397
398#endif // _RWSTD_REENTRANT
399
400 return rw_test (argc, argv, __FILE__,
401 "lib.locale.time.put",
402 "thread safety", run_test,
403 "|-soft-timeout#0 " // must be non-negative
404 "|-nloops#0 " // must be non-negative
405 "|-nthreads#0-* " // must be in [0, MAX_THREADS]
406 "|-nlocales#0 " // arg must be non-negative
407 "|-locales= " // must be provided
408 "|-shared-locale# ",
410 &opt_nloops,
411 int (MAX_THREADS),
416}
#define i
Definition 17.names.cpp:126
#define loc
Definition 17.names.cpp:492
#define j
Definition 17.names.cpp:127
#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
struct MyTimeData my_time_data[MAX_THREADS]
int opt_shared_locale
int opt_nlocales
#define MAX_THREADS
bool test_wchar
int opt_nthreads
#define MAX_LOOPS
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
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)
std::basic_streambuf< charT, Traits > Base
void pubsetp(charT *beg, charT *cur, charT *end)
void pubsetp(charT *pbeg, std::streamsize n)
wchar_t wcs_[BufferSize]
const char * locale_name_
char ncs_[BufferSize]