From stdcxx-commits-return-1682-apmail-incubator-stdcxx-commits-archive=incubator.apache.org@incubator.apache.org Wed Sep 05 00:11:15 2007 Return-Path: Delivered-To: apmail-incubator-stdcxx-commits-archive@www.apache.org Received: (qmail 73045 invoked from network); 5 Sep 2007 00:11:14 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 5 Sep 2007 00:11:14 -0000 Received: (qmail 16882 invoked by uid 500); 5 Sep 2007 00:11:09 -0000 Delivered-To: apmail-incubator-stdcxx-commits-archive@incubator.apache.org Received: (qmail 16874 invoked by uid 500); 5 Sep 2007 00:11:09 -0000 Mailing-List: contact stdcxx-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: stdcxx-dev@incubator.apache.org Delivered-To: mailing list stdcxx-commits@incubator.apache.org Received: (qmail 16863 invoked by uid 99); 5 Sep 2007 00:11:09 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 04 Sep 2007 17:11:09 -0700 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 05 Sep 2007 00:12:27 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 53AC81A9832; Tue, 4 Sep 2007 17:10:50 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r572842 - /incubator/stdcxx/trunk/tests/localization/22.locale.money.get.mt.cpp Date: Wed, 05 Sep 2007 00:10:50 -0000 To: stdcxx-commits@incubator.apache.org From: sebor@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20070905001050.53AC81A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: sebor Date: Tue Sep 4 17:10:49 2007 New Revision: 572842 URL: http://svn.apache.org/viewvc?rev=572842&view=rev Log: 2007-08-28 Travis Vitek STDCXX-528 * 22.locale.money.get.mt.cpp: New test exercising the thread safety of the std::money_get facet. Added: incubator/stdcxx/trunk/tests/localization/22.locale.money.get.mt.cpp (with props) Added: incubator/stdcxx/trunk/tests/localization/22.locale.money.get.mt.cpp URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/tests/localization/22.locale.money.get.mt.cpp?rev=572842&view=auto ============================================================================== --- incubator/stdcxx/trunk/tests/localization/22.locale.money.get.mt.cpp (added) +++ incubator/stdcxx/trunk/tests/localization/22.locale.money.get.mt.cpp Tue Sep 4 17:10:49 2007 @@ -0,0 +1,468 @@ +/************************************************************************ + * + * 22.locale.money.get.mt.cpp + * + * test exercising the thread safety of the money_get facet + * + * $Id$ + * + *************************************************************************** + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + * + **************************************************************************/ + +#include // for ios +#include // for ostreambuf_iterator +#include // for locale, money_get + +#include // for strlen() + +#include +#include +#include +#include // for rw_strncmp () + + +// maximum number of threads allowed by the command line interface +#define MAX_THREADS 32 +#define MAX_LOOPS 100000 + +// default number of threads (will be adjusted to the number +// of processors/cores later) +int rw_opt_nthreads = 1; + +// the number of times each thread should iterate (unless specified +// otherwise on the command line) +int rw_opt_nloops = 100000; + +// number of locales to use +int rw_opt_nlocales = MAX_THREADS; + +// should all threads share the same set of locale objects instead +// of creating their own? +int rw_opt_shared_locale; + +/**************************************************************************/ + +// array of locale names to use for testing +static const char* +locales [MAX_THREADS]; + +// number of locale names in the array +static std::size_t +nlocales; + +/**************************************************************************/ + +// +struct MyMoneyData +{ + enum { BufferSize = 16 }; + + enum GetId { + get_ldbl, + get_string, + get_max + }; + + // name of the locale the data corresponds to + const char* locale_name_; + + // optionally set to the named locale for threads to share + std::locale locale_; + + // international or domestic format flag + bool intl_; + + // + long double units_; + + // narrow locale specific representations of units_ + char ncs_ [BufferSize]; + std::string ncs_digits_; + +#ifndef _RWSTD_NO_WCHAR_T + + // wide locale specific representations of units_ + wchar_t wcs_ [BufferSize]; + std::wstring wcs_digits_; + +#endif // _RWSTD_NO_WCHAR_T + +} my_money_data [MAX_THREADS]; + + +template +struct MyIos: std::basic_ios +{ + MyIos () { + this->init (0); + } +}; + + +template +struct MyStreambuf: std::basic_streambuf +{ + typedef std::basic_streambuf Base; + + MyStreambuf () + : Base () { + } + + void pubsetg (const charT *gbeg, std::streamsize n) { + this->setg (_RWSTD_CONST_CAST (charT*, gbeg), + _RWSTD_CONST_CAST (charT*, gbeg), + _RWSTD_CONST_CAST (charT*, gbeg) + n); + } + + void pubsetp (charT *pbeg, std::streamsize n) { + this->setp (pbeg, pbeg + n); + } +}; + + +extern "C" { + +bool test_char; // exercise money_get +bool test_wchar; // exercise money_get + + +static void* +thread_func (void*) +{ + MyIos > nio; + MyStreambuf > nsb; + std::basic_string > str; + nio.rdbuf (&nsb); + +#ifndef _RWSTD_NO_WCHAR_T + MyIos > wio; + MyStreambuf > wsb; + std::basic_string > wstr; + wio.rdbuf (&wsb); +#endif // _RWSTD_NO_WCHAR_T + + std::ios_base::iostate state = std::ios_base::goodbit; + +#ifndef _RWSTD_NO_LONG_DOUBLE + long double ldbl = 0.; +#endif // _RWSTD_NO_LONG_DOUBLE + + for (int i = 0; i != rw_opt_nloops; ++i) { + + // save the name of the locale + const MyMoneyData& data = my_money_data [i % nlocales]; + + // construct a named locale, get a reference to the money_get + // facet from it and use it to format a random money value + const std::locale loc = + rw_opt_shared_locale ? data.locale_ + : std::locale (data.locale_name_); + + if (test_char) { + // exercise the narrow char specialization of the facet + + const std::money_get &ng = + std::use_facet >(loc); + + nio.imbue (loc); + nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_)); + + if (i & 1) { + ng.get (std::istreambuf_iterator(&nsb), + std::istreambuf_iterator(), + data.intl_, nio, state, ldbl); + RW_ASSERT (! (state & std::ios_base::failbit)); + RW_ASSERT (! rw_ldblcmp (ldbl, data.units_)); + } + else { + ng.get (std::istreambuf_iterator(&nsb), + std::istreambuf_iterator(), + data.intl_, nio, state, str); + RW_ASSERT (! (state & std::ios_base::failbit)); + RW_ASSERT (! rw_strncmp (str.c_str (), + data.ncs_digits_.c_str ())); + } + } + + // both specializations may be tested at the same time + + if (test_wchar) { + // exercise the wide char specialization of the facet + +#ifndef _RWSTD_NO_WCHAR_T + + const std::money_get &wg = + std::use_facet >(loc); + + wio.imbue (loc); + wsb.pubsetg (data.wcs_, RW_COUNT_OF (data.wcs_)); + + if (i & 1) { + wg.get (std::istreambuf_iterator(&wsb), + std::istreambuf_iterator(), + data.intl_, wio, state, ldbl); + RW_ASSERT (! (state & std::ios_base::failbit)); + RW_ASSERT (! rw_ldblcmp (ldbl, data.units_)); + } + else { + wg.get (std::istreambuf_iterator(&wsb), + std::istreambuf_iterator(), + data.intl_, wio, state, wstr); + RW_ASSERT (! (state & std::ios_base::failbit)); + RW_ASSERT (! rw_strncmp(wstr.c_str (), + data.wcs_digits_.c_str ())); + } + +#endif // _RWSTD_NO_WCHAR_T + + } + } + + return 0; +} + +} // extern "C" + +/**************************************************************************/ + +static int +run_test (int, char**) +{ + MyIos > nio; + MyStreambuf > nsb; + nio.rdbuf (&nsb); + +#ifndef _RWSTD_NO_WCHAR_T + MyIos > wio; + MyStreambuf > wsb; + wio.rdbuf (&wsb); +#endif // _RWSTD_NO_WCHAR_T + + // find all installed locales for which setlocale (LC_ALL) succeeds + const char* const locale_list = + rw_opt_locales ? rw_opt_locales : rw_locales (_RWSTD_LC_ALL); + + const std::size_t maxinx = RW_COUNT_OF (locales); + + for (const char* name = locale_list; + *name; + name += std::strlen (name) + 1) { + + const std::size_t inx = nlocales; + locales [inx] = name; + + // fill in the money and results for this locale + MyMoneyData& data = my_money_data [inx]; + data.locale_name_ = name; + + try { + const std::locale loc (data.locale_name_); + + // exercise domestic formats every other iteration + // and international formats the rest + data.intl_ = 0 == (inx & 5); + + // initialize with random but valid values + long double units = 1.f + inx; + + // exercise postive and negative values + if (inx & 1) + units += (units * 3.14159); + else + units -= (units * 2.71828); + + // local scope + { + const std::money_put &np = + std::use_facet >(loc); + + const std::money_get &ng = + std::use_facet >(loc); + + std::ios::iostate state = std::ios::goodbit; + + nio.imbue (loc); + + // write the value to buffer from long double + nsb.pubsetp (data.ncs_, RW_COUNT_OF (data.ncs_)); + *np.put (std::ostreambuf_iterator(&nsb), + data.intl_, nio, ' ', units) = '\0'; + + rw_fatal (!nio.fail (), __FILE__, __LINE__, + "money_put::put(...) " + "failed for locale(%#s)", data.locale_name_); + + // read the value back so threads know what to expect + nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_)); + ng.get (std::istreambuf_iterator(&nsb), + std::istreambuf_iterator(), + data.intl_, nio, state, data.units_); + + // read back as string, again for threads + nsb.pubsetg (data.ncs_, RW_COUNT_OF (data.ncs_)); + ng.get (std::istreambuf_iterator(&nsb), + std::istreambuf_iterator(), + data.intl_, nio, state, data.ncs_digits_); + + if (state & std::ios_base::failbit) + continue; + } + +#ifndef _RWSTD_NO_WCHAR_T + + // local scope + { + const std::money_put &wp = + std::use_facet >(loc); + + const std::money_get &wg = + std::use_facet >(loc); + + std::ios::iostate state = std::ios::goodbit; + + wio.imbue (loc); + + // write the value to buffer from long double + wsb.pubsetp (data.wcs_, RW_COUNT_OF (data.wcs_)); + *wp.put (std::ostreambuf_iterator(&wsb), + data.intl_, wio, L' ', units) = L'\0'; + + rw_fatal (!nio.fail (), __FILE__, __LINE__, + "money_put::put(...) " + "failed for locale(%#s)", data.locale_name_); + + // read back as string, again for threads + wsb.pubsetg (data.wcs_, RW_COUNT_OF (data.wcs_)); + wg.get (std::istreambuf_iterator(&wsb), + std::istreambuf_iterator(), + data.intl_, wio, state, data.wcs_digits_); + + if (state & std::ios_base::failbit) + continue; + } + +#endif // _RWSTD_NO_WCHAR_T + + if (rw_opt_shared_locale) + data.locale_ = loc; + + nlocales += 1; + + } + catch (...) { + rw_warn (!rw_opt_locales, 0, __LINE__, + "failed to create locale(%#s)", name); + } + + if (nlocales == maxinx || nlocales == std::size_t (rw_opt_nlocales)) + break; + } + + // avoid divide by zero in thread if there are no locales to test + rw_fatal (nlocales != 0, 0, __LINE__, + "failed to create one or more usable locales!"); + + rw_info (0, 0, 0, + "testing std::money_get with %d thread%{?}s%{;}, " + "%zu iteration%{?}s%{;} each, in %zu locales { %{ .*A@} }", + rw_opt_nthreads, 1 != rw_opt_nthreads, + rw_opt_nloops, 1 != rw_opt_nloops, + nlocales, int (nlocales), "%#s", locales); + + rw_info (0, 0, 0, "exercising std::money_get"); + + test_char = true; + test_wchar = false; + + // create and start a pool of threads and wait for them to finish + int result = + rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + + rw_error (result == 0, 0, __LINE__, + "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", + rw_opt_nthreads, thread_func); + +#ifndef _RWSTD_NO_WCHAR_T + + rw_info (0, 0, 0, "exercising std::money_get"); + + test_char = false; + test_wchar = true; + + // start a pool of threads to exercise wstring thread safety + result = + rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + + rw_error (result == 0, 0, __LINE__, + "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", + rw_opt_nthreads, thread_func); + + // exercise both the char and the wchar_t specializations + // at the same time + + rw_info (0, 0, 0, + "exercising both std::money_get " + "and std::money_get"); + + test_char = true; + test_wchar = true; + + // start a pool of threads to exercise wstring thread safety + result = + rw_thread_pool (0, std::size_t (rw_opt_nthreads), 0, thread_func, 0); + + rw_error (result == 0, 0, __LINE__, + "rw_thread_pool(0, %d, 0, %{#f}, 0) failed", + rw_opt_nthreads, thread_func); + +#endif // _RWSTD_NO_WCHAR_T + + return result; +} + +/**************************************************************************/ + +int main (int argc, char *argv[]) +{ +#ifdef _RWSTD_REENTRANT + + // set nthreads to the greater of the number of processors + // and 2 (for uniprocessor systems) by default + rw_opt_nthreads = rw_get_cpus (); + if (rw_opt_nthreads < 2) + rw_opt_nthreads = 2; + +#endif // _RWSTD_REENTRANT + + return rw_test (argc, argv, __FILE__, + "lib.locale.money.get", + "thread safety", run_test, + "|-nloops#0 " // must be non-negative + "|-nthreads#0-* " // must be in [0, MAX_THREADS] + "|-nlocales#0 " // arg must be non-negative + "|-locales= " // must be provided + "|-shared-locale# ", + &rw_opt_nloops, + int (MAX_THREADS), + &rw_opt_nthreads, + &rw_opt_nlocales, + &rw_opt_setlocales, + &rw_opt_shared_locale); +} Propchange: incubator/stdcxx/trunk/tests/localization/22.locale.money.get.mt.cpp ------------------------------------------------------------------------------ svn:eol-style = native Propchange: incubator/stdcxx/trunk/tests/localization/22.locale.money.get.mt.cpp ------------------------------------------------------------------------------ svn:keywords = Id