You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by se...@apache.org on 2005/12/17 00:06:28 UTC
svn commit: r357248 -
/incubator/stdcxx/trunk/tests/diagnostics/19.exceptions.mt.cpp
Author: sebor
Date: Fri Dec 16 15:06:24 2005
New Revision: 357248
URL: http://svn.apache.org/viewcvs?rev=357248&view=rev
Log:
2005-12-16 Martin Sebor <se...@roguewave.com>
STDCXX-4
* 19.exceptions.mt.cpp: New test exercising the thread safety
of the C++ Standard Library exception classes.
Added:
incubator/stdcxx/trunk/tests/diagnostics/19.exceptions.mt.cpp (with props)
Added: incubator/stdcxx/trunk/tests/diagnostics/19.exceptions.mt.cpp
URL: http://svn.apache.org/viewcvs/incubator/stdcxx/trunk/tests/diagnostics/19.exceptions.mt.cpp?rev=357248&view=auto
==============================================================================
--- incubator/stdcxx/trunk/tests/diagnostics/19.exceptions.mt.cpp (added)
+++ incubator/stdcxx/trunk/tests/diagnostics/19.exceptions.mt.cpp Fri Dec 16 15:06:24 2005
@@ -0,0 +1,365 @@
+/***************************************************************************
+ *
+ * exceptions_mt.cpp - test exercising the thread safety
+ * of C++ Standard Library exception classes
+ *
+ * $Id$
+ *
+ ***************************************************************************
+ *
+ * Copyright (c) 1994-2005 Quovadx, Inc., acting through its Rogue Wave
+ * Software division. Licensed 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 <stdexcept> // for exceptions
+#include <string> // for string
+
+#include <cassert> // for assert
+#include <cstdio> // for printf()
+
+#include <alarm.h>
+#include <cmdopt.h>
+#include <driver.h>
+#include <rwthread.h>
+#include <valcmp.h>
+
+/**************************************************************************/
+
+#ifndef NTHREADS
+# ifndef _RWSTD_REENTRANT
+# define MAX_THREADS 0
+# define NTHREADS 0
+# else
+# define MAX_THREADS 32
+# define NTHREADS 4
+# endif // _RWSTD_REENTRANT
+#endif // NTHREADS
+
+/**************************************************************************/
+
+/* extern */ int rw_opt_nloops = 256 * 1024;
+/* extern */ int rw_opt_nthreads = NTHREADS;
+
+/**************************************************************************/
+
+volatile int alarm_expired;
+
+extern "C" {
+
+static void handle_alarm (int)
+{
+ alarm_expired = 1;
+}
+
+} // extern "C"
+
+
+// string to intialize exceptions from
+static const char what_buf [] = {
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789ABCDEF"
+};
+
+
+enum {
+ exception_tag,
+ logic_error_tag,
+ domain_error_tag,
+ invalid_argument_tag,
+ length_error_tag,
+ out_of_range_tag,
+ runtime_error_tag,
+ range_error_tag,
+ overflow_error_tag,
+ underflow_error_tag,
+ Derived_tag
+};
+
+
+struct DerivedException: std::invalid_argument
+{
+ DerivedException (const char *str)
+ : std::invalid_argument (str) { }
+};
+
+
+static void
+throw_exception (unsigned which, const char *what)
+{
+ switch (which) {
+ case exception_tag: throw std::exception ();
+ case logic_error_tag: throw std::logic_error (what);
+ case domain_error_tag: throw std::domain_error (what);
+ case invalid_argument_tag: throw std::invalid_argument (what);
+ case length_error_tag: throw std::length_error (what);
+ case out_of_range_tag: throw std::out_of_range (what);
+ case runtime_error_tag: throw std::runtime_error (what);
+ case range_error_tag: throw std::range_error (what);
+ case overflow_error_tag: throw std::overflow_error (what);
+ case underflow_error_tag: throw std::underflow_error (what);
+ case Derived_tag: throw DerivedException (what);
+
+ default: _RWSTD_ASSERT (!"logic error: bad exception tag");
+ }
+}
+
+/**************************************************************************/
+
+extern "C" void*
+test_single_exception (void *arg)
+{
+ const rw_thread_t* const tid = (rw_thread_t*)arg;
+
+ std::printf ("thread procedure %ld starting...\n", tid->threadno);
+
+ for (unsigned i = 0; i < unsigned (rw_opt_nloops); ++i) {
+
+ if (alarm_expired)
+ break;
+
+ const std::size_t what_len = std::size_t (i % 1024);
+
+ const char* const what = what_buf + sizeof what_buf - what_len - 1;
+
+ const unsigned thrown = i % 11;
+
+ unsigned caught = _RWSTD_UINT_MAX;
+
+ try {
+ // construct and throw an exception object of one
+ // of the predefined standard exception classes
+ // initialized with a distinct what string
+ throw_exception (thrown, what);
+ }
+ catch (DerivedException ex) {
+ // catch the exception object by value and verify
+ // that the pointer returned by what() compares
+ // equal to the string the thrown object was
+ // constructed with
+ caught = Derived_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::domain_error ex) {
+ caught = domain_error_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::invalid_argument ex) {
+ caught = invalid_argument_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::length_error ex) {
+ caught = length_error_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::out_of_range ex) {
+ caught = out_of_range_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::range_error ex) {
+ caught = range_error_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::overflow_error ex) {
+ caught = overflow_error_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::underflow_error ex) {
+ caught = underflow_error_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::logic_error ex) {
+ caught = logic_error_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::runtime_error ex) {
+ caught = runtime_error_tag;
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+ catch (std::exception ex) {
+ caught = exception_tag;
+ rw_strncmp (ex.what (), what);
+ }
+
+ // verify that an object of the thrown type was caught
+ assert (caught == thrown);
+ }
+
+ return 0;
+}
+
+/**************************************************************************/
+
+static void
+test_multi (unsigned i, unsigned nactive)
+{
+ const std::size_t what_len = (i + nactive) % sizeof what_buf;
+
+ const char* const what = what_buf + sizeof what_buf - what_len - 1;
+
+ const unsigned thrown = (i + nactive) % 10 + 1;
+
+ try {
+ // construct and throw an exception object of a distinct type
+ // with a distinct what string at each level of recursion
+ throw_exception (thrown, what);
+ }
+ catch (std::exception &ex) {
+
+ // recursively throw another exception while the caught
+ // exception object is still active
+ if (nactive)
+ test_multi (i, nactive - 1);
+
+ // verify that the caught object's what string matches
+ // the string the object was originally constructed with
+ assert (0 == rw_strncmp (ex.what (), what));
+ }
+}
+
+extern "C" void*
+test_multi_exceptions (void *arg)
+{
+ const rw_thread_t* const tid = (rw_thread_t*)arg;
+
+ std::printf ("thread procedure %ld starting...\n", tid->threadno);
+
+ for (unsigned i = 0; i < unsigned (rw_opt_nloops); ++i) {
+
+ if (alarm_expired)
+ break;
+
+ // exercise up to 4 simultaneously active exceptions
+ test_multi (i, i % 4);
+ }
+
+ return 0;
+}
+
+/**************************************************************************/
+
+static int
+run_test (int, char**)
+{
+ // check that the number of threads is valid
+ rw_fatal (-1 < rw_opt_nthreads && rw_opt_nthreads < MAX_THREADS, 0, 0,
+ "number of threads must be in the range [0, %d), got %d",
+ MAX_THREADS, rw_opt_nthreads);
+
+ // check that the number of loops is non-negative
+ rw_fatal (-1 < rw_opt_nloops, 0, 0,
+ "number of loops must be non-negative, got %d",
+ rw_opt_nloops);
+
+ // get the current alarm (if any) set for the test
+ // on the command line without resetting it
+ const unsigned max_sec = rw_alarm (0, rw_sig_hold);
+
+ // compute a shorter timeout for each of the two subtests
+ const unsigned nsec = 3 < max_sec ? max_sec / 2 : 0;
+
+ rw_info (0, 0, 0,
+ "single active exception per thread"
+ "%{?}; timeout in %u seconds%{;}",
+ 0 != max_sec, nsec ? nsec : max_sec);
+
+ // set a shorter alarm if possible
+ if (nsec) {
+ alarm_expired = 0;
+ rw_alarm (nsec, handle_alarm);
+ }
+
+ const std::size_t nthreads = std::size_t (rw_opt_nthreads);
+
+#if 0 < NTHREADS
+
+ rw_fatal (0 == rw_thread_pool (0, nthreads, 0, test_single_exception, 0),
+ 0, __LINE__, "rw_thread_pool() failed");
+
+#else // if !(0 < NTHREADS)
+
+ rw_thread_t tid;
+ std::memset (&tid, 0, sizeof tid);
+
+ test_single_exception (&tid);
+
+#endif // NTHREADS
+
+ rw_info (0, 0, 0,
+ "multiple active exceptions per thread"
+ "%{?}; timeout in %u seconds%{;}",
+ 0 != max_sec, nsec ? nsec : max_sec);
+
+ // set another shorter alarm if possible
+ if (nsec) {
+ alarm_expired = 0;
+ rw_alarm (nsec, handle_alarm);
+ }
+
+#if 0 < NTHREADS
+
+ rw_fatal (0 == rw_thread_pool (0, nthreads, 0, test_multi_exceptions, 0),
+ 0, __LINE__, "rw_thread_pool() failed");
+
+#else // if !(0 < NTHREADS)
+
+ test_multi_exceptions (&tid);
+
+#endif // NTHREADS
+
+ // restore the original alarm to go off approximately
+ // when the original alar would have if it hadn't been
+ // replaced above
+ if (nsec)
+ rw_alarm (2 * nsec, rw_sig_restore);
+
+ return 0;
+}
+
+/**************************************************************************/
+
+int main (int argc, char *argv[])
+{
+ return rw_test (argc, argv, __FILE__,
+ "lib.std.exceptions",
+ "thread safety", run_test,
+ "|-nloops# "
+ "|-nthreads#",
+ &rw_opt_nloops,
+ &rw_opt_nthreads);
+}
Propchange: incubator/stdcxx/trunk/tests/diagnostics/19.exceptions.mt.cpp
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: incubator/stdcxx/trunk/tests/diagnostics/19.exceptions.mt.cpp
------------------------------------------------------------------------------
svn:keywords = Id