first commit

This commit is contained in:
Jose Caban
2025-06-07 11:34:38 -04:00
commit 0eb2d7c07d
4708 changed files with 1500614 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
/***************************************************************************
*
* 18.csetjmp.cpp - test exercising [support.runtime], header <csetjmp>
*
* $Id: 18.csetjmp.cpp 593007 2007-11-08 04:30:45Z sebor $
*
***************************************************************************
*
* 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.
*
* Copyright 2007 Rogue Wave Software, Inc.
*
**************************************************************************/
#include <csetjmp>
#include <driver.h>
/**************************************************************************/
std::jmp_buf env;
void test_longjmp (int arg)
{
std::longjmp (env, arg);
rw_assert (0, 0, __LINE__,
"call to std::longjmp(..., %d) returned", arg);
}
/**************************************************************************/
static int
run_test (int, char**)
{
#ifdef longjmp
// longjmp must not be #defined as a macro
rw_assert (0, 0, __LINE__, "longjmp #defined as a macro");
#endif // longjmp
#ifdef jmp_buf
//jmp_buf must not be #defined as a macro
rw_assert (0, 0, __LINE__, "jmp_buf #defined as a macro");
#endif // jmp_buf
#ifndef setjmp
//setjmp must be #defined as a macro
rw_assert (0, 0, __LINE__, "macro setjmp not #defined");
#endif // setjmp
// verify that setjmp works
// using volatile to work around a gcc optimizer bug:
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34024
volatile int arg = 1;
int result;
result = setjmp (env);
if (0 == result) {
test_longjmp (arg);
rw_assert (0, 0, __LINE__,
"call to std::longjmp(..., %d) returned", arg);
}
else {
rw_assert (arg == result, 0, __LINE__,
"std::longjmp(..., %d) returned %d from setjmp()",
arg, result);
// repeat a couple more times
if (arg < 3)
test_longjmp (++arg);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"support.runtime",
"header <csetjmp>",
run_test,
"",
(void*)0);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,204 @@
/***************************************************************************
*
* 18.limits.cvqual.cpp:
*
* Test exercising lib.numeric.limits, numeric_limits specializations
* on cv-qualified scalar types. See DR 559 for details:
* http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#559
*
* $Id: 18.limits.cvqual.cpp 580483 2007-09-28 20:55:52Z sebor $
*
***************************************************************************
*
* 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.
*
* Copyright 2006-2007 Rogue Wave Software, Inc.
*
**************************************************************************/
#include <limits>
#include <driver.h>
/**************************************************************************/
template <class T>
struct UserType
{
const T val_;
UserType (T val = T ()): val_ (val) { /* empty */}
operator T () const { return val_; }
};
template <class T, class CVQualifiedT>
void test_limits (const volatile T*, CVQualifiedT*,
const char *tname,
const char *quals)
{
#ifndef _RWSTD_NO_EXT_CV_QUALIFIED_LIMITS
typedef std::numeric_limits<T> limits;
typedef std::numeric_limits<CVQualifiedT> cv_limits;
// verify that the member has the same value as the same member
// of a specialization of numeric_limits on the cv-qualified T
# define TEST(member) \
rw_assert (limits::member == cv_limits::member, 0, __LINE__, \
"numeric_limits<%s>::%s == numeric_limits<%s %1$s>::%2$s", \
tname, #member, quals)
#else // if defined (_RWSTD_NO_EXT_CV_QUALIFIED_LIMITS)
typedef std::numeric_limits<UserType<T> > limits;
typedef std::numeric_limits<CVQualifiedT> cv_limits;
// verify that the member has the same value as the same member
// of a specialization of numeric_limits on some user-defined T
// (i.e., the primary template)
# define TEST(member) \
rw_assert (limits::member == cv_limits::member, 0, __LINE__, \
"numeric_limits<%s>::%s == numeric_limits<%s %1$s>::%2$s", \
tname, #member, quals)
#endif // _RWSTD_NO_EXT_CV_QUALIFIED_LIMITS
TEST (is_specialized);
TEST (min ());
TEST (max ());
TEST (digits);
TEST (digits10);
TEST (is_signed);
TEST (is_integer);
TEST (is_exact);
TEST (radix);
TEST (epsilon ());
TEST (round_error ());
TEST (min_exponent);
TEST (min_exponent10);
TEST (max_exponent);
TEST (max_exponent10);
TEST (has_infinity);
TEST (has_quiet_NaN);
TEST (has_signaling_NaN);
TEST (has_denorm);
TEST (has_denorm_loss);
TEST (infinity ());
if (limits::is_integer) {
TEST (quiet_NaN ());
TEST (signaling_NaN ());
}
else {
const bool expect = limits::has_quiet_NaN;
rw_assert (expect == (limits::quiet_NaN () != cv_limits::quiet_NaN ()),
0, __LINE__,
"numeric_limits<%s>::qNaN() %{?}!=%{:}==%{;} "
"numeric_limits<%s %1$s>::qNaN ()",
tname, expect, quals);
}
TEST (denorm_min ());
TEST (is_iec559);
TEST (is_bounded);
TEST (is_modulo);
TEST (traps);
TEST (tinyness_before);
TEST (round_style);
}
/**************************************************************************/
template <class T>
void test_limits (const volatile T*, const char *tname)
{
typedef const T const_T;
typedef volatile T volatile_T;
typedef const volatile T const_volatile_T;
rw_info (0, 0, __LINE__,
"std::numeric_limits<T> with T = cv-qualified %s", tname);
test_limits ((T*)0, (const_T*)0, tname, "const");
test_limits ((T*)0, (volatile_T*)0, tname, "volatile");
test_limits ((T*)0, (const_volatile_T*)0, tname, "const volatile");
}
/**************************************************************************/
static int
run_test (int, char*[])
{
#undef TEST
#define TEST(T) test_limits ((T*)0, _RWSTD_STRSTR (T))
#ifndef _RWSTD_NO_NATIVE_BOOL
TEST (bool);
#endif // _RWSTD_NO_NATIVE_BOOL
TEST (char);
TEST (signed char);
TEST (unsigned char);
TEST (short);
TEST (unsigned short);
TEST (int);
TEST (unsigned);
TEST (long);
TEST (unsigned long);
#ifdef _RWSTD_LONG_LONG
TEST (_RWSTD_LONG_LONG);
TEST (unsigned _RWSTD_LONG_LONG);
#endif
TEST (float);
TEST (double);
#ifndef _RWSTD_NO_LONG_DOUBLE
TEST (long double);
#endif // _RWSTD_NO_LONG_DOUBLE
#ifndef _RWSTD_NO_NATIVE_WCHAR_T
TEST (wchar_t);
#endif // _RWSTD_NO_NATIVE_WCHAR_T
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.numeric.limits",
#ifdef _RWSTD_NO_EXT_CV_QUALIFIED_LIMITS
"testing the absence of "
#endif // _RWSTD_NO_EXT_CV_QUALIFIED_LIMITS
"specializations on cv-qualifed types",
run_test,
0,
(void*)0);
}

View File

@@ -0,0 +1,216 @@
/***************************************************************************
*
* 18.limits_traps.cpp - test exercising std::numeric_limits::traps
*
* $Id: 18.limits.traps.cpp 515262 2007-03-06 19:28:51Z sebor $
*
***************************************************************************
*
* 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.
*
* Copyright 2005-2006 Rogue Wave Software.
*
**************************************************************************/
#include <limits>
#include <csignal> // for SIGFPE, signal
#include <any.h> // for rw_any_t
#include <cmdopt.h> // for rw_enabled()
#include <driver.h> // for rw_test(), ...
/**************************************************************************/
#ifdef _RWSTD_OS_LINUX
// use siglongjmp() and sigsetjmp() on Linux to avoid
// http://sourceware.org/bugzilla/show_bug.cgi?id=2351
# include <setjmp.h> // for siglongjmp, sigsetjmp
jmp_buf jmp_env;
extern "C" {
void handle_fpe (int)
{
siglongjmp (jmp_env, 1);
}
} // extern "C"
# define RW_SIGSETJMP(env, signo) sigsetjmp (env, signo)
#else // if !defined (_RWSTD_OS_LINUX)
# include <csetjmp> // for longjmp, setjmp
std::jmp_buf jmp_env;
extern "C" {
void handle_fpe (int)
{
std::longjmp (jmp_env, 1);
}
} // extern "C"
# define RW_SIGSETJMP(env, ignore) setjmp (env)
#endif // _RWSTD_OS_LINUX
/**************************************************************************/
#ifdef _MSC_VER
// silence useless MSVC warnings:
// 4800: 'int' : forcing value to bool 'true' or 'false'
// 4804: '/' : unsafe use of type 'bool' in operation
# pragma warning (disable: 4800 4804)
// use Structured Exception Handling to detect arithmetic exceptions
# define TRY __try
# define EXCEPT(arg) __except (arg)
#else
# define TRY if (1)
# define EXCEPT(ignore) else if (0)
#endif // _MSC_VER
template <class numT>
inline void
try_trap (const volatile numT &one, const volatile numT &zero,
numT &result, bool &trapped)
{
TRY {
result = one / zero;
}
EXCEPT (1) {
// Windows SEH hackery
trapped = true;
}
}
template <class numT>
numT test_traps (numT, int lineno, bool)
{
static const char* const tname = rw_any_t (numT ()).type_name ();
if (!rw_enabled (tname)) {
rw_note (0, 0, 0, "numeric_limits<%s>::traps test disabled", tname);
return numT ();
}
const bool traps = std::numeric_limits<numT>::traps;
rw_info (0, 0, 0, "std::numeric_limits<%s>::traps = %b", tname, traps);
#ifdef SIGFPE
std::signal (SIGFPE, handle_fpe);
#else // if !defined (SIGFPE)
if (!rw_warn (!traps, 0, lineno,
"SIGFPE not #defined and numeric_limits<%s>::traps == %b, "
"cannot test", tname, traps)) {
return numT ();
}
#endif // SIGFPE
numT result = numT ();
// set the environment
const int jumped = RW_SIGSETJMP (jmp_env, SIGFPE);
volatile numT zero = numT (jumped);
volatile numT one = numT (1);
bool trapped = false;
if (jumped) {
// setjmp() call above returned from the SIGFPE handler
// as a result of a floating point exception triggered
// by the division by zero in the else block below
result = zero / one;
trapped = true;
}
else {
// setjmp() call above returned after setting up the jump
// environment; see of division by zero traps (if so, it
// will generate a SIGFPE which will be caught by the
// signal hanlder above and execution will resume by
// returning from setjmp() above again, but this time
// with a non-zero value
try_trap (one, zero, result, trapped);
}
rw_assert (trapped == traps, 0, lineno,
"numeric_limits<%s>::traps == %b, got %b",
tname, trapped, traps);
return result;
}
/**************************************************************************/
static int
run_test (int, char*[])
{
#define TEST(T, floating) test_traps ((T)0, __LINE__, floating)
#ifndef _RWSTD_NO_NATIVE_BOOL
TEST (bool, false);
#endif // _RWSTD_NO_NATIVE_BOOL
TEST (char, false);
TEST (signed char, false);
TEST (unsigned char, false);
TEST (short, false);
TEST (unsigned short, false);
TEST (int, false);
TEST (unsigned int, false);
TEST (long, false);
TEST (unsigned long, false);
#ifndef _RWSTD_NO_LONG_LONG
TEST (_RWSTD_LONG_LONG, false);
TEST (unsigned _RWSTD_LONG_LONG, false);
#endif // _RWSTD_NO_LONG_LONG
#ifndef _RWSTD_NO_NATIVE_WCHAR_T
TEST (wchar_t, false);
#endif // _RWSTD_NO_NATIVE_WCHAR_T
TEST (float, true);
TEST (double, true);
#ifndef _RWSTD_NO_LONG_DOUBLE
TEST (long double, true);
#endif // _RWSTD_NO_LONG_DOUBLE
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"lib.numeric.limits.members",
"traps data member",
run_test,
0, 0);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,654 @@
/***************************************************************************
*
* 18.numeric.special.int.cpp - tests specializations of the numeric_limits
* class template on integer types
*
* $Id: 18.numeric.special.int.cpp 648752 2008-04-16 17:01:56Z faridz $
*
***************************************************************************
*
* 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.
*
* Copyright 2004-2008 Rogue Wave Software, Inc.
*
**************************************************************************/
#include <limits> // for numeric_limits
#include <climits> // for {CHAR,SHRT,INT,LONG}_{MIN,MAX}, etc.
#include <cstdio> // for sprintf()
#include <driver.h>
template <class T>
struct Limits
{
enum { is_specialized = false };
static T (min) () { return 0; }
static T (max) () { return 0; }
enum { digits };
enum { digits10 };
enum { is_signed };
enum { is_integer };
enum { is_exact };
enum { radix };
enum { is_bounded = false };
static bool is_modulo () { return false; }
static int compute_digits10 () {
return 0;
}
};
// edg (DEC cxx and others) gives an error in strict ANSI mode
// for things like INT_MAX + 1; this works around that error...
template <class T>
inline bool is_modulo (T _max)
{
// avoid MSVC warning C4800: 'int' :
// forcing value to bool 'true' or 'false' (performance warning)
T max_plus_one = _max;
return ++max_plus_one < _max;
}
_RWSTD_SPECIALIZED_FUNCTION
inline bool is_modulo (bool)
{
return false;
}
_RWSTD_SPECIALIZED_CLASS
struct Limits<int>
{
enum { is_specialized = true };
static int (min) () { return INT_MIN; }
static int (max) () { return INT_MAX; }
enum { digits = CHAR_BIT * sizeof (int) - 1 };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = true };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%d", INT_MAX) - 1;
}
};
#ifndef _RWSTD_NO_BOOL
_RWSTD_SPECIALIZED_CLASS
struct Limits<bool>
{
enum { is_specialized = true };
static bool (min) () { return false; }
static bool (max) () { return true; }
enum { digits = 1 };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = false };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
return 0;
}
};
#endif //_RWSTD_NO_BOOL
_RWSTD_SPECIALIZED_CLASS
struct Limits<char>
{
enum { is_specialized = true };
static char (min) () { return CHAR_MIN; }
static char (max) () { return CHAR_MAX; }
enum { is_signed = CHAR_MAX == SCHAR_MAX ? true : false };
enum {
digits = is_signed ? CHAR_BIT * sizeof (char) -1
: CHAR_BIT * sizeof (char)
};
enum { digits10 = (digits * 301) / 1000 };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%d", (unsigned char)CHAR_MAX) - 1;
}
};
_RWSTD_SPECIALIZED_CLASS
struct Limits<signed char>
{
enum { is_specialized = true };
static signed char (min) () { return SCHAR_MIN; }
static signed char (max) () { return SCHAR_MAX; }
enum { digits = CHAR_BIT * sizeof (signed char) - 1 };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = true };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%d", (unsigned char)SCHAR_MAX) - 1;
}
};
_RWSTD_SPECIALIZED_CLASS
struct Limits<unsigned char>
{
enum { is_specialized = true };
static unsigned char (min) () { return 0; }
static unsigned char (max) () { return UCHAR_MAX; }
enum { digits = CHAR_BIT * sizeof (unsigned char) };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = false };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%d", (unsigned char)UCHAR_MAX) - 1;
}
};
#ifndef _RWSTD_NO_NATIVE_WCHAR_T
_RWSTD_SPECIALIZED_CLASS
struct Limits<wchar_t>
{
enum { is_specialized = true };
static wchar_t (min) () {
return wchar_t (-1) > wchar_t (0) ? 0
: sizeof (wchar_t) == sizeof (short) ? wchar_t (SHRT_MIN)
: sizeof (wchar_t) == sizeof (int) ? wchar_t (INT_MIN)
: sizeof (wchar_t) == sizeof (long) ? wchar_t (LONG_MIN)
: wchar_t (SCHAR_MIN);
}
static wchar_t (max) () {
return wchar_t (-1) > wchar_t (0) ?
( sizeof (wchar_t) == sizeof (short) ? wchar_t (USHRT_MAX)
: sizeof (wchar_t) == sizeof (int) ? wchar_t (UINT_MAX)
: sizeof (wchar_t) == sizeof (long) ? wchar_t (ULONG_MAX)
: wchar_t (SCHAR_MAX))
: ( sizeof (wchar_t) == sizeof (short) ? wchar_t (SHRT_MAX)
: sizeof (wchar_t) == sizeof (int) ? wchar_t (INT_MAX)
: sizeof (wchar_t) == sizeof (long) ? wchar_t (LONG_MAX)
: wchar_t (UCHAR_MAX));
}
enum { is_signed = wchar_t (0) > wchar_t (~0) };
enum {
digits = is_signed ? CHAR_BIT * sizeof (wchar_t) - 1
: CHAR_BIT*sizeof(wchar_t)
};
enum { digits10 = (digits * 301) / 1000 };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%u", wchar_t (~0)) - 1;
}
};
#endif //_RWSTD_NO_NATIVE_WCHAR_T
_RWSTD_SPECIALIZED_CLASS
struct Limits<short>
{
enum { is_specialized = true };
static short (min) () { return SHRT_MIN; }
static short (max) () { return SHRT_MAX; }
enum { digits = CHAR_BIT * sizeof (short) - 1 };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = true };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%d", (int)SHRT_MAX) - 1;
}
};
_RWSTD_SPECIALIZED_CLASS
struct Limits<long>
{
enum { is_specialized = true };
static long (min) () { return LONG_MIN; }
static long (max) () { return LONG_MAX; }
enum { digits = CHAR_BIT * sizeof(long)-1 };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = true };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%ld", LONG_MAX) - 1;
}
};
_RWSTD_SPECIALIZED_CLASS
struct Limits <unsigned short>
{
enum { is_specialized = true };
static unsigned short (min) () { return 0; }
static unsigned short (max) () { return USHRT_MAX; }
enum { digits = CHAR_BIT * sizeof(unsigned short) };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = false };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%u", unsigned (USHRT_MAX)) - 1;
}
};
_RWSTD_SPECIALIZED_CLASS
struct Limits<unsigned int>
{
enum { is_specialized = true };
static unsigned int (min) () { return 0; }
static unsigned int (max) () { return UINT_MAX; }
enum { digits = CHAR_BIT * sizeof(unsigned int) };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = false };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%u", UINT_MAX) - 1;
}
};
_RWSTD_SPECIALIZED_CLASS
struct Limits<unsigned long>
{
enum { is_specialized = true };
static unsigned long (min) () { return 0; }
static unsigned long (max) () { return ULONG_MAX; }
enum { digits = CHAR_BIT * sizeof(unsigned long) };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = false };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
return std::sprintf (buf, "%lu", ULONG_MAX) - 1;
}
};
#ifdef _RWSTD_LONG_LONG
_RWSTD_SPECIALIZED_CLASS
struct Limits<_RWSTD_LONG_LONG>
{
typedef _RWSTD_LONG_LONG LLong;
enum { is_specialized = true };
static LLong (min) () {
typedef unsigned _RWSTD_LONG_LONG ULLong;
ULLong zero = 0; // prevent an EDG eccp warning #68-D
return ~zero / ULLong (2) + ULLong (1);
}
static LLong (max) () {
typedef unsigned _RWSTD_LONG_LONG ULLong;
return ~ULLong (0) / ULLong (2);
}
enum { digits = CHAR_BIT * sizeof (LLong) - 1 };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = true };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
const char fmt[] = "%" _RWSTD_LLONG_PRINTF_PREFIX "u";
return std::sprintf (buf, fmt, (max) ()) - 1;
}
};
_RWSTD_SPECIALIZED_CLASS
struct Limits<unsigned _RWSTD_LONG_LONG>
{
typedef unsigned _RWSTD_LONG_LONG ULLong;
enum { is_specialized = true };
static ULLong (min) () { return 0; }
static ULLong (max) () { return ~ULLong (0); }
enum { digits = CHAR_BIT * sizeof (ULLong) };
enum { digits10 = (digits * 301) / 1000 };
enum { is_signed = false };
enum { is_integer = true };
enum { is_exact = true };
enum { radix = 2 };
enum { is_bounded = true };
static bool is_modulo () { return ::is_modulo ((max)()); }
static int compute_digits10 () {
char buf [80];
const char fmt[] = "%" _RWSTD_LLONG_PRINTF_PREFIX "i";
// work around libc bugs (e.g., glibc on Linux)
const int n = std::sprintf (buf, fmt, (max) ());
if (n < Limits<unsigned>::digits10)
return digits10;
return n - 1;
}
};
#endif // _RWSTD_LONG_LONG
template <class T>
void run_test (T*, const char *tname, const char *fmt)
{
typedef std::numeric_limits<T> limT;
typedef Limits<T> Traits;
RW_ASSERT (0 != tname);
RW_ASSERT (0 != fmt);
#if !defined (__EDG__) || __EDG_VERSION__ > 245
# define ASSERT(expr, fmt) \
/* verify that `expr' is a constant integral expression */ \
{ enum { is_const_integral_expression = limT::expr }; } \
rw_assert (limT::expr == int (Traits::expr), 0, __LINE__, \
"std::numeric_limits<%s>::" #expr \
" == %{@}, got %{@}", \
tname, fmt, Traits::expr, fmt, limT::expr)
#else // if EDG eccp < 3.0
// working around an EDG eccp 2.4x ICE
# define ASSERT(expr) \
/* verify that `expr' is a constant integral expression */ \
switch (limT::expr) { case limT::expr: break; }; \
rw_assert (limT::expr == int (Traits::expr), 0, __LINE__, \
"std::numeric_limits<%s>::" #expr \
"== %{@}, got %{@}", \
tname, fmt, Traits::expr, fmt, limT::expr)
#endif // EDG eccp < 3.0
#define ASSERT_0(expr, fmt) \
rw_assert (!limT::expr, 0, __LINE__, \
"std::numeric_limits<%s>::" #expr " == 0, got %{@}", \
tname, fmt, limT::expr)
ASSERT (is_specialized, "%#b");
// 18.2.1.2, p1
rw_info (0, 0, __LINE__,
"std::numeric_limits<%s>::min() == %{@}",
tname, fmt, (Traits::min ()));
rw_assert ((limT::min)() == (Traits::min)(), 0, __LINE__,
"std::numeric_limits<%s>::min() == %{@}, got %{@}",
tname, fmt, (Traits::min)(), fmt, (limT::min)());
// 18.2.1.2, p4
rw_info (0, 0, __LINE__,
"std::numeric_limits<%s>::max() == %{@}",
tname, fmt, (Traits::max ()));
rw_assert ((limT::max)() == (Traits::max)(), 0, __LINE__,
"std::numeric_limits<%s>::max() == %{@}, got %{@}",
tname, fmt, (Traits::max)(), fmt, (limT::max)());
// 18.2.1.2, p6
ASSERT (digits, "%d");
// 18.2.1.2, p9
ASSERT (digits10, "%d");
rw_assert (limT::digits10 == Traits::compute_digits10 (), 0, __LINE__,
"std::numeric_limits<%s>::digits10 == %d (computed), got %d",
tname, Traits::compute_digits10 (), limT::digits10);
// 18.2.1.2, p11
ASSERT (is_signed, "%b");
// 18.2.1.2, p13
ASSERT (is_integer, "%b");
// 18.2.1.2, p15
ASSERT (is_exact, "%b");
// 18.2.1.2, p17
ASSERT (radix, "%i");
// 18.2.1.2, p20
ASSERT_0 (epsilon (), fmt);
// 18.2.1.2, p22
ASSERT_0 (round_error (), fmt);
// 18.2.1.2, p23
ASSERT_0 (min_exponent, "%i");
// 18.2.1.2, p25
ASSERT_0 (min_exponent10, "%i");
// 18.2.1.2, p27
ASSERT_0 (max_exponent, "%i");
// 18.2.1.2, p29
ASSERT_0 (max_exponent10, "%i");
// 18.2.1.2, p31
ASSERT_0 (has_infinity, "%b");
// 18.2.1.2, p34
ASSERT_0 (has_quiet_NaN, "%b");
// 18.2.1.2, p37
ASSERT_0 (has_signaling_NaN, "%b");
// 18.2.1.2, p40
ASSERT_0 (has_denorm, "%b");
// 18.2.1.2, p42
ASSERT_0 (has_denorm_loss, "%b");
// 18.2.1.2, p43
ASSERT_0 (infinity (), fmt);
// 18.2.1.2, p45
ASSERT_0 (quiet_NaN (), fmt);
// 18.2.1.2, p47
ASSERT_0 (signaling_NaN (), fmt);
// 18.2.1.2, p49
ASSERT_0 (denorm_min (), fmt);
// 18.2.1.2, p52
ASSERT_0 (is_iec559, "%b");
// 18.2.1.2, p54
ASSERT (is_bounded, "%b");
// 18.2.1.2, p56
rw_assert (limT::is_modulo == Traits::is_modulo (), 0, __LINE__,
"std::numeric_limits<%s>::is_modulo == %#b",
tname, Traits::is_modulo ());
// 18.2.1.2, p59
ASSERT_0 (traps, "%b");
// 18.2.1.2, p61
ASSERT_0 (tinyness_before, "%b");
// 18.2.1.2, p63
rw_assert (limT::round_style == int (std::round_toward_zero), 0, __LINE__,
"std::numeric_limits<%s>::round_style == %d",
tname, std::round_toward_zero);
}
static int
run_test (int, char**)
{
#define TEST(T, fmt) run_test ((T*)0, #T, fmt)
#ifndef _RWSTD_NO_BOOL
TEST (bool, "%#b");
#endif //_RWSTD_NO_BOOL
TEST (char, "%{#c}");
TEST (signed char, "%{#c}");
TEST (unsigned char, "%{#c}");
TEST (short, "%hi");
TEST (unsigned short, "%hu");
TEST (int, "%i");
TEST (unsigned int, "%u");
TEST (long, "%li");
TEST (unsigned long, "%lu");
#ifdef _RWSTD_LONG_LONG
TEST (_RWSTD_LONG_LONG, "%lli");
TEST (unsigned _RWSTD_LONG_LONG, "%llu");
#endif // _RWSTD_LONG_LONG
#ifndef _RWSTD_NO_NATIVE_WCHAR_T
TEST (wchar_t, "%{#lc}");
#endif //_RWSTD_NO_NATIVE_WCHAR_T
TEST (void*, "%#p");
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"numeric.special",
"integer specializations",
run_test,
"",
(void*)0);
}

View File

@@ -0,0 +1,110 @@
/***************************************************************************
*
* 18.setjmp.cpp - test exercising [support.runtime], header <setjmp.h>
*
* $Id: 18.setjmp.cpp 593007 2007-11-08 04:30:45Z sebor $
*
***************************************************************************
*
* 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.
*
* Copyright 2007 Rogue Wave Software, Inc.
*
**************************************************************************/
#include <setjmp.h>
#include <driver.h>
/**************************************************************************/
jmp_buf env;
void test_longjmp (int arg)
{
longjmp (env, arg);
rw_assert (0, 0, __LINE__,
"call to longjmp(..., %d) returned", arg);
}
/**************************************************************************/
static int
run_test (int, char**)
{
#ifdef longjmp
// longjmp must not be #defined as a macro
rw_assert (0, 0, __LINE__, "longjmp #defined as a macro");
#endif // longjmp
#ifdef jmp_buf
//jmp_buf must not be #defined as a macro
rw_assert (0, 0, __LINE__, "jmp_buf #defined as a macro");
#endif // jmp_buf
#ifndef setjmp
//setjmp must be #defined as a macro
rw_assert (0, 0, __LINE__, "macro setjmp not #defined");
#endif // setjmp
// verify that setjmp works
// using volatile to work around a gcc optimizer bug:
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34024
volatile int arg = 1;
int result;
result = setjmp (env);
if (0 == result) {
test_longjmp (arg);
rw_assert (0, 0, __LINE__,
"call to longjmp(..., %d) returned", arg);
}
else {
rw_assert (arg == result, 0, __LINE__,
"longjmp(..., %d) returned %d from setjmp()",
arg, result);
// repeat a couple more times
if (arg < 3)
test_longjmp (++arg);
}
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
"support.runtime",
"header <setjmp.h>",
run_test,
"",
(void*)0);
}

View File

@@ -0,0 +1,478 @@
/***************************************************************************
*
* 18.support.dynamic.cpp - test exercising [lib.support.dynamic]
*
* $Id: 18.support.dynamic.cpp 648752 2008-04-16 17:01:56Z faridz $
*
***************************************************************************
*
* 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.
*
* Copyright 2001-2008 Rogue Wave Software.
*
**************************************************************************/
#include <new>
#include <memory>
#include <driver.h>
#include <rw/_defs.h>
#include <rw/_error.h>
#include <cstdlib> // for malloc() and free()
#include <cstring> // for strlen()
#ifdef _MSC_VER
// verify that <new> et al can coexist with MSVC's <new.h>
# include <new.h>
#endif
/**************************************************************************/
// detects recursive implementation of operator new (size_t, nothrow_t)
static int recursive_new_nothrow = 0;
static int recursive_delete_nothrow = 0;
// MemoryAllocator is used to replace the global new and delete
// in order to test conformance of of the other operators that
// might be defined in <new>
struct MemoryAllocator
{
MemoryAllocator () {
init ();
}
void* operatorNew (std::size_t n) _THROWS ((std::bad_alloc)) {
_allocPtr = 0;
_newCalled = true;
_bytesRequested = n;
if (_failAlloc) {
_failAlloc = false;
_THROW (std::bad_alloc ());
}
#if !defined (_RWSTD_NO_EXT_OPERATOR_NEW) && \
defined (_RWSTD_NO_OPERATOR_NEW_NOTHROW)
// test our implementation of
// ::operator new(size_t, const std::nothrow)
// this operator must not be implemented in terms
// of ::operator new(size_t) to prevent recursion
if (recursive_new_nothrow++)
_allocPtr = std::malloc (_bytesRequested);
else
_allocPtr = ::operator new (_bytesRequested, std::nothrow);
--recursive_new_nothrow;
#else
_allocPtr = std::malloc (_bytesRequested);
#endif
return _allocPtr;
}
void operatorDelete (void* ptr) _THROWS (()) {
_deallocPtr = ptr;
#if !defined (_RWSTD_NO_EXT_OPERATOR_NEW) && \
defined (_RWSTD_NO_OPERATOR_NEW_NOTHROW)
// memory allocated by our nothrow operator new()
if (recursive_delete_nothrow++ || recursive_new_nothrow)
std::free (ptr);
else
::operator delete (ptr, std::nothrow);
--recursive_delete_nothrow;
#else
std::free (ptr);
#endif
_deleteCalled = true;
}
void init () {
_newCalled = _deleteCalled = _failAlloc = false;
_bytesRequested = 0;
_deallocPtr = _allocPtr = 0;
}
bool newCalled () {
bool tmp = _newCalled;
_newCalled = 0;
return tmp;
}
bool deleteCalled () {
bool tmp = _deleteCalled;
_deleteCalled = 0;
return tmp;
}
std::size_t _bytesRequested;
bool _newCalled;
bool _deleteCalled;
bool _failAlloc;
void* _allocPtr;
void* _deallocPtr;
};
// static instance of memory allocator
static MemoryAllocator alloc;
/**************************************************************************/
// replace the global operators with MemoryAllocator versions
void* operator new (std::size_t size) _THROWS ((std::bad_alloc))
{
return alloc.operatorNew (size);
}
void operator delete (void* p) _THROWS (())
{
alloc.operatorDelete (p);
}
/**************************************************************************/
#define TEST_OP_THROWS(expr,cond,tag) \
_TRY { \
alloc._failAlloc = true; \
expr; \
rw_assert (cond, 0, __LINE__, tag); \
} \
_CATCH (std::bad_alloc) { \
RW_ASSERT (!cond, 0, __LINE__, tag); \
} \
_CATCH (...) { \
rw_assert (!cond, 0, __LINE__, tag); \
} \
(void)0
/**************************************************************************/
// provide a handler for unexpected exceptions so that at least the
// test will log the event rather than just aborting
void my_unexpected_handler ()
{
rw_assert (false, 0, __LINE__, "caught an unexpected exception\n");
}
// used in exists_set_new_handler below
void my_new_handler ()
{
}
// grab default throw procedure
void (*default_throw_proc)(int, char*) = _RW::__rw_throw_proc;
bool my_throw_proc_called = false;
// my_throw_proc just sets a global flag to indicate
// that it was called, and then dispatches the call
// to the default throw procedure
static void my_throw_proc (int id, char* what)
{
my_throw_proc_called = true;
default_throw_proc (id, what);
}
/**************************************************************************/
static
int run_test (int, char* [])
{
std::set_unexpected (&my_unexpected_handler);
if (1) {
// exists_std_nothrow
const std::nothrow_t* p = &std::nothrow;
rw_assert (p != 0, 0, __LINE__, "std::nothrow defined");
}
if (1) {
// exists_bad_alloc
std::bad_alloc ba1; // default ctor
std::bad_alloc ba2 = ba1; // copy ctor
std::exception* e = &ba1; // derived from exception
(void) &e;
ba1 = ba2; // assignment operator
// verify that a member function is accessible and has the
// appropriate signature, including return type and exception
// specification
std::bad_alloc& (std::bad_alloc::*p_op_assign)
(const std::bad_alloc&) _PTR_THROWS (())
= &std::bad_alloc::operator=;
_RWSTD_UNUSED (p_op_assign);
const char*
(std::bad_alloc::*p_what_fn)() const _PTR_THROWS (())
= &std::bad_alloc::what;
_RWSTD_UNUSED (p_what_fn);
const char* s = ba1.what ();
rw_assert (s && 0 != std::strlen (s), 0, __LINE__,
"std::bad_alloc::what() returned bad string");
}
if (1) {
// set_new_handler
typedef void (*new_handler_t) ();
new_handler_t (*f) (new_handler_t) _PTR_THROWS (());
f = &std::set_new_handler;
rw_assert (f != 0, 0, __LINE__,
"std::set_new_handler() defined");
new_handler_t original_handler
= std::set_new_handler (my_new_handler);
#if !defined (__EDG__) || __EDG_VERSION__ > 245 || defined (__DECCXX)
// EDG eccp 2.45 standalone demo is known to fail
rw_assert (original_handler == 0, 0, __LINE__,
"std::set_new_handler() unexpectedly returned "
"installed handler");
#define _RWSTD_NO_EXT_OPERATOR_NEW
#endif // !__EDG__ || __EDG_VERSION__ > 245 || __DECCXX
new_handler_t replacement_handler
= std::set_new_handler (original_handler);
rw_assert (my_new_handler == replacement_handler, 0, __LINE__,
"std::set_new_handler() failed to return previously "
"installed handler");
}
// test all operators that we have provided definitions for
// in <new>; exercises the operators by setting the
// replacement allocator to fail, and asserting that an
// exception is thrown or not as appropriate for the operator
if (1) {
// operator new throws
void* ptr = 0;
_RWSTD_UNUSED (ptr);
alloc.init (); // reset the allocator
#ifdef _RWSTD_NO_OPERATOR_NEW_NOTHROW
// verify that the nothrow version of operator new provided
// by our library doesn't call the ordinary operator new
// (if it did it would cause recursion if a replacement operator
// new were to be implemented in terms of the nothrow version)
// also verify that it returns 0 on failure
// force a failure by requesting too large a block of storage
// size_t (~0) alone isn't good enough since it causes annoying
// dialog boxes to be popped up by the MSVCRTD, the MSVC runtime
TEST_OP_THROWS ((ptr = operator new (~0U - 4096U, std::nothrow)),
(ptr == 0),
"operator new(size_t, nothrow_t) returns 0");
rw_assert (!alloc.newCalled (), 0, __LINE__,
"operator new called by operator new(size_t, nothrow)");
#endif // defined _RWSTD_NO_OPERATOR_NEW_NOTHROW
#if defined (_RWSTD_NO_OPERATOR_DELETE_NOTHROW) && \
!defined (_RWSTD_NO_PLACEMENT_DELETE)
// verify that the nothrow version of operator delete provided
// by our library prevents exceptions from propagating
TEST_OP_THROWS ((operator delete (0, std::nothrow)), true,
"operator delete(void*, nothrow_t) doesn't throw");
// verify that the nothrow version of operator delete provided
// by our library doesn't call the ordinary operator delete
// (if it did it might cause recursion if a replacement operator
// delete were to be implemented in terms of the nothrow version)
rw_assert (!alloc.deleteCalled (), 0, __LINE__,
"operator delete(void*) called by "
"operator delete(void*, nothrow_t)");
#endif // _RWSTD_NO_OPERATOR_DELETE_NOTHROW && _RWSTD_NO_PLACEMENT_DELETE
#ifdef _RWSTD_NO_OPERATOR_NEW_ARRAY
// verify that the array form of operator new throws bad_alloc on
// failure
TEST_OP_THROWS ((operator new[] (1)), false,
"operator new[] (size_t) throws bad_alloc");
// verify that the array form of operator new provided by our
// library calls the ordinary operator new
rw_assert (alloc.newCalled (), 0, __LINE__,
"operator new called by operator new[](size_t)");
#endif // defined _RWSTD_NO_OPERATOR_NEW_ARRAY
#ifdef _RWSTD_NO_OPERATOR_NEW_ARRAY_NOTHROW
TEST_OP_THROWS ((ptr = operator new[](1, std::nothrow)),
(ptr == 0),
"operator new[] (size_t, nothrow_t) returns 0");
rw_assert (alloc.newCalled (), 0, __LINE__,
"operator new(size_t) called by "
"operator new[](size_t, nothrow_t)");
#endif // defined _RWSTD_NO_OPERATOR_NEW_ARRAY_NOTHROW
#ifdef _RWSTD_NO_OPERATOR_DELETE_ARRAY
TEST_OP_THROWS ((operator delete[] (0)), true,
"operator delete[] (void*) doesn't throw");
rw_assert (alloc.deleteCalled (), 0, __LINE__,
"operator delete called by operator delete[](void*)");
#endif // defined _RWSTD_NO_OPERATOR_DELETE_ARRAY
#if defined (_RWSTD_NO_OPERATOR_DELETE_ARRAY_NOTHROW) && \
!defined ( _RWSTD_NO_PLACEMENT_DELETE)
TEST_OP_THROWS ((operator delete[] (0, std::nothrow)), true,
"operator delete[] (void*, nothrow_t) doesn't "
"throw");
rw_assert (alloc.deleteCalled (), 0, __LINE__,
"operator delete(void*) called by "
"operator delete[](void*, nothrow_t)");
#endif // _RWSTD_NO_OPERATOR_DELETE_ARRAY_NOTHROW &&
// !_RWSTD_NO_PLACEMENT_DELETE
// verify that the nothrow form of operator new provided by our
// library isn't recursively implemented in terms of the ordinary
// operator new
rw_assert (0 == recursive_new_nothrow, 0, __LINE__,
"operator new (size_t, nothrow_t) causes recursion");
rw_assert (0 == recursive_delete_nothrow, 0, __LINE__,
"operator delete (void*, nothrow_t) causes recursion");
}
// __rw_allocate() is like ::operator new() except that it calls
// __rw_throw() on failure (which may throw std::bad_alloc).
// This test checks that __rw_throw() is called,
// that it properly calls __rw_throw_proc(), and that bad_alloc
// is thrown. We'll use the replaced ::operator new() to
// control when a memory allocation request will fail.
#ifndef _RWSTD_NO_REPLACEABLE_NEW_DELETE
const bool test_rw_allocate = true;
#else // if defined (_RWSTD_NO_REPLACEABLE_NEW_DELETE)
// avoid tests that depend on the replacement operators new
// and delete on platforms like AIX or Win32 where they cannot
// be reliably replaced
const bool test_rw_allocate = false;
#endif // _RWSTD_NO_REPLACEABLE_NEW_DELETE
if (test_rw_allocate) {
alloc.init (); // reset the allocator
_RW::__rw_throw_proc = my_throw_proc; // set the throw func
my_throw_proc_called = false;
for (std::size_t i = 0; i < 10; ++i) {
char* ptr = 0;
const bool doFail = !!(i % 2); // prevent MSVC warning 4800
if (doFail)
alloc._failAlloc = true;
try {
// allocation
alloc._bytesRequested = ~i; // reset
ptr = _RWSTD_STATIC_CAST (char*, _RW::__rw_allocate (i));
rw_assert (alloc._bytesRequested == i, 0, __LINE__,
"__rw_allocate (%u) requested %u bytes",
i, alloc._bytesRequested);
rw_assert (alloc.newCalled (), 0, __LINE__,
"operator new() called");
rw_assert (!doFail, 0, __LINE__,
"allocation succeeded");
rw_assert (my_throw_proc_called == false,
0, __LINE__,
"my_throw_proc called");
// deallocation
_RW::__rw_deallocate (ptr, i);
rw_assert (alloc.deleteCalled (),
0, __LINE__,
"operator delete() called");
rw_assert (alloc._deallocPtr == ptr,
0, __LINE__,
"allocated memory deallocated");
}
catch (std::bad_alloc) {
rw_assert (doFail, 0, __LINE__,
"expected bad_alloc exception");
rw_assert (my_throw_proc_called == true, 0, __LINE__,
"my_throw_proc called");
}
catch (...) {
rw_assert (false, 0, __LINE__,
"expected std::bad_alloc exception");
}
my_throw_proc_called = false;
}
}
else {
rw_warn (false, 0, __LINE__,
"__rw::__rw_allocate() not exercised: "
"_RWSTD_NO_REPLACEABLE_NEW_DELETE #defined");
}
return 0;
}
/**************************************************************************/
int main (int argc, char* argv [])
{
return rw_test (argc, argv, __FILE__,
"lib.support.dynamic",
0 /* no comment */,
run_test,
"",
(void*)0);
}

View File

@@ -0,0 +1,439 @@
/***************************************************************************
*
* 18.support.rtti.cpp - test exercising 18.5 [lib.support.rtti]
*
* $Id: 18.support.rtti.cpp 648752 2008-04-16 17:01:56Z faridz $
*
***************************************************************************
*
* 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.
*
* Copyright 2001-2008 Rogue Wave Software.
*
**************************************************************************/
#include <rw/_defs.h>
#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
// Disable implicit inclusion to work around
// a limitation in IBM's VisualAge 5.0.2.0 (see PR#26959)
# define _RWSTD_NO_IMPLICIT_INCLUSION
#endif
/**************************************************************************/
// verifies that typeid is correctly declared for MSVC (see PR #25603)
void foo ()
{
_THROW (0); // must appear before #include <typeinfo>
}
/**************************************************************************/
#include <typeinfo>
#include <driver.h>
#include <valcmp.h>
// polymorphic classes (10.3, p1) used in tests below
struct B { virtual ~B () { } };
struct D1: B { };
struct D2: B { };
/**************************************************************************/
static int
run_test (int, char* [])
{
if (1) {
// exercise 18.5, the synopsis of <typeinfo>
std::type_info *ti = 0;
std::bad_cast *bc = 0;
std::bad_typeid *bt = 0;
_RWSTD_UNUSED (ti);
_RWSTD_UNUSED (bc);
_RWSTD_UNUSED (bt);
}
if (1) {
// exercise 18.5.1, class type_info interface
// 18.5.1, p2
bool (std::type_info::*p_op_eq)(const std::type_info&) const =
&std::type_info::operator==;
// 18.5.1, p3
bool (std::type_info::*p_op_neq)(const std::type_info&) const =
&std::type_info::operator!=;
// 18.5.1, p5
bool (std::type_info::*p_before)(const std::type_info&) const =
&std::type_info::before;
// 18.5.1, p7
const char* (std::type_info::*p_name)() const = &std::type_info::name;
_RWSTD_UNUSED (p_op_eq);
_RWSTD_UNUSED (p_op_neq);
_RWSTD_UNUSED (p_before);
_RWSTD_UNUSED (p_name);
}
if (1) {
// exercise 18.5.1, class type_info functionality
D1 d1;
D2 d2;
const std::type_info &ti_D1 = typeid (D1);
const std::type_info &ti_D2 = typeid (D2);
const std::type_info &ti_d1 = typeid (d1);
const std::type_info &ti_d2 = typeid (d2);
const char *D1_name = ti_D1.name () ? ti_D1.name () : "(D1 null)";
const char *D2_name = ti_D2.name () ? ti_D2.name () : "(D2 null)";
const char *d1_name = ti_d1.name () ? ti_d1.name () : "(d1 null)";
const char *d2_name = ti_d2.name () ? ti_d2.name () : "(d2 null)";
// 18.5.1, p2
rw_assert (ti_D1 == ti_D1, 0, __LINE__,
"std::type_info::operator==(): \"%s\" != \"%s\"",
D1_name, D1_name);
rw_assert (ti_D1 == ti_d1, 0, __LINE__,
"std::type_info::operator==(): \"%s\" != \"%s\"",
D1_name, d1_name);
rw_assert (!(ti_D1 == ti_D2), 0, __LINE__,
"std::type_info::operator==(): \"%s\" == \"%s\"",
D1_name, D2_name);
rw_assert (ti_d1 == ti_d1, 0, __LINE__,
"std::type_info::operator==(): \"%s\" != \"%s\"",
d1_name, d1_name);
rw_assert (ti_d1 == ti_D1, 0, __LINE__,
"std::type_info::operator==(): \"%s\" != \"%s\"",
d1_name, D1_name);
rw_assert (!(ti_d1 == ti_d2), 0, __LINE__,
"std::type_info::operator==(): \"%s\" == \"%s\"",
d1_name, d2_name);
// 18.5.1, p3
rw_assert (ti_D1 != ti_D2, 0, __LINE__,
"std::type_info::operator!=(): \"%s\" == \"%s\"",
D1_name, D2_name);
rw_assert (ti_D1 != ti_d2, 0, __LINE__,
"std::type_info::operator!=(): \"%s\" == \"%s\"",
D1_name, d2_name);
rw_assert (!(ti_D1 != ti_D1), 0, __LINE__,
"std::type_info::operator!=(): \"%s\" != \"%s\"",
D1_name, D1_name);
rw_assert (ti_d1 != ti_d2, 0, __LINE__,
"std::type_info::operator!=(): \"%s\" == \"%s\"",
d1_name, d2_name);
rw_assert (ti_d1 != ti_D2, 0, __LINE__,
"std::type_info::operator!=(): \"%s\" == \"%s\"",
d1_name, D2_name);
rw_assert (!(ti_d1 != ti_d1), 0, __LINE__,
"std::type_info::operator!=(): \"%s\" != \"%s\"",
d1_name, d1_name);
// 18.5.1, p5
rw_assert (!ti_D1.before (ti_D1) && !ti_D2.before (ti_D2),
0, __LINE__, "std::type_info::before ()");
rw_assert (ti_D1.before (ti_D2) || ti_D2.before (ti_D1),
0, __LINE__, "std::type_info::before ()");
rw_assert (ti_d1.before (ti_d2) || ti_d2.before (ti_d1),
0, __LINE__, "std::type_info::before ()");
rw_assert (!ti_d1.before (ti_d1) && !ti_d2.before (ti_d2),
0, __LINE__, "std::type_info::before ()");
// 18.5.1, p7
rw_assert (0 == rw_strncmp (D1_name, d1_name), 0, __LINE__,
"std::type_info::name (): \"%s\" != \"%s\"",
D1_name, d1_name);
rw_assert (0 != rw_strncmp (D1_name, D2_name), 0, __LINE__,
"std::type_info::name (): \"%s\" == \"%s\"",
D1_name, D2_name);
rw_assert (0 == rw_strncmp (D2_name, d2_name), 0, __LINE__,
"std::type_info::name (): \"%s\" != \"%s\"",
D2_name, d2_name);
rw_assert (0 != rw_strncmp (d1_name, d2_name), 0, __LINE__,
"std::type_info::name (): \"%s\" == \"%s\"",
d1_name, d2_name);
}
if (1) {
// exercise 18.5.2, class bad_cast interface
// std::bad_cast must publicly derive from std::exception
const std::bad_cast *pbc = 0;
const std::exception *pe = pbc;
// 18.5.2, p2
std::bad_cast bc;
// 18.5.2, p4 - copy ctor
std::bad_cast bc2 (bc);
// 18.5.2, p4 - assignment
std::bad_cast& (std::bad_cast::*p_op_assign)(const std::bad_cast&)
_PTR_THROWS (()) = &std::bad_cast::operator=;
// 18.5.2, p5
const char* (std::bad_cast::*p_what)() const _PTR_THROWS (()) =
&std::bad_cast::what;
_RWSTD_UNUSED (pbc);
_RWSTD_UNUSED (pe);
_RWSTD_UNUSED (bc);
_RWSTD_UNUSED (bc2);
_RWSTD_UNUSED (p_op_assign);
_RWSTD_UNUSED (p_what);
}
if (1) {
// exercise 18.5.2, class bad_cast functionality
#ifndef _RWSTD_NO_EXCEPTIONS
# ifndef _RWSTD_NO_DYNAMIC_CAST
const char *caught = "no exception";
D1 d1;
B &b = d1;
try {
D2 &d2 = dynamic_cast<D2&>(b);
_RWSTD_UNUSED (d2);
}
catch (const std::bad_cast &bc) {
caught = "std::bad_cast";
// 18.5.2, p2
std::bad_cast bc2;
// 18.5.2, p4 - copy ctor
std::bad_cast bc3 (bc);
const char* const bc_what = bc.what ();
const char* bc2_what = bc2.what ();
const char* const bc3_what = bc3.what ();
if (0 == bc2_what)
rw_assert (false, 0, __LINE__, "bad_cast().what() != 0");
if (0 == bc3_what)
rw_assert (false, 0, __LINE__,
"bad_cast::what() != 0 failed "
"for a copy of a caught exception object");
if (bc2_what && bc3_what)
rw_warn (0 == rw_strncmp (bc2_what, bc3_what),
0, __LINE__,
"bad_cast::bad_cast (const bad_cast&): "
"\"%s\" != \"%s\"", bc_what, bc3_what);
// 18.5.2, p4 - assignment
bc2 = bc;
bc2_what = bc2.what ();
if (0 == bc_what)
rw_assert (false, 0, __LINE__,
"bad_cast::what() != 0 failed "
"for a caught exception object");
if (0 == bc2_what)
rw_assert (false, 0, __LINE__,
"bad_cast::what() != 0 failed "
"for an assigned exception object");
if (bc_what && bc2_what)
rw_warn (0 == rw_strncmp (bc_what, bc2_what),
0, __LINE__,
"bad_cast::operator=(const bad_cast&): "
"\"%s\" != \"%s\"", bc_what, bc2_what);
// 18.5.2, p5
if (bc_what)
rw_assert (0 == rw_strncmp (bc.what (), bc.what ()),
0, __LINE__,
"bad_cast::what() const: \"%s\" != \"%s\"",
bc.what (), bc.what ());
}
catch (const std::exception&) {
caught = "std::exception";
}
catch (...) {
caught = "unknown exception";
}
#if !defined (_RWSTD_NO_STD_BAD_CAST) \
|| !defined (_RWSTD_NO_RUNTIME_IN_STD)
const char expect[] = "std::bad_cast";
#else
const char expect[] = "std::bad_cast (alias for ::bad_cast)";
#endif // !NO_STD_BAD_CAST || !NO_RUNTIME_IN_STD
rw_assert (0 == rw_strncmp (caught, "std::bad_cast"),
0, __LINE__,
"dynamic_cast<>() threw %s, expected %s; this suggests "
"that bad_cast might be defined in the wrong namespace",
caught, expect);
_RWSTD_UNUSED (d1);
_RWSTD_UNUSED (b);
# endif // _RWSTD_NO_DYNAMIC_CAST
#endif // _RWSTD_NO_EXCEPTIONS
}
if (1) {
// exercise 18.5.3, class bad_typeid interface
// std::bad_cast must publicly derive from std::exception
const std::bad_typeid *pbt = 0;
const std::exception *pe = pbt;
// 18.5.2, p2
std::bad_typeid bt;
// 18.5.2, p4 - copy ctor
std::bad_typeid bt2 (bt);
// 18.5.2, p4 - assignment
std::bad_typeid& (std::bad_typeid::*p_op_assign)(const std::bad_typeid&)
_PTR_THROWS (()) = &std::bad_typeid::operator=;
// 18.5.2, p5
const char* (std::bad_typeid::*p_what)() const _PTR_THROWS (()) =
&std::bad_typeid::what;
_RWSTD_UNUSED (pbt);
_RWSTD_UNUSED (pe);
_RWSTD_UNUSED (bt);
_RWSTD_UNUSED (bt2);
_RWSTD_UNUSED (p_op_assign);
_RWSTD_UNUSED (p_what);
}
if (1) {
// exercise 18.5.3, class bad_typeid functionality
#ifndef _RWSTD_NO_EXCEPTIONS
const char *caught = "no exception";
try {
#if !defined (__GNUG__) || __GNUG__ > 2
B *b = 0;
// 5.2.8, p2 - typeid(0) throws std::bad_typeid
const std::type_info &ti = typeid (*b);
_RWSTD_UNUSED (b);
_RWSTD_UNUSED (ti);
#else
// working around a gcc 2.x bug
caught = "SIGSEGV (program dumps core)";
#endif // gcc < 3.0
}
catch (const std::bad_typeid &bt) {
caught = "std::bad_typeid";
// 18.5.2, p2
std::bad_typeid bt2;
// 18.5.2, p4 - copy ctor
std::bad_typeid bt3 (bt);
// verify that what() returns the same string
// after copy construction
rw_warn (0 == rw_strncmp (bt.what (), bt3.what ()),
0, __LINE__,
"std::bad_typeid::bad_typeid (const bad_typeid&): "
"\"%s\" != \"%s\"", bt.what (), bt3.what ());
// 18.5.2, p4 - assignment
bt2 = bt;
// verify that what() returns the same string
// after assignment
rw_warn (0 == rw_strncmp (bt.what (), bt2.what ()),
0, __LINE__,
"std::bad_typeid::operator=(const bad_typeid&): "
"\"%s\" != \"%s\"", bt.what (), bt2.what ());
// 18.5.2, p5
rw_assert (0 == rw_strncmp (bt.what (), bt.what ()),
0, __LINE__,
"std::bad_typeid::what() const: "
"\"%s\" != \"%s\"", bt.what (), bt.what ());
}
catch (const std::exception&) {
caught = "std::exception";
}
catch (...) {
caught = "unknown exception";
}
#if !defined (_RWSTD_NO_STD_BAD_TYPEID) \
|| !defined (_RWSTD_NO_RUNTIME_IN_STD)
const char expect[] = "std::bad_typeid";
#else
const char expect[] = "std::bad_typeid (alias for ::bad_typeid)";
#endif // !NO_STD_BAD_TYPEID || !NO_RUNTIME_IN_STD
rw_assert (0 == rw_strncmp (caught, "std::bad_typeid"),
0, __LINE__,
"typeid ((T*)0) threw %s, expected %s; this suggests "
"that bad_typeid might be defined in the wrong namespace",
caught, expect);
#endif // _RWSTD_NO_EXCEPTIONS
}
return 0;
}
int main (int argc, char* argv [])
{
return rw_test (argc, argv, __FILE__,
"lib.support.rtti",
0 /* no comment */,
run_test,
"",
(void*)0);
}

View File

@@ -0,0 +1,382 @@
/***************************************************************************
*
* 18.atomic.add.cpp - test exercising the __rw_atomic_preincrement()
* and __rw_atomic_predecrement function templates
*
* $Id: atomic_add.cpp 425530 2006-07-25 21:39:50Z sebor $
*
***************************************************************************
*
* 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.
*
* Copyright 2003-2006 Rogue Wave Software.
*
**************************************************************************/
#include <stdio.h>
#include <string.h>
#include <rw/_mutex.h>
#include <any.h>
#include <cmdopt.h>
#include <driver.h>
#include <rw_thread.h> // for rw_thread_create()
/**************************************************************************/
struct thr_args_base
{
static enum tag_t {
Char, SChar, UChar,
Short, UShort, Int, UInt, Long, ULong,
LLong, ULLong
} type_tag_;
};
thr_args_base::tag_t thr_args_base::type_tag_;
template <class intT>
struct thr_args: thr_args_base
{
unsigned threadno_; // thread ordinal number
static int inc_; // increment, decrement, or both
static unsigned nincr_; // number of increments
static intT *shared_; // shared variables
static unsigned nthreads_; // number of threads
static intT* get_array ();
};
template <class intT>
int thr_args<intT>::inc_;
template <class intT>
unsigned thr_args<intT>::nincr_;
template <class intT>
intT* thr_args<intT>::shared_ = thr_args<intT>::get_array ();
template <class intT>
unsigned thr_args<intT>::nthreads_;
// working around compiler bugs that prevent us from defining
// a static array data member of a class template (PR #30009)
template <class intT>
intT* thr_args<intT>::get_array ()
{
static intT array [2];
return array;
}
/**************************************************************************/
template <class T>
T preincrement (T &x)
{
#ifndef _RWSTD_REENTRANT
return ++x;
#else // if defined (_RWSTD_REENTRANT)
return _RW::__rw_atomic_preincrement (x, false);
#endif // _RWSTD_REENTRANT
}
template <class T>
T predecrement (T &x)
{
#ifndef _RWSTD_REENTRANT
return --x;
#else // if defined (_RWSTD_REENTRANT)
return _RW::__rw_atomic_predecrement (x, false);
#endif // _RWSTD_REENTRANT
}
/**************************************************************************/
template <class intT>
void* thread_routine (thr_args<intT> *args)
{
printf ("thread %u starting to %screment\n",
args->threadno_,
args->inc_ < 0 ? "de"
: args->inc_ > 0 ? "in"
: "decrement and in");
if (args->inc_ > 0) {
// exercise atomic_preincrement() in a tight loop
for (unsigned i = 0; i != args->nincr_; ++i) {
preincrement (args->shared_ [0]);
preincrement (args->shared_ [1]);
}
}
else if (args->inc_ < 0) {
// exercise atomic_predecrement() in a tight loop
for (unsigned i = 0; i != args->nincr_; ++i) {
predecrement (args->shared_ [0]);
predecrement (args->shared_ [1]);
}
}
else {
// exercise both atomic_preincrement() and atomic_predecrement()
for (unsigned i = 0; i != args->nincr_; ++i) {
preincrement (args->shared_ [0]);
predecrement (args->shared_ [0]);
preincrement (args->shared_ [1]);
predecrement (args->shared_ [1]);
}
}
return 0;
}
/**************************************************************************/
extern "C" void* thread_routine (void *arg)
{
thr_args_base* const args = (thr_args_base*)arg;
switch (args->type_tag_) {
case thr_args_base::Char:
return thread_routine ((thr_args<char>*)(arg));
case thr_args_base::SChar:
return thread_routine ((thr_args<signed char>*)(arg));
case thr_args_base::UChar:
return thread_routine ((thr_args<unsigned char>*)(arg));
case thr_args_base::Short:
return thread_routine ((thr_args<short>*)(arg));
case thr_args_base::UShort:
return thread_routine ((thr_args<unsigned short>*)(arg));
case thr_args_base::Int:
return thread_routine ((thr_args<int>*)(arg));
case thr_args_base::UInt:
return thread_routine ((thr_args<unsigned int>*)(arg));
case thr_args_base::Long:
return thread_routine ((thr_args<long>*)(arg));
case thr_args_base::ULong:
return thread_routine ((thr_args<unsigned long>*)(arg));
#ifdef _RWSTD_LONG_LONG
case thr_args_base::LLong:
return thread_routine ((thr_args<_RWSTD_LONG_LONG>*)(arg));
case thr_args_base::ULLong:
return thread_routine ((thr_args<unsigned _RWSTD_LONG_LONG>*)(arg));
#endif // _RWSTD_LONG_LONG
};
return 0;
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 1024 * 1024;
/* extern */ int rw_opt_nthreads = 4;
#define MAX_THREADS 32
template <class intT>
void run_test (intT, thr_args_base::tag_t tag, int inc)
{
static const char* const tname = rw_any_t (intT ()).type_name ();
if (!rw_enabled (tname)) {
rw_note (0, 0, 0, "%s test disabled", tname);
return;
}
#if defined (_RWSTD_REENTRANT)
static const char* const fun =
inc < 0 ? "__rw_atomic_predecrement"
: inc > 0 ? ":__rw_atomic_preincrement"
: "__rw_atomic_pre{in,de}crement";
rw_info (0, 0, 0, "__rw::%s (%s&): %d iterations in %d threads",
fun, tname, rw_opt_nloops, rw_opt_nthreads);
rw_thread_t tid [MAX_THREADS];
typedef thr_args<intT> Args;
Args::nthreads_ = rw_opt_nthreads;
Args::type_tag_ = tag;
Args::inc_ = inc;
Args::nincr_ = unsigned (rw_opt_nloops);
Args::shared_ [0] = intT ();
Args::shared_ [1] = intT ();
_RWSTD_ASSERT (Args::nthreads_ < sizeof tid / sizeof *tid);
Args args [sizeof tid / sizeof *tid];
memset (args, 0, sizeof args);
for (unsigned i = 0; i != Args::nthreads_; ++i) {
args [i].threadno_ = i;
rw_fatal (0 == rw_thread_create (tid + i, 0, thread_routine, args + i),
0, __LINE__, "thread_create() failed");
}
for (unsigned i = 0; i != Args::nthreads_; ++i) {
rw_error (0 == rw_thread_join (tid [i], 0), 0, __LINE__,
"thread_join() failed");
}
// compute the expected result
intT expect = intT ();
if (inc < 0) {
for (unsigned i = 0; i != Args::nthreads_ * Args::nincr_; ++i)
--expect;
}
else if (inc > 0) {
for (unsigned i = 0; i != Args::nthreads_ * Args::nincr_; ++i)
++expect;
}
// verify that the final value of the variable shared among all
// threads equals the number of increments or decrements performed
// by all threads
rw_assert (Args::shared_ [0] == expect, 0, __LINE__,
"1. %s (%s&); %s == %s failed",
fun, tname, TOSTR (Args::shared_ [0]), TOSTR (expect));
rw_assert (Args::shared_ [1] == expect, 0, __LINE__,
"2. %s (%s&); %s == %s failed",
fun, tname, TOSTR (Args::shared_ [1]), TOSTR (expect));
#else // if !defined (_RWSTD_REENTRANT)
_RWSTD_UNUSED (tag);
_RWSTD_UNUSED (inc);
#endif // _RWSTD_REENTRANT
}
/**************************************************************************/
static int
run_test (int, char**)
{
// exercise atomic subtract
run_test ((char)0, thr_args_base::Char, -1);
run_test ((signed char)0, thr_args_base::SChar, -1);
run_test ((unsigned char)0, thr_args_base::UChar, -1);
run_test ((short)0, thr_args_base::Short, -1);
run_test ((unsigned short)0, thr_args_base::UShort, -1);
run_test ((int)0, thr_args_base::Int, -1);
run_test ((unsigned int)0, thr_args_base::UInt, -1);
run_test ((long)0, thr_args_base::Long, -1);
run_test ((unsigned long)0, thr_args_base::ULong, -1);
#ifdef _RWSTD_LONG_LONG
run_test ((_RWSTD_LONG_LONG)0, thr_args_base::LLong, -1);
run_test ((unsigned _RWSTD_LONG_LONG)0, thr_args_base::ULLong, -1);
#endif // _RWSTD_LONG_LONG
// exercise atomic add
run_test ((char)0, thr_args_base::Char, +1);
run_test ((signed char)0, thr_args_base::SChar, +1);
run_test ((unsigned char)0, thr_args_base::UChar, +1);
run_test ((short)0, thr_args_base::Short, +1);
run_test ((unsigned short)0, thr_args_base::UShort, +1);
run_test ((int)0, thr_args_base::Int, +1);
run_test ((unsigned int)0, thr_args_base::UInt, +1);
run_test ((long)0, thr_args_base::Long, +1);
run_test ((unsigned long)0, thr_args_base::ULong, +1);
#ifdef _RWSTD_LONG_LONG
run_test ((_RWSTD_LONG_LONG)0, thr_args_base::LLong, +1);
run_test ((unsigned _RWSTD_LONG_LONG)0, thr_args_base::ULLong, +1);
#endif // _RWSTD_LONG_LONG
// exercise both atomic add and subtract
run_test ((char)0, thr_args_base::Char, 0);
run_test ((signed char)0, thr_args_base::SChar, 0);
run_test ((unsigned char)0, thr_args_base::UChar, 0);
run_test ((short)0, thr_args_base::Short, 0);
run_test ((unsigned short)0, thr_args_base::UShort, 0);
run_test ((int)0, thr_args_base::Int, 0);
run_test ((unsigned int)0, thr_args_base::UInt, 0);
run_test ((long)0, thr_args_base::Long, 0);
run_test ((unsigned long)0, thr_args_base::ULong, 0);
#ifdef _RWSTD_LONG_LONG
run_test ((_RWSTD_LONG_LONG)0, thr_args_base::LLong, 0);
run_test ((unsigned _RWSTD_LONG_LONG)0, thr_args_base::ULLong, 0);
#endif // _RWSTD_LONG_LONG
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
0 /* no clause */,
0 /* no comment */,
run_test,
"|-nloops#0 " // must be non-negative
"|-nthreads#0-*" , // must be in [0, MAX_THREADS]
&rw_opt_nloops,
int (MAX_THREADS),
&rw_opt_nthreads);
}

View File

@@ -0,0 +1,368 @@
/***************************************************************************
*
* 18.atomic.xchg.cpp - test exercising the __rw_atomic_exchange() function
* template
*
* $Id: atomic_xchg.cpp 580483 2007-09-28 20:55:52Z sebor $
*
***************************************************************************
*
* 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.
*
* Copyright 2003-2006 Rogue Wave Software.
*
**************************************************************************/
#include <stdio.h>
#include <string.h>
#include <rw/_mutex.h>
#include <any.h>
#include <cmdopt.h>
#include <driver.h>
#include <rw_thread.h> // for rw_thread_create()
/**************************************************************************/
struct thr_args_base
{
static enum tag_t {
Char, SChar, UChar,
Short, UShort, Int, UInt, Long, ULong,
LLong, ULLong
} type_tag_;
unsigned long threadno_; // thread ordinal number
unsigned long niter_; // number of iterations
unsigned long nxchg_; // number of exchanges
};
thr_args_base::tag_t thr_args_base::type_tag_;
template <class intT>
struct thr_args: thr_args_base
{
static unsigned long nincr_; // number of increments
static intT *shared_; // shared variables
static unsigned long nthreads_; // number of threads
static intT* get_array ();
};
template <class intT>
unsigned long thr_args<intT>::nincr_;
template <class intT>
intT* thr_args<intT>::shared_ = thr_args<intT>::get_array ();
template <class intT>
unsigned long thr_args<intT>::nthreads_;
// working around compiler bugs that prevent us from defining
// a static array data member of a class template (PR #30009)
template <class intT>
/* static */ intT* thr_args<intT>::get_array ()
{
static intT array [2];
return array;
}
/**************************************************************************/
template <class intT>
intT exchange (intT &x, intT y)
{
#ifndef _RWSTD_REENTRANT
intT save (x);
x = y;
return save;
#else // if defined (_RWSTD_REENTRANT)
return _RW::__rw_atomic_exchange (x, y, false);
#endif // _RWSTD_REENTRANT
}
/**************************************************************************/
template <class intT>
void* thread_routine (thr_args<intT> *args)
{
// each thread operates on one of two shared values to exercise
// problems due to operating on adjacent bytes or half-words
const unsigned long inx = args->threadno_ % 2;
static volatile int failed;
// exercise atomic_exchange() in a tight loop
// perform the requested number increments, or until the
// shared `failed' variable is set to a non-zero value
for (unsigned long i = 0; i != args->nincr_ && !failed; ++i) {
for (unsigned long j = 0; !failed; ++j) {
// increment the number of iterations of this thread
++args->niter_;
// use intT() as a special "lock" value
const intT old = exchange (args->shared_ [inx], intT ());
// increment the number of exchanges performed by this thread
++args->nxchg_;
if (intT () != old) {
// shared variable was not locked by any other thread
// increment the value of the shared variable, taking
// care to avoid the special "lock" value of intT()
intT newval = intT (old + 1);
if (intT () == newval)
++newval;
const intT lock = exchange (args->shared_ [inx], newval);
// increment the number of exchanges
++args->nxchg_;
// the returned value must be the special "lock" value
if (intT () == lock)
break;
// fail by setting the shared failed variable (to
// prevent deadlock) if the returned value is not
// the special "lock" value
printf ("*** line %d: error: thread %lu failed "
"at increment %lu after %lu iterations\n",
__LINE__, args->threadno_, i, args->niter_);
failed = 1;
return 0;
}
if (100UL * args->nincr_ == j) {
// fail by setting the shared failed variable (to
// prevent deadlock) if the number of failed attempts
// to lock the shared variable reaches the requested
// number of increments * 100 (an arbitrary number)
printf ("*** line %d: error thread %lu \"timed out\" after "
"%lu increments and %lu iterations\n",
__LINE__, args->threadno_, i, args->niter_);
failed = 1;
return 0;
}
}
}
return 0;
}
/**************************************************************************/
extern "C" void* thread_routine (void *arg)
{
thr_args_base* const args = (thr_args_base*)arg;
printf ("thread %lu starting\n", args->threadno_);
switch (args->type_tag_) {
case thr_args_base::Char:
return thread_routine ((thr_args<char>*)(arg));
case thr_args_base::SChar:
return thread_routine ((thr_args<signed char>*)(arg));
case thr_args_base::UChar:
return thread_routine ((thr_args<unsigned char>*)(arg));
case thr_args_base::Short:
return thread_routine ((thr_args<short>*)(arg));
case thr_args_base::UShort:
return thread_routine ((thr_args<unsigned short>*)(arg));
case thr_args_base::Int:
return thread_routine ((thr_args<int>*)(arg));
case thr_args_base::UInt:
return thread_routine ((thr_args<unsigned int>*)(arg));
case thr_args_base::Long:
return thread_routine ((thr_args<long>*)(arg));
case thr_args_base::ULong:
return thread_routine ((thr_args<unsigned long>*)(arg));
#ifdef _RWSTD_LONG_LONG
case thr_args_base::LLong:
return thread_routine ((thr_args<_RWSTD_LONG_LONG>*)(arg));
case thr_args_base::ULLong:
return thread_routine ((thr_args<unsigned _RWSTD_LONG_LONG>*)(arg));
#endif // _RWSTD_LONG_LONG
};
return 0;
}
/**************************************************************************/
/* extern */ int rw_opt_nloops = 1024 * 1024;
/* extern */ int rw_opt_nthreads = 4;
#define MAX_THREADS 32
template <class intT>
void run_test (intT, thr_args_base::tag_t tag)
{
static const char* const tname = rw_any_t (intT ()).type_name ();
if (!rw_enabled (tname)) {
rw_note (0, 0, 0, "%s test disabled", tname);
return;
}
#ifdef _RWSTD_REENTRANT
static const char* const fun = "__rw_atomic_exchange";
rw_info (0, 0, 0, "__rw::%s (%s&, %2$s): %d iterations in %d threads",
fun, tname, rw_opt_nloops, rw_opt_nthreads);
rw_thread_t tid [MAX_THREADS];
typedef thr_args<intT> Args;
Args::nthreads_ = unsigned (rw_opt_nthreads);
Args::type_tag_ = tag;
Args::nincr_ = unsigned (rw_opt_nloops);
Args::shared_ [0] = intT (1);
Args::shared_ [1] = intT (1);
_RWSTD_ASSERT (Args::nthreads_ < sizeof tid / sizeof *tid);
Args args [sizeof tid / sizeof *tid];
for (unsigned long i = 0; i != Args::nthreads_; ++i) {
args [i].threadno_ = i;
args [i].niter_ = 0;
args [i].nxchg_ = 0;
rw_fatal (0 == rw_thread_create (tid + i, 0, thread_routine, args + i),
0, __LINE__, "thread_create() failed");
}
for (unsigned long i = 0; i != Args::nthreads_; ++i) {
rw_error (0 == rw_thread_join (tid [i], 0), 0, __LINE__,
"thread_join() failed");
if (args [i].niter_) {
// compute the percantage of thread iterations that resulted
// in increments of one of the shared variables
const unsigned long incrpcnt =
(100U * Args::nincr_) / args [i].niter_;
printf ("thread %lu performed %lu exchanges in %lu iterations "
"(%lu%% increments)\n",
args [i].threadno_, args [i].nxchg_,
args [i].niter_, incrpcnt);
}
}
// compute the expected result, "skipping" zeros by incrementing
// expect twice when it overflows and wraps around to 0 (zero is
// used as the lock variable in thread_routine() above)
intT expect = intT (1);
const unsigned long nincr = (Args::nthreads_ * Args::nincr_) / 2U;
for (unsigned long i = 0; i != nincr; ++i) {
if (intT () == ++expect)
++expect;
}
// verify that the final value of the variables shared among all
// threads equals the number of increments performed by the threads
rw_assert (Args::shared_ [0] == expect, 0, __LINE__,
"1. %s (%s&, %2$s); %s == %s failed",
fun, tname, TOSTR (Args::shared_ [0]), TOSTR (expect));
rw_assert (Args::shared_ [1] == expect, 0, __LINE__,
"2. %s (%s&, %2$s); %s == %s failed",
fun, tname, TOSTR (Args::shared_ [1]), TOSTR (expect));
#else // if !defined (_RWSTD_REENTRANT)
_RWSTD_UNUSED (tag);
#endif // _RWSTD_REENTRANT
}
/**************************************************************************/
static int
run_test (int, char**)
{
// exercise atomic exchange
run_test ((char)0, thr_args_base::Char);
run_test ((signed char)0, thr_args_base::SChar);
run_test ((unsigned char)0, thr_args_base::UChar);
run_test ((short)0, thr_args_base::Short);
run_test ((unsigned short)0, thr_args_base::UShort);
run_test ((int)0, thr_args_base::Int);
run_test ((unsigned int)0, thr_args_base::UInt);
run_test ((long)0, thr_args_base::Long);
run_test ((unsigned long)0, thr_args_base::ULong);
#ifdef _RWSTD_LONG_LONG
run_test ((_RWSTD_LONG_LONG)0, thr_args_base::LLong);
run_test ((unsigned _RWSTD_LONG_LONG)0, thr_args_base::ULLong);
#endif // _RWSTD_LONG_LONG
return 0;
}
/**************************************************************************/
int main (int argc, char *argv[])
{
return rw_test (argc, argv, __FILE__,
0 /* no clause */,
0 /* no comment */, run_test,
"|-nloops#0 " // must be non-negative
"|-nthreads#0-*", // must be in [0, MAX_THREADS]
&rw_opt_nloops,
int (MAX_THREADS),
&rw_opt_nthreads);
}