Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
22.locale.globals.mt.cpp
Go to the documentation of this file.
1
29#include <locale> // for locale
30
31#include <cwchar> // for mbstate_t
32#include <cstring> // for strlen()
33
34#include <rw_locale.h> // for rw_locales()
35#include <rw_thread.h> // for rw_get_processors(), rw_thread_pool()
36#include <rw_driver.h> // for rw_test()
37
38
39// maximum number of threads allowed by the command line interface
40#define MAX_THREADS 16
41
42// default number of threads (will be adjusted to the number
43// of processors/cores later)
45
46// the number of times each thread should iterate (unless specified
47// otherwise on the command line)
48int opt_nloops = 20000;
49
50enum {
65};
66
67// tri-state options to enable/disable individual facets
68// opt_facets [i] < 0: facet is initially explicitly disabled
69// opt_facets [i] == 0: option not specified on the command line
70// opt_facets [i] > 0: facet is initially explicitly enabled
72
73// disable exceptions?
75
76// default timeout used by each threaded section of this test
77int opt_timeout = 60;
78
79
81// array of locale names to use for testing
82static const char*
84
85// number of locale names in the array
86static std::size_t
88
89
91// convenience typedefs for all required specializations of standard facets
92typedef std::codecvt<char, char, std::mbstate_t> Codecvt;
93typedef std::collate<char> Collate;
94typedef std::ctype<char> Ctype;
95typedef std::messages<char> Messages;
96typedef std::moneypunct<char, false> Moneypunct0;
97typedef std::moneypunct<char, true> Moneypunct1;
98typedef std::numpunct<char> Numpunct;
99typedef std::money_get<char> MoneyGet;
100typedef std::money_put<char> MoneyPut;
101typedef std::num_get<char> NumGet;
102typedef std::num_put<char> NumPut;
103typedef std::time_get<char> TimeGet;
104typedef std::time_put<char> TimePut;
105
106typedef std::collate_byname<char> CollateByname;
107typedef std::ctype_byname<char> CtypeByname;
108typedef std::codecvt_byname<char, char, std::mbstate_t> CodecvtByname;
109typedef std::messages_byname<char> MessagesByname;
110typedef std::moneypunct_byname<char, false> Moneypunct0Byname;
111typedef std::moneypunct_byname<char, true> Moneypunct1Byname;
112typedef std::numpunct_byname<char> NumpunctByname;
113typedef std::time_get_byname<char> TimeGetByname;
114typedef std::time_put_byname<char> TimePutByname;
115
116
117#ifndef _RWSTD_NO_WCHAR_T
118
119typedef std::collate<wchar_t> WCollate;
120typedef std::ctype<wchar_t> WCtype;
121typedef std::codecvt<wchar_t, char, std::mbstate_t> WCodecvt;
122typedef std::messages<wchar_t> WMessages;
123typedef std::moneypunct<wchar_t, false> WMoneypunct0;
124typedef std::moneypunct<wchar_t, true> WMoneypunct1;
125typedef std::numpunct<wchar_t> WNumpunct;
126typedef std::money_get<wchar_t> WMoneyGet;
127typedef std::money_put<wchar_t> WMoneyPut;
128typedef std::num_get<wchar_t> WNumGet;
129typedef std::num_put<wchar_t> WNumPut;
130typedef std::time_get<wchar_t> WTimeGet;
131typedef std::time_put<wchar_t> WTimePut;
132
133typedef std::collate_byname<wchar_t> WCollateByname;
134typedef std::ctype_byname<wchar_t> WCtypeByname;
135typedef std::codecvt_byname<wchar_t, char, std::mbstate_t> WCodecvtByname;
136typedef std::messages_byname<wchar_t> WMessagesByname;
137typedef std::moneypunct_byname<wchar_t, false> WMoneypunct0Byname;
138typedef std::moneypunct_byname<wchar_t, true> WMoneypunct1Byname;
139typedef std::numpunct_byname<wchar_t> WNumpunctByname;
140typedef std::time_get_byname<wchar_t> WTimeGetByname;
141typedef std::time_put_byname<wchar_t> WTimePutByname;
142
143#endif // _RWSTD_NO_WCHAR_T
144
145
146extern "C" {
147
148static void*
149test_has_facet (void*)
150{
151 const std::locale classic (std::locale::classic ());
152
153 for (int i = 0; i != opt_nloops; ++i) {
154
156 break;
157
158 // save the name of the locale
159 const char* const locale_name = locales [i % nlocales];
160
161 // construct a named locale and imbue it in the ios object
162 // so that the locale is used not only by the num_put facet
163 // but also by the numpunct facet
164 const std::locale loc (locale_name);
165
166 const bool byname = loc != classic;
167
168// call has_facet for each base facet only of it's enabled
169#define HAS(Facet, opt) \
170 (0 <= opt_facets [opt_inx_ ## opt] ? std::has_facet<Facet>(loc) : true)
171
172 HAS (Codecvt, codecvt);
173 HAS (Collate, collate);
174 HAS (Ctype, ctype);
175 HAS (Messages, messages);
176 HAS (Moneypunct0, moneypunct);
177 HAS (Moneypunct1, moneypunct_intl);
178 HAS (MoneyGet, money_get);
179 HAS (MoneyPut, money_put);
180 HAS (Numpunct, numpunct);
181 HAS (NumGet, num_get);
182 HAS (NumPut, num_put);
183 HAS (TimeGet, time_get);
184 HAS (TimePut, time_put);
185
186// call has_facet for each _byname facet only of it's enabled
187#define HAS_BYNAME(Facet, opt) \
188 (0 <= opt_facets [opt_inx_ ## opt] ? \
189 byname == std::has_facet<Facet>(loc) : true)
190
191 HAS_BYNAME (CodecvtByname, codecvt);
192 HAS_BYNAME (CollateByname, collate);
193 HAS_BYNAME (CtypeByname, ctype);
194 HAS_BYNAME (MessagesByname, messages);
195 HAS_BYNAME (Moneypunct0Byname, moneypunct);
196 HAS_BYNAME (Moneypunct1Byname, moneypunct_intl);
197 HAS_BYNAME (TimeGetByname, time_get);
198 HAS_BYNAME (TimePutByname, time_put);
199
200#ifndef _RWSTD_NO_WCHAR_T
201
202 HAS (WCodecvt, codecvt);
203 HAS (WCollate, collate);
204 HAS (WCtype, ctype);
205 HAS (WMessages, messages);
206 HAS (WMoneypunct0, moneypunct);
207 HAS (WMoneypunct1, moneypunct_intl);
208 HAS (WMoneyGet, money_get);
209 HAS (WMoneyPut, money_put);
210 HAS (WNumpunct, numpunct);
211 HAS (WNumGet, num_get);
212 HAS (WNumPut, num_put);
213 HAS (WTimeGet, time_get);
214 HAS (WTimePut, time_put);
215
216 HAS_BYNAME (WCodecvtByname, codecvt);
217 HAS_BYNAME (WCollateByname, collate);
218 HAS_BYNAME (WCtypeByname, ctype);
219 HAS_BYNAME (WMessagesByname, messages);
220 HAS_BYNAME (WMoneypunct0Byname, moneypunct);
221 HAS_BYNAME (WMoneypunct1Byname, moneypunct_intl);
222 HAS_BYNAME (WTimeGetByname, time_get);
223 HAS_BYNAME (WTimePutByname, time_put);
224
225#endif // _RWSTD_NO_WCHAR_T
226
227 }
228
229 return 0;
230}
231
232} // extern "C"
233
234
235static void
236use_facet_loop (const std::locale &classic, int i)
237{
238 static const std::locale::facet* const dummy =
239 (std::locale::facet*)1;
240
241 // save the name of the locale
242 const char* const locale_name = locales [i % nlocales];
243
244 // construct a named locale and imbue it in the ios object
245 // so that the locale is used not only by the num_put facet
246 // but also by the numpunct facet
247 const std::locale loc (locale_name);
248
249 const bool byname = loc != classic;
250
251 {
252
253#define USE(Facet, opt) \
254 (0 <= opt_facets [opt_inx_ ## opt] ? &std::use_facet<Facet>(loc) : dummy)
255
256 const std::locale::facet* const bases[] = {
257 // get pointers to the char specializations of facets
258 USE (Collate, collate),
259 USE (Ctype, ctype),
260 USE (Codecvt, codecvt),
261 USE (Messages, messages),
262 USE (Moneypunct0, moneypunct),
263 USE (Moneypunct1, moneypunct_intl),
264 USE (MoneyGet, money_get),
265 USE (MoneyPut, money_put),
266 USE (Numpunct, numpunct),
267 USE (NumGet, num_get),
268 USE (NumPut, num_put),
269 USE (TimeGet, time_get),
270 USE (TimePut, time_put)
271 };
272
273 if (byname) {
274
275 // get pointers to the char specializations
276 // of byname facets
277 const std::locale::facet* const derived[] = {
278 USE (CollateByname, collate),
279 USE (CtypeByname, ctype),
280 USE (CodecvtByname, codecvt),
281 USE (MessagesByname, messages),
282 USE (Moneypunct0Byname, moneypunct),
283 USE (Moneypunct1Byname, moneypunct_intl),
284 // no money_get_byname or money_put_byname
285 USE (MoneyGet, money_get),
286 USE (MoneyPut, money_put),
287 USE (NumpunctByname, numpunct),
288 // no num_get_byname or num_put_byname
289 USE (NumGet, num_get),
290 USE (NumPut, num_put),
291 USE (TimeGetByname, time_get),
292 USE (TimePutByname, time_put)
293 };
294
295 const std::size_t nbases = sizeof bases / sizeof *bases;
296
297 for (std::size_t j = 0; j != nbases; ++j) {
298 RW_ASSERT (bases [j] != 0);
299 RW_ASSERT (bases [j] == derived [j]);
300 }
301 }
302 else if (0 == opt_no_exceptions) {
303
304 bool threw;
305
306#define TEST_USE_FACET(Facet, opt) \
307 try { \
308 threw = false; \
309 if (0 <= opt_facets [opt_inx_ ## opt]) \
310 std::use_facet<Facet>(loc); \
311 } \
312 catch (...) { threw = true; } \
313 RW_ASSERT (threw || opt_facets [opt_inx_ ## opt] < 0)
314
315 TEST_USE_FACET (CollateByname, collate);
317 TEST_USE_FACET (CodecvtByname, codecvt);
318 TEST_USE_FACET (MessagesByname, messages);
319 TEST_USE_FACET (Moneypunct0Byname, moneypunct);
320 TEST_USE_FACET (Moneypunct1Byname, moneypunct_intl);
321 TEST_USE_FACET (NumpunctByname, numpunct);
322 TEST_USE_FACET (TimeGetByname, time_get);
323 TEST_USE_FACET (TimePutByname, time_put);
324 }
325 }
326
327#ifndef _RWSTD_NO_WCHAR_T
328
329 {
330 const std::locale::facet* const bases[] = {
331 // get pointers to the char specializations of facets
332 USE (WCollate, collate),
333 USE (WCtype, ctype),
334 USE (WCodecvt, codecvt),
335 USE (WMessages, messages),
336 USE (WMoneypunct0, moneypunct),
337 USE (WMoneypunct1, moneypunct_intl),
338 USE (WMoneyGet, money_get),
339 USE (WMoneyPut, money_put),
340 USE (WNumpunct, numpunct),
341 USE (WNumGet, num_get),
342 USE (WNumPut, num_put),
343 USE (WTimeGet, time_get),
344 USE (WTimePut, time_put)
345 };
346
347 if (byname) {
348 // get pointers to the char specializations
349 // of byname facets
350 const std::locale::facet* const derived[] = {
351 USE (WCollateByname, collate),
352 USE (WCtypeByname, ctype),
353 USE (WCodecvtByname, codecvt),
354 USE (WMessagesByname, messages),
355 USE (WMoneypunct0Byname, moneypunct),
356 USE (WMoneypunct1Byname, moneypunct_intl),
357 // no money_get_byname or money_put_byname
358 USE (WMoneyGet, money_get),
359 USE (WMoneyPut, money_put),
360 USE (WNumpunctByname, numpunct),
361 // no num_get_byname or num_put_byname
362 USE (WNumGet, num_get),
363 USE (WNumPut, num_put),
364 USE (WTimeGetByname, time_get),
365 USE (WTimePutByname, time_put)
366 };
367
368 const std::size_t nbases = sizeof bases / sizeof *bases;
369
370 for (std::size_t j = 0; j != nbases; ++j) {
371 RW_ASSERT (bases [j] != 0);
372 RW_ASSERT (bases [j] == derived [j]);
373 }
374 }
375 else if (0 == opt_no_exceptions) {
376
377 bool threw;
378
384 TEST_USE_FACET (WMoneypunct1Byname, moneypunct_intl);
386 TEST_USE_FACET (WTimeGetByname, time_get);
387 TEST_USE_FACET (WTimePutByname, time_put);
388 }
389 }
390
391#endif // _RWSTD_NO_WCHAR_T
392
393}
394
395
396extern "C" {
397
398static void*
399test_use_facet (void*)
400{
401 const std::locale classic (std::locale::classic ());
402
403 for (int i = 0; i != opt_nloops; ++i) {
404
406 break;
407
408 try {
409 use_facet_loop (classic, i);
410 }
411 catch (...) {
412 // what to do here?
413 }
414 }
415
416 return 0;
417}
418
419
420} // extern "C"
421
422
424int opt_has_facet; // exercise std::has_facet?
425int opt_use_facet; // exercise std::use_facet?
426
427
428static int
429run_test (int, char**)
430{
431 for (std::size_t i = 0; i != opt_nfacets; ++i) {
432 if (0 < opt_facets [i]) {
433 for (std::size_t j = 0; j != opt_nfacets; ++j) {
434 if (opt_facets [j] == 0)
435 opt_facets [j] = -1;
436 }
437 break;
438 }
439 }
440
441 rw_note (0 <= opt_facets [opt_inx_codecvt], 0, __LINE__,
442 "std::codecvt tests disabled");
443
444 rw_note (0 <= opt_facets [opt_inx_collate], 0, __LINE__,
445 "std::collate tests disabled");
446
447 rw_note (0 <= opt_facets [opt_inx_ctype], 0, __LINE__,
448 "std::ctype tests disabled");
449
450 rw_note (0 <= opt_facets [opt_inx_messages], 0, __LINE__,
451 "std::messages tests disabled");
452
453 rw_note (0 <= opt_facets [opt_inx_moneypunct], 0, __LINE__,
454 "std::moneypunct<charT, false> tests disabled");
455
456 rw_note (0 <= opt_facets [opt_inx_moneypunct_intl], 0, __LINE__,
457 "std::moneypunct<charT, true> tests disabled");
458
459 rw_note (0 <= opt_facets [opt_inx_money_get], 0, __LINE__,
460 "std::money_get tests disabled");
461
462 rw_note (0 <= opt_facets [opt_inx_money_put], 0, __LINE__,
463 "std::money_put tests disabled");
464
465 rw_note (0 <= opt_facets [opt_inx_numpunct], 0, __LINE__,
466 "std::numpunct tests disabled");
467
468 rw_note (0 <= opt_facets [opt_inx_num_get], 0, __LINE__,
469 "std::num_get tests disabled");
470
471 rw_note (0 <= opt_facets [opt_inx_num_put], 0, __LINE__,
472 "std::num_put tests disabled");
473
474 rw_note (0 <= opt_facets [opt_inx_time_get], 0, __LINE__,
475 "std::time_get tests disabled");
476
477 rw_note (0 <= opt_facets [opt_inx_time_put], 0, __LINE__,
478 "std::time_put tests disabled");
479
480 rw_note (0 == opt_no_exceptions, 0, __LINE__,
481 "tests involving exceptions disabled");
482
483 // find all installed locales for which setlocale(LC_ALL) succeeds
484 const char* const locale_list =
485 rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL);
486
487 const std::size_t maxinx = sizeof locales / sizeof *locales;
488
489 // set to true if the classic "C" locale is on the lost
490 bool has_classic = false;
491
492 for (const char *name = locale_list; *name; name += std::strlen (name) +1) {
493
494 locales [nlocales++] = name;
495
496 if (!has_classic && 0 == std::strcmp ("C", name))
497 has_classic = true;
498
499 if (nlocales == maxinx)
500 break;
501 }
502
503 // when the classic "C" locale isn't on the list put it there
504 // unless the list was explicitly specified on the command line
505 if (1 < nlocales && !has_classic && 0 == rw_opt_locales)
506 locales [0] = "C";
507
508 int result;
509
510 rw_info (0, 0, 0,
511 "testing std::locale globals with %d thread%{?}s%{;}, "
512 "%d iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }",
515 nlocales, int (nlocales), "%#s", locales);
516
517 if (opt_has_facet >= 0) {
518 rw_info (0, 0, 0,
519 "template <class T> bool std::has_facet (const locale&)");
520
521 // create and start a pool of threads and wait for them to finish
522 result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
523 test_has_facet, 0, std::size_t (opt_timeout));
524
525 rw_error (result == 0, 0, __LINE__,
526 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
527 opt_nthreads, test_has_facet);
528 }
529 else {
530 rw_note (0, 0, 0, "std::has_facet test disabled");
531 }
532
533 if (opt_use_facet >= 0) {
534 rw_info (0, 0, 0,
535 "template <class T> const T& std::use_facet (const locale&)");
536
537#ifdef _RWSTD_NO_DYNAMIC_CAST
538
539 // if dynamic_cast isn't supported, then [has,use]_facet()
540 // can't reliably detect if a facet is installed or not.
541 rw_warn (0 != opt_no_exceptions, 0, __LINE__,
542 "dynamic_cast not supported "
543 "(macro _RWSTD_NO_DYNAMIC_CAST is #defined), "
544 "disabling exceptions tests");
545
547
548#endif // _RWSTD_NO_DYNAMIC_CAST
549
550
551#ifdef _RWSTD_NO_THREAD_SAFE_EXCEPTIONS
552
553 // avoid exercising exceptions (triggered by use_facet) if
554 // their implementation in the runtime isn't thread-safe
555 rw_warn (0, 0, 0,
556 "exceptions not thread safe (macro "
557 "_RWSTD_NO_THREAD_SAFE_EXCEPTIONS is #defined), "
558 "disabling exceptions tests");
559
561
562#endif // _RWSTD_NO_THREAD_SAFE_EXCEPTIONS
563
564
565 // create and start a pool of threads and wait for them to finish
566 result = rw_thread_pool (0, std::size_t (opt_nthreads), 0,
567 test_use_facet, 0, std::size_t (opt_timeout));
568
569 rw_error (result == 0, 0, __LINE__,
570 "rw_thread_pool(0, %d, 0, %{#f}, 0) failed",
571 opt_nthreads, test_use_facet);
572 }
573 else {
574 rw_note (0, 0, 0, "std::use_facet test disabled");
575 }
576
577 return result;
578}
579
580
582int main (int argc, char *argv[])
583{
584#ifdef _RWSTD_REENTRANT
585
586 // set nthreads to the greater of the number of processors
587 // and 2 (for uniprocessor systems) by default
589 if (opt_nthreads < 2)
590 opt_nthreads = 2;
591
592#endif // _RWSTD_REENTRANT
593
594 return rw_test (argc, argv, __FILE__,
595 "lib.locale.global.templates",
596 "thread safety", run_test,
597 "|-has_facet~ "
598 "|-use_facet~ "
599 "|-soft-timeout#0 " // must be non-negative
600 "|-nloops#0 " // arg must be non-negative
601 "|-nthreads#0-* " // arg must be in [0, MAX_THREADS]
602 "|-locales= " // argument must be provided
603 "|-no-exceptions# " // disable exceptions
604 "|-codecvt~ " // enable/disable individual facets
605 "|-collate~ "
606 "|-ctype~ "
607 "|-messages~ "
608 "|-moneypunct~ "
609 "|-moneypunct_intl~ "
610 "|-money_get~ "
611 "|-money_put~ "
612 "|-numpunct~ "
613 "|-num_get~ "
614 "|-num_put~ "
615 "|-time_get~ "
616 "|-time_put~ ",
620 &opt_nloops,
621 int (MAX_THREADS),
638}
#define i
Definition 17.names.cpp:126
#define loc
Definition 17.names.cpp:492
#define j
Definition 17.names.cpp:127
volatile int result
std::codecvt< char, char, std::mbstate_t > Codecvt
std::codecvt< wchar_t, char, std::mbstate_t > WCodecvt
std::codecvt_byname< wchar_t, char, std::mbstate_t > WCodecvtByname
std::codecvt_byname< char, char, std::mbstate_t > CodecvtByname
const char * locale_list
std::time_get_byname< char > TimeGetByname
int opt_use_facet
std::numpunct_byname< char > NumpunctByname
std::ctype< wchar_t > WCtype
std::ctype_byname< wchar_t > WCtypeByname
#define HAS_BYNAME(Facet, opt)
std::numpunct< wchar_t > WNumpunct
std::money_put< wchar_t > WMoneyPut
int opt_timeout
std::codecvt< char, char, std::mbstate_t > Codecvt
std::time_get_byname< wchar_t > WTimeGetByname
std::num_get< char > NumGet
std::collate< char > Collate
std::codecvt< wchar_t, char, std::mbstate_t > WCodecvt
std::numpunct< char > Numpunct
int opt_nloops
int opt_has_facet
std::moneypunct< wchar_t, true > WMoneypunct1
std::num_put< char > NumPut
std::ctype< char > Ctype
std::moneypunct< char, true > Moneypunct1
std::codecvt_byname< wchar_t, char, std::mbstate_t > WCodecvtByname
std::collate_byname< wchar_t > WCollateByname
std::ctype_byname< char > CtypeByname
std::moneypunct_byname< char, false > Moneypunct0Byname
#define USE(Facet, opt)
std::moneypunct_byname< char, true > Moneypunct1Byname
#define TEST_USE_FACET(Facet, opt)
int opt_facets[opt_nfacets]
#define MAX_THREADS
int opt_no_exceptions
std::num_put< wchar_t > WNumPut
std::codecvt_byname< char, char, std::mbstate_t > CodecvtByname
std::collate< wchar_t > WCollate
std::time_put< wchar_t > WTimePut
std::money_put< char > MoneyPut
std::money_get< char > MoneyGet
#define HAS(Facet, opt)
std::collate_byname< char > CollateByname
std::num_get< wchar_t > WNumGet
std::moneypunct_byname< wchar_t, false > WMoneypunct0Byname
std::time_get< wchar_t > WTimeGet
std::moneypunct< char, false > Moneypunct0
std::moneypunct_byname< wchar_t, true > WMoneypunct1Byname
std::moneypunct< wchar_t, false > WMoneypunct0
std::messages_byname< wchar_t > WMessagesByname
std::time_put_byname< char > TimePutByname
std::messages< wchar_t > WMessages
std::time_put_byname< wchar_t > WTimePutByname
std::money_get< wchar_t > WMoneyGet
std::messages_byname< char > MessagesByname
int opt_nthreads
std::time_get< char > TimeGet
@ opt_inx_messages
@ opt_inx_money_put
@ opt_inx_numpunct
@ opt_inx_num_put
@ opt_inx_money_get
@ opt_inx_collate
@ opt_inx_moneypunct_intl
@ opt_inx_time_put
@ opt_inx_num_get
@ opt_inx_moneypunct
@ opt_inx_codecvt
@ opt_inx_time_get
std::messages< char > Messages
std::time_put< char > TimePut
std::numpunct_byname< wchar_t > WNumpunctByname
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
_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_note(int, const char *, int, const char *,...)
Definition driver.cpp:1664
_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)
_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