summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2000-05-15 22:26:55 +0000
committercoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2000-05-15 22:26:55 +0000
commitec42afe8e8d4952567723685999a6a7990ec5d08 (patch)
tree684ed84f1bc373a59ecd5bc4d8377c4aaae1db68
parentf0a1acd242b0abcf4cc0ec15aec3d508e138dfe5 (diff)
downloadATCD-ec42afe8e8d4952567723685999a6a7990ec5d08.tar.gz
ChangeLogTag:Mon May 15 15:14:41 2000 Carlos O'Ryan <coryan@uci.edu>
-rw-r--r--ChangeLog37
-rw-r--r--ChangeLogs/ChangeLog-02a37
-rw-r--r--ChangeLogs/ChangeLog-03a37
-rw-r--r--ace/CDR_Stream.cpp507
-rw-r--r--ace/CDR_Stream.h16
-rw-r--r--ace/CDR_Stream.i168
-rw-r--r--tests/CDR_Array_Test.cpp899
-rw-r--r--tests/CDR_Array_Test.dsp101
-rw-r--r--tests/CDR_Array_Test.icc15
-rw-r--r--tests/CDR_File_Test.cpp194
-rw-r--r--tests/Makefile1
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/Makefile.bor2
-rw-r--r--tests/run_tests.bat2
-rw-r--r--tests/run_tests.lst1
-rw-r--r--tests/run_tests.vxworks11
-rw-r--r--tests/tests.dsw12
17 files changed, 1923 insertions, 119 deletions
diff --git a/ChangeLog b/ChangeLog
index bdad33d7c20..f9f90b821f6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+Mon May 15 15:14:41 2000 Carlos O'Ryan <coryan@uci.edu>
+
+ * ace/CDR_Stream.h:
+ * ace/CDR_Stream.i:
+ * ace/CDR_Stream.cpp:
+ Cristian Ferretti <cristian_ferretti@yahoo.com> has contributed
+ a number of optimizations to the but swapping code for CDR
+ streams. The optimizations include loop unrolling for 32-bit
+ and 64-bit architectures, use of special assembly instructions
+ for x86-based platforms and use of bit operations (instead of
+ memory manipulation) for other processors.
+
+ * tests/Makefile:
+ * tests/Makefile.am:
+ * tests/Makefile.bor:
+ * tests/run_tests.bat:
+ * tests/run_tests.lst:
+ * tests/run_tests.vxworks:
+ * tests/tests.dsw:
+ * tests/CDR_Array_Test.cpp:
+ * tests/CDR_Array_Test.dsp:
+ * tests/CDR_Array_Test.icc:
+ New test to verify that the array operations in the CDR classes
+ actually work, this is specially critical because the new
+ versions unroll loop, perform assembly instructions that work
+ best when the alingment is right, etc.
+
+ * tests/CDR_File_Test.cpp:
+ The test was extended. Now we can save a file in one platform
+ and load it (manually) in another platform, to verify that byte
+ swapping actually works.
+ Both tests were contributed by Cristian Ferretti
+ <cristian_ferretti@yahoo.com>, which is good because all this
+ voodoo programming needs testing.
+ The changes were tested using PA-RISC, Alphas, Sparcs and
+ finally Pentiums in various forms and using several compilers.
+
Mon May 15 14:01:23 2000 Ossama Othman <ossama@uci.edu>
* ace/OS.h:
diff --git a/ChangeLogs/ChangeLog-02a b/ChangeLogs/ChangeLog-02a
index bdad33d7c20..f9f90b821f6 100644
--- a/ChangeLogs/ChangeLog-02a
+++ b/ChangeLogs/ChangeLog-02a
@@ -1,3 +1,40 @@
+Mon May 15 15:14:41 2000 Carlos O'Ryan <coryan@uci.edu>
+
+ * ace/CDR_Stream.h:
+ * ace/CDR_Stream.i:
+ * ace/CDR_Stream.cpp:
+ Cristian Ferretti <cristian_ferretti@yahoo.com> has contributed
+ a number of optimizations to the but swapping code for CDR
+ streams. The optimizations include loop unrolling for 32-bit
+ and 64-bit architectures, use of special assembly instructions
+ for x86-based platforms and use of bit operations (instead of
+ memory manipulation) for other processors.
+
+ * tests/Makefile:
+ * tests/Makefile.am:
+ * tests/Makefile.bor:
+ * tests/run_tests.bat:
+ * tests/run_tests.lst:
+ * tests/run_tests.vxworks:
+ * tests/tests.dsw:
+ * tests/CDR_Array_Test.cpp:
+ * tests/CDR_Array_Test.dsp:
+ * tests/CDR_Array_Test.icc:
+ New test to verify that the array operations in the CDR classes
+ actually work, this is specially critical because the new
+ versions unroll loop, perform assembly instructions that work
+ best when the alingment is right, etc.
+
+ * tests/CDR_File_Test.cpp:
+ The test was extended. Now we can save a file in one platform
+ and load it (manually) in another platform, to verify that byte
+ swapping actually works.
+ Both tests were contributed by Cristian Ferretti
+ <cristian_ferretti@yahoo.com>, which is good because all this
+ voodoo programming needs testing.
+ The changes were tested using PA-RISC, Alphas, Sparcs and
+ finally Pentiums in various forms and using several compilers.
+
Mon May 15 14:01:23 2000 Ossama Othman <ossama@uci.edu>
* ace/OS.h:
diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a
index bdad33d7c20..f9f90b821f6 100644
--- a/ChangeLogs/ChangeLog-03a
+++ b/ChangeLogs/ChangeLog-03a
@@ -1,3 +1,40 @@
+Mon May 15 15:14:41 2000 Carlos O'Ryan <coryan@uci.edu>
+
+ * ace/CDR_Stream.h:
+ * ace/CDR_Stream.i:
+ * ace/CDR_Stream.cpp:
+ Cristian Ferretti <cristian_ferretti@yahoo.com> has contributed
+ a number of optimizations to the but swapping code for CDR
+ streams. The optimizations include loop unrolling for 32-bit
+ and 64-bit architectures, use of special assembly instructions
+ for x86-based platforms and use of bit operations (instead of
+ memory manipulation) for other processors.
+
+ * tests/Makefile:
+ * tests/Makefile.am:
+ * tests/Makefile.bor:
+ * tests/run_tests.bat:
+ * tests/run_tests.lst:
+ * tests/run_tests.vxworks:
+ * tests/tests.dsw:
+ * tests/CDR_Array_Test.cpp:
+ * tests/CDR_Array_Test.dsp:
+ * tests/CDR_Array_Test.icc:
+ New test to verify that the array operations in the CDR classes
+ actually work, this is specially critical because the new
+ versions unroll loop, perform assembly instructions that work
+ best when the alingment is right, etc.
+
+ * tests/CDR_File_Test.cpp:
+ The test was extended. Now we can save a file in one platform
+ and load it (manually) in another platform, to verify that byte
+ swapping actually works.
+ Both tests were contributed by Cristian Ferretti
+ <cristian_ferretti@yahoo.com>, which is good because all this
+ voodoo programming needs testing.
+ The changes were tested using PA-RISC, Alphas, Sparcs and
+ finally Pentiums in various forms and using several compilers.
+
Mon May 15 14:01:23 2000 Ossama Othman <ossama@uci.edu>
* ace/OS.h:
diff --git a/ace/CDR_Stream.cpp b/ace/CDR_Stream.cpp
index 985f86cdaea..bd8f2d8fd0f 100644
--- a/ace/CDR_Stream.cpp
+++ b/ace/CDR_Stream.cpp
@@ -8,6 +8,453 @@
ACE_RCSID(ace, CDR_Stream, "$Id$")
+//
+// See comments in CDR_Stream.i about optimization cases for swap_XX_array.
+//
+
+void
+ACE_CDR::swap_2_array (const char* orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+ // Later, we try to read in 32 or 64 bit chunks,
+ // so make sure we don't do that for unaligned addresses.
+#if ACE_SIZEOF_LONG == 8
+ const char* const o8 = ACE_ptr_align_binary(orig, 8);
+ while (orig < o8 && n > 0)
+ {
+ ACE_CDR::swap_2 (orig, target);
+ orig += 2;
+ target += 2;
+ --n;
+ }
+#else
+ const char* const o4 = ACE_ptr_align_binary(orig, 4);
+ // this is an _if_, not a _while_. The mistmatch can only be by 2.
+ if (orig != o4)
+ {
+ ACE_CDR::swap_2 (orig, target);
+ orig += 2;
+ target += 2;
+ --n;
+ }
+#endif
+ if (n == 0)
+ return;
+
+ //
+ // Loop unrolling. Here be dragons.
+ //
+
+ // (n & (~3)) is the greatest multiple of 4 not bigger than n.
+ // In the while loop ahead, orig will move over the array by 8 byte
+ // increments (4 elements of 2 bytes).
+ // end marks our barrier for not falling outside.
+ const char* const end = orig + 2*(n & (~3));
+
+ // See if we're aligned for writting in 64 or 32 bit chunks...
+#if ACE_SIZEOF_LONG == 8
+ if (target == ACE_ptr_align_binary(target, 8))
+#else
+ if (target == ACE_ptr_align_binary(target, 4))
+#endif
+ {
+ while (orig < end)
+ {
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ unsigned int a =
+ * ACE_reinterpret_cast(const unsigned int*, orig);
+ unsigned int b =
+ * ACE_reinterpret_cast(const unsigned int*, orig + 4);
+ asm( "bswap %1" : "=r" (a) : "0" (a) );
+ asm( "bswap %1" : "=r" (b) : "0" (b) );
+ asm( "rol $16, %1" : "=r" (a) : "0" (a) );
+ asm( "rol $16, %1" : "=r" (b) : "0" (b) );
+ * ACE_reinterpret_cast(unsigned int*, target) = a;
+ * ACE_reinterpret_cast(unsigned int*, target + 4) = b;
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ecx, orig;
+ __asm mov edx, target;
+ __asm mov eax, [ecx];
+ __asm mov ebx, 4[ecx];
+ __asm bswap eax;
+ __asm bswap ebx;
+ __asm rol eax, 16;
+ __asm rol ebx, 16;
+ __asm mov [edx], eax;
+ __asm mov 4[edx], ebx;
+#elif ACE_SIZEOF_LONG == 8
+ // 64 bit architecture.
+ register unsigned long a =
+ * ACE_reinterpret_cast(const unsigned long*, orig);
+
+ register unsigned long a1 = (a & 0x00ff00ff00ff00ffUL) << 8;
+ register unsigned long a2 = (a & 0xff00ff00ff00ff00UL) >> 8;
+
+ a = (a1 | a2);
+
+ * ACE_reinterpret_cast(unsigned long*, target) = a;
+#else
+ register ACE_UINT32 a =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ register ACE_UINT32 b =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 4);
+
+ register ACE_UINT32 a1 = (a & 0x00ff00ffU) << 8;
+ register ACE_UINT32 b1 = (b & 0x00ff00ffU) << 8;
+ register ACE_UINT32 a2 = (a & 0xff00ff00U) >> 8;
+ register ACE_UINT32 b2 = (b & 0xff00ff00U) >> 8;
+
+ a = (a1 | a2);
+ b = (b1 | b2);
+
+ * ACE_reinterpret_cast(ACE_UINT32*, target) = a;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = b;
+#endif
+ orig += 8;
+ target += 8;
+ }
+ }
+ else
+ {
+ // We're out of luck. We have to write in 2 byte chunks.
+ while (orig < end)
+ {
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ unsigned int a =
+ * ACE_reinterpret_cast(const unsigned int*, orig);
+ unsigned int b =
+ * ACE_reinterpret_cast(const unsigned int*, orig + 4);
+ asm( "bswap %1" : "=r" (a) : "0" (a) );
+ asm( "bswap %1" : "=r" (b) : "0" (b) );
+ // We're little endian.
+ * ACE_reinterpret_cast(unsigned short*, target + 2)
+ = (unsigned short) (a & 0xffff);
+ * ACE_reinterpret_cast(unsigned short*, target + 6)
+ = (unsigned short) (b & 0xffff);
+ asm( "shrl $16, %1" : "=r" (a) : "0" (a) );
+ asm( "shrl $16, %1" : "=r" (b) : "0" (b) );
+ * ACE_reinterpret_cast(unsigned short*, target + 0)
+ = (unsigned short) (a & 0xffff);
+ * ACE_reinterpret_cast(unsigned short*, target + 4)
+ = (unsigned short) (b & 0xffff);
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ecx, orig;
+ __asm mov edx, target;
+ __asm mov eax, [ecx];
+ __asm mov ebx, 4[ecx];
+ __asm bswap eax;
+ __asm bswap ebx;
+ // We're little endian.
+ __asm mov 2[edx], ax;
+ __asm mov 6[edx], bx;
+ __asm shr eax, 16;
+ __asm shr ebx, 16;
+ __asm mov 0[edx], ax;
+ __asm mov 4[edx], bx;
+#elif ACE_SIZEOF_LONG == 8
+ // 64 bit architecture.
+ register unsigned long a =
+ * ACE_reinterpret_cast(const unsigned long*, orig);
+
+ register unsigned long a1 = (a & 0x00ff00ff00ff00ffUL) << 8;
+ register unsigned long a2 = (a & 0xff00ff00ff00ff00UL) >> 8;
+
+ a = (a1 | a2);
+
+ ACE_UINT16 b1 = ACE_static_cast(ACE_UINT16, (a >> 48));
+ ACE_UINT16 b2 = ACE_static_cast(ACE_UINT16, ((a >> 32) & 0xffff));
+ ACE_UINT16 b3 = ACE_static_cast(ACE_UINT16, ((a >> 16) & 0xffff));
+ ACE_UINT16 b4 = ACE_static_cast(ACE_UINT16, (a & 0xffff));
+
+#if defined(ACE_LITTLE_ENDIAN)
+ * ACE_reinterpret_cast(ACE_UINT16*, target) = b4;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 2) = b3;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 4) = b2;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 6) = b1;
+#else
+ * ACE_reinterpret_cast(ACE_UINT16*, target) = b1;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 2) = b2;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 4) = b3;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 6) = b4;
+#endif
+#else
+ register ACE_UINT32 a =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ register ACE_UINT32 b =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 4);
+
+ register ACE_UINT32 a1 = (a & 0x00ff00ff) << 8;
+ register ACE_UINT32 b1 = (b & 0x00ff00ff) << 8;
+ register ACE_UINT32 a2 = (a & 0xff00ff00) >> 8;
+ register ACE_UINT32 b2 = (b & 0xff00ff00) >> 8;
+
+ a = (a1 | a2);
+ b = (b1 | b2);
+
+ ACE_UINT32 c1 = ACE_static_cast(ACE_UINT16, (a >> 16));
+ ACE_UINT32 c2 = ACE_static_cast(ACE_UINT16, (a & 0xffff));
+ ACE_UINT32 c3 = ACE_static_cast(ACE_UINT16, (b >> 16));
+ ACE_UINT32 c4 = ACE_static_cast(ACE_UINT16, (b & 0xffff));
+
+#if defined(ACE_LITTLE_ENDIAN)
+ * ACE_reinterpret_cast(ACE_UINT16*, target) = c2;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 2) = c1;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 4) = c4;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 6) = c3;
+#else
+ * ACE_reinterpret_cast(ACE_UINT16*, target) = c1;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 2) = c2;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 4) = c3;
+ * ACE_reinterpret_cast(ACE_UINT16*, target + 6) = c4;
+#endif
+#endif
+
+ orig += 8;
+ target += 8;
+ }
+ }
+
+ // (n & 3) == (n % 4).
+ switch (n&3) {
+ case 3:
+ ACE_CDR::swap_2 (orig, target);
+ orig += 2;
+ target += 2;
+ case 2:
+ ACE_CDR::swap_2 (orig, target);
+ orig += 2;
+ target += 2;
+ case 1:
+ ACE_CDR::swap_2 (orig, target);
+ }
+}
+
+void
+ACE_CDR::swap_4_array (const char* orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+#if ACE_LONG_SIZE == 8
+ // Later, we read from *orig in 64 bit chunks,
+ // so make sure we don't generate unaligned readings.
+ const char* const o8 = ACE_ptr_align_binary(orig, 8);
+ // The mistmatch can only be by 4.
+ if (orig != o8)
+ {
+ ACE_CDR::swap_4 (orig, target);
+ orig += 4;
+ target += 4;
+ --n;
+ }
+#endif
+ if (n == 0)
+ return;
+
+ //
+ // Loop unrolling. Here be dragons.
+ //
+
+ // (n & (~3)) is the greatest multiple of 4 not bigger than n.
+ // In the while loop, orig will move over the array by 16 byte
+ // increments (4 elements of 4 bytes).
+ // ends marks our barrier for not falling outside.
+ const char* const end = orig + 4*(n & (~3));
+
+#if ACE_LONG_SIZE == 8
+ // 64 bits architecture.
+ // See if we can write in 8 byte chunks.
+ if (target == ACE_ptr_align_binary(target, 8))
+ {
+ while (orig < end)
+ {
+ register unsigned long a =
+ * ACE_reinterpret_cast(const long*, orig);
+ register unsigned long b =
+ * ACE_reinterpret_cast(const long*, orig + 8);
+
+ register unsigned long a84 = (a & 0x000000ff000000ffL) << 24;
+ register unsigned long b84 = (b & 0x000000ff000000ffL) << 24;
+ register unsigned long a73 = (a & 0x0000ff000000ff00L) << 8;
+ register unsigned long b73 = (b & 0x0000ff000000ff00L) << 8;
+ register unsigned long a62 = (a & 0x00ff000000ff0000L) >> 8;
+ register unsigned long b62 = (b & 0x00ff000000ff0000L) >> 8;
+ register unsigned long a51 = (a & 0xff000000ff000000L) >> 24;
+ register unsigned long b51 = (b & 0xff000000ff000000L) >> 24;
+
+ a = (a84 | a73 | a62 | a51);
+ b = (b84 | b73 | b62 | b51);
+
+ * ACE_reinterpret_cast(long*, target) = a;
+ * ACE_reinterpret_cast(long*, target + 8) = b;
+
+ orig += 16;
+ target += 16;
+ }
+ }
+ else
+ {
+ // We are out of luck, we have to write in 4 byte chunks.
+ while (orig < end)
+ {
+ register unsigned long a =
+ * ACE_reinterpret_cast(const long*, orig);
+ register unsigned long b =
+ * ACE_reinterpret_cast(const long*, orig + 8);
+
+ register unsigned long a84 = (a & 0x000000ff000000ffL) << 24;
+ register unsigned long b84 = (b & 0x000000ff000000ffL) << 24;
+ register unsigned long a73 = (a & 0x0000ff000000ff00L) << 8;
+ register unsigned long b73 = (b & 0x0000ff000000ff00L) << 8;
+ register unsigned long a62 = (a & 0x00ff000000ff0000L) >> 8;
+ register unsigned long b62 = (b & 0x00ff000000ff0000L) >> 8;
+ register unsigned long a51 = (a & 0xff000000ff000000L) >> 24;
+ register unsigned long b51 = (b & 0xff000000ff000000L) >> 24;
+
+ a = (a84 | a73 | a62 | a51);
+ b = (b84 | b73 | b62 | b51);
+
+ ACE_UINT32 c1 = ACE_static_cast(ACE_UINT32, (a >> 32));
+ ACE_UINT32 c2 = ACE_static_cast(ACE_UINT32, (a & 0xffffffff));
+ ACE_UINT32 c3 = ACE_static_cast(ACE_UINT32, (b >> 32));
+ ACE_UINT32 c4 = ACE_static_cast(ACE_UINT32, (b & 0xffffffff));
+
+#if defined(ACE_LITTLE_ENDIAN)
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 0) = c2;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = c1;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 8) = c4;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 12) = c3;
+#else
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 0) = c1;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = c2;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 8) = c3;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 12) = c4;
+#endif
+ orig += 16;
+ target += 16;
+ }
+ }
+
+#else /* ACE_LONG_SIZE != 8 */
+
+ while (orig < end)
+ {
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ register unsigned int a =
+ *ACE_reinterpret_cast(const unsigned int*, orig);
+ register unsigned int b =
+ *ACE_reinterpret_cast(const unsigned int*, orig + 4);
+ register unsigned int c =
+ *ACE_reinterpret_cast(const unsigned int*, orig + 8);
+ register unsigned int d =
+ *ACE_reinterpret_cast(const unsigned int*, orig + 12);
+
+ asm ("bswap %1" : "=r" (a) : "0" (a));
+ asm ("bswap %1" : "=r" (b) : "0" (b));
+ asm ("bswap %1" : "=r" (c) : "0" (c));
+ asm ("bswap %1" : "=r" (d) : "0" (d));
+
+ *ACE_reinterpret_cast(unsigned int*, target) = a;
+ *ACE_reinterpret_cast(unsigned int*, target + 4) = b;
+ *ACE_reinterpret_cast(unsigned int*, target + 8) = c;
+ *ACE_reinterpret_cast(unsigned int*, target + 12) = d;
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov eax, orig
+ __asm mov esi, target
+ __asm mov edx, [eax]
+ __asm mov ecx, 4[eax]
+ __asm mov ebx, 8[eax]
+ __asm mov eax, 12[eax]
+ __asm bswap edx
+ __asm bswap ecx
+ __asm bswap ebx
+ __asm bswap eax
+ __asm mov [esi], edx
+ __asm mov 4[esi], ecx
+ __asm mov 8[esi], ebx
+ __asm mov 12[esi], eax
+#else
+ register ACE_UINT32 a =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ register ACE_UINT32 b =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 4);
+ register ACE_UINT32 c =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 8);
+ register ACE_UINT32 d =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 12);
+
+ // Expect the optimizer reordering this A LOT.
+ // We leave it this way for clarity.
+ a = (a << 24) | ((a & 0xff00) << 8) | ((a & 0xff0000) >> 8) | (a >> 24);
+ b = (b << 24) | ((b & 0xff00) << 8) | ((b & 0xff0000) >> 8) | (b >> 24);
+ c = (c << 24) | ((c & 0xff00) << 8) | ((c & 0xff0000) >> 8) | (c >> 24);
+ d = (d << 24) | ((d & 0xff00) << 8) | ((d & 0xff0000) >> 8) | (d >> 24);
+
+ * ACE_reinterpret_cast(ACE_UINT32*, target) = a;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = b;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 8) = c;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 12) = d;
+#endif
+
+ orig += 16;
+ target += 16;
+ }
+
+#endif /* ACE_LONG_SIZE == 8 */
+
+ // (n & 3) == (n % 4).
+ switch (n&3) {
+ case 3:
+ ACE_CDR::swap_4 (orig, target);
+ orig += 4;
+ target += 4;
+ case 2:
+ ACE_CDR::swap_4 (orig, target);
+ orig += 4;
+ target += 4;
+ case 1:
+ ACE_CDR::swap_4 (orig, target);
+ }
+}
+
+//
+// We don't benefit from unrolling in swap_8_array and swap_16_array
+// (swap_8 and swap_16 are big enough).
+//
+void
+ACE_CDR::swap_8_array (const char* orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+ const char* const end = orig + 8*n;
+ while (orig < end)
+ {
+ swap_8(orig, target);
+ orig += 8;
+ target += 8;
+ }
+}
+
+void
+ACE_CDR::swap_16_array (const char* orig, char* target, size_t n)
+{
+ // ACE_ASSERT(n > 0); The caller checks that n > 0
+
+ const char* const end = orig + 16*n;
+ while (orig < end)
+ {
+ swap_16(orig, target);
+ orig += 16;
+ target += 16;
+ }
+}
+
int
ACE_CDR::grow (ACE_Message_Block *mb, size_t minsize)
{
@@ -519,38 +966,26 @@ ACE_OutputCDR::write_array (const void *x,
}
else
{
- // I cannot see any fast way out of this....
- typedef void (*SWAPPER)(const char *, char *);
- SWAPPER swapper;
+ const char *source = ACE_reinterpret_cast (const char *, x);
switch (size)
{
case 2:
- swapper = ACE_CDR::swap_2;
- break;
+ ACE_CDR::swap_2_array (source, buf, length);
+ return 1;
case 4:
- swapper = ACE_CDR::swap_4;
- break;
+ ACE_CDR::swap_4_array (source, buf, length);
+ return 1;
case 8:
- swapper = ACE_CDR::swap_8;
- break;
+ ACE_CDR::swap_8_array (source, buf, length);
+ return 1;
case 16:
- swapper = ACE_CDR::swap_16;
- break;
+ ACE_CDR::swap_16_array (source, buf, length);
+ return 1;
default:
// TODO: print something?
this->good_bit_ = 0;
return 0;
}
-
- const char *source = ACE_reinterpret_cast (const char *, x);
- const char *end = source + size*length;
-
- for (; source != end; source += size, buf += size)
- {
- (*swapper)(source, buf);
- }
-
- return 1;
}
#endif /* ACE_ENABLE_SWAP_ON_WRITE */
}
@@ -811,41 +1246,29 @@ ACE_InputCDR::read_array (void* x,
char* buf;
if (this->adjust (size * length, align, buf) == 0)
{
-#if !defined (ACE_DISABLE_SWAP_ON_READ)
+#if defined (ACE_DISABLE_SWAP_ON_READ)
+ ACE_OS::memcpy (x, buf, size*length);
+#else
if (!this->do_byte_swap_ || size == 1)
{
ACE_OS::memcpy (x, buf, size*length);
}
else
{
- // I cannot see any fast way out of this....
char *target = ACE_reinterpret_cast (char*, x);
- char *end = target + size*length;
switch (size)
{
case 2:
- for (; target != end; target += size, buf += size)
- {
- ACE_CDR::swap_2 (buf, target);
- }
- break;
+ ACE_CDR::swap_2_array (buf, target, length);
+ break;
case 4:
- for (; target != end; target += size, buf += size)
- {
- ACE_CDR::swap_4 (buf, target);
- }
+ ACE_CDR::swap_4_array (buf, target, length);
break;
case 8:
- for (; target != end; target += size, buf += size)
- {
- ACE_CDR::swap_8 (buf, target);
- }
+ ACE_CDR::swap_8_array (buf, target, length);
break;
case 16:
- for (; target != end; target += size, buf += size)
- {
- ACE_CDR::swap_16 (buf, target);
- }
+ ACE_CDR::swap_16_array (buf, target, length);
break;
default:
// TODO: print something?
@@ -853,8 +1276,6 @@ ACE_InputCDR::read_array (void* x,
return 0;
}
}
-#else
- ACE_OS::memcpy (x, buf, size*length);
#endif /* ACE_DISABLE_SWAP_ON_READ */
return this->good_bit_;
}
diff --git a/ace/CDR_Stream.h b/ace/CDR_Stream.h
index 13439e7410c..7adf7e9a383 100644
--- a/ace/CDR_Stream.h
+++ b/ace/CDR_Stream.h
@@ -103,6 +103,18 @@ public:
static void swap_4 (const char *orig, char *target);
static void swap_8 (const char *orig, char *target);
static void swap_16 (const char *orig, char *target);
+ static void swap_2_array (const char *orig,
+ char *target,
+ size_t length);
+ static void swap_4_array (const char *orig,
+ char *target,
+ size_t length);
+ static void swap_8_array (const char *orig,
+ char *target,
+ size_t length);
+ static void swap_16_array (const char *orig,
+ char *target,
+ size_t length);
// Do byte swapping for each basic IDL type size. There exist only
// routines to put byte, halfword (2 bytes), word (4 bytes),
// doubleword (8 bytes) and quadword (16 byte); because those are
@@ -118,7 +130,7 @@ public:
// To understand how a "best fit" is computed look at the
// algorithm in the code.
// Basically the buffers grow exponentially, up to a certain point,
- // then the buffer size grows linearly.
+ // then the buffer size grows linearly.
// The advantage of this algorithm is that is rapidly grows to a
// large value, but does not explode at the end.
@@ -630,7 +642,7 @@ public:
// another without requiring any extra memory allocations, data
// copies or too many temporaries.
Transfer_Contents (ACE_InputCDR &rhs);
-
+
ACE_InputCDR &rhs_;
};
ACE_InputCDR (Transfer_Contents rhs);
diff --git a/ace/CDR_Stream.i b/ace/CDR_Stream.i
index 9fd0c6c142a..33d0d21c685 100644
--- a/ace/CDR_Stream.i
+++ b/ace/CDR_Stream.i
@@ -3,54 +3,150 @@
// ****************************************************************
+//
+// The ACE_CDR::swap_X and ACE_CDR::swap_X_array routines are broken
+// in 4 cases for optimization:
+//
+// * x86 Pentium CPU + gnu g++
+// (ACE_HAS_PENTIUM && __GNUG__)
+// => gcc x86 inline assembly.
+//
+// * x86 Pentium CPU and (_MSC_VER) or BORLAND C++)
+// (ACE_HAS_PENTIUM && ( _MSC_VER || __BORLANDC__ )
+// => MSC x86 inline assembly.
+//
+// * 64 bit architecture
+// (ACE_SIZEOF_LONG == 8)
+// => shift/masks using 64bit words.
+//
+// * default
+// (none of the above)
+// => shift/masks using 32bit words.
+//
+//
+// Some things you could find usefull to know if you intend to mess
+// with this optimizations for swaps:
+//
+// * MSVC++ don't assume register values are conserved between
+// statements. So you can clobber any register you want,
+// whenever you want (well not *anyone* really, see manual).
+// The MSVC++ optimizer will try to pick different registers
+// for the C++ statements sorrounding your asm block, and if
+// it's not possible will use the stack.
+//
+// * If you clobber registers with asm statements in gcc, you
+// better do it in an asm-only function, or save/restore them
+// before/after in the stack. If not, sorrounding C statements
+// could end using the same registers and big-badda-bum (been
+// there, done that...). The big-badda-bum could happen *even
+// if you specify the clobbered register in your asm's*.
+// Even better, use gcc asm syntax for detecting the register
+// asigned to a certain variable so you don't have to clobber any
+// register directly.
+//
+
ACE_INLINE void
ACE_CDR::swap_2 (const char *orig, char* target)
{
- target[1] = *orig++;
- target[0] = *orig++;
+#if defined(ACE_HAS_PENTIUM)
+# if defined(__GNUG__)
+ asm( "movw 0(%0), %%ax" : /* no output */ : "r" (orig) : "%ax");
+ asm( "rolw $8, %%ax" : /* no output */ : /* no input */ : "%ax");
+ asm( "movw %%ax, 0(%0)" : /* no output */ : "r" (target) : "memory");
+# elif (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ebx, orig;
+ __asm mov ecx, target;
+ __asm mov ax, [ebx];
+ __asm rol ax, 8;
+ __asm mov [ecx], ax;
+# else
+ // For CISC Platforms this is faster than shift/masks.
+ target[1] = orig[0];
+ target[0] = orig[1];
+# endif
+#else
+ register ACE_UINT16 usrc = * ACE_reinterpret_cast(const ACE_UINT16*, orig);
+ register ACE_UINT16* udst = ACE_reinterpret_cast(ACE_UINT16*, target);
+ *udst = (usrc << 8) | (usrc >> 8);
+#endif /* ACE_HAS_PENTIUM */
}
ACE_INLINE void
-ACE_CDR::swap_4 (const char *orig, char* target)
-{
- target [3] = *orig++;
- target [2] = *orig++;
- target [1] = *orig++;
- target [0] = *orig++;
+ACE_CDR::swap_4 (const char* orig, char* target)
+{
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ // We have ACE_HAS_PENTIUM, so we know the sizeof's.
+ register unsigned int j =
+ *ACE_reinterpret_cast(const unsigned int*, orig);
+ asm ("bswap %1" : "=r" (j) : "0" (j));
+ *ACE_reinterpret_cast(unsigned int*, target) = j;
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ebx, orig;
+ __asm mov ecx, target;
+ __asm mov eax, [ebx];
+ __asm bswap eax;
+ __asm mov [ecx], eax;
+#else
+ register ACE_UINT32 x = * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
+ * ACE_reinterpret_cast(ACE_UINT32*, target) = x;
+#endif
}
ACE_INLINE void
-ACE_CDR::swap_8 (const char *orig, char* target)
-{
- target [7] = *orig++;
- target [6] = *orig++;
- target [5] = *orig++;
- target [4] = *orig++;
- target [3] = *orig++;
- target [2] = *orig++;
- target [1] = *orig++;
- target [0] = *orig++;
+ACE_CDR::swap_8 (const char* orig, char* target)
+{
+#if defined(ACE_HAS_PENTIUM) && defined(__GNUG__)
+ register unsigned int i =
+ *ACE_reinterpret_cast(const unsigned int*, orig);
+ register unsigned int j =
+ *ACE_reinterpret_cast(const unsigned int*, (orig + 4));
+ asm ("bswap %1" : "=r" (i) : "0r" (i));
+ asm ("bswap %1" : "=r" (j) : "0r" (j));
+ *ACE_reinterpret_cast(unsigned int*, target + 4) = i;
+ *ACE_reinterpret_cast(unsigned int*, target) = j;
+#elif defined(ACE_HAS_PENTIUM) \
+ && (defined(_MSC_VER) || defined(__BORLANDC__)) \
+ && !defined(ACE_LACKS_INLINE_ASSEMBLY)
+ __asm mov ecx, orig;
+ __asm mov edx, target;
+ __asm mov eax, [ecx];
+ __asm mov ebx, 4[ecx];
+ __asm bswap eax;
+ __asm bswap ebx;
+ __asm mov 4[edx], eax;
+ __asm mov [edx], ebx;
+#elif ACE_SIZEOF_LONG == 8
+ // 64 bit architecture.
+ register unsigned long x =
+ * ACE_reinterpret_cast(const unsigned long*, orig);
+ register unsigned long x84 = (x & 0x000000ff000000ffUL) << 24;
+ register unsigned long x73 = (x & 0x0000ff000000ff00UL) << 8;
+ register unsigned long x62 = (x & 0x00ff000000ff0000UL) >> 8;
+ register unsigned long x51 = (x & 0xff000000ff000000UL) >> 24;
+ x = (x84 | x73 | x62 | x51);
+ x = (x << 32) | (x >> 32);
+ *ACE_reinterpret_cast(unsigned long*, target) = x;
+#else
+ register ACE_UINT32 x =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig);
+ register ACE_UINT32 y =
+ * ACE_reinterpret_cast(const ACE_UINT32*, orig + 4);
+ x = (x << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | (x >> 24);
+ y = (y << 24) | ((y & 0xff00) << 8) | ((y & 0xff0000) >> 8) | (y >> 24);
+ * ACE_reinterpret_cast(ACE_UINT32*, target) = y;
+ * ACE_reinterpret_cast(ACE_UINT32*, target + 4) = x;
+#endif
}
ACE_INLINE void
-ACE_CDR::swap_16 (const char *orig, char* target)
-{
- target [15] = *orig++;
- target [14] = *orig++;
- target [13] = *orig++;
- target [12] = *orig++;
- target [11] = *orig++;
- target [10] = *orig++;
- target [9] = *orig++;
- target [8] = *orig++;
- target [7] = *orig++;
- target [6] = *orig++;
- target [5] = *orig++;
- target [4] = *orig++;
- target [3] = *orig++;
- target [2] = *orig++;
- target [1] = *orig++;
- target [0] = *orig++;
+ACE_CDR::swap_16 (const char* orig, char* target)
+{
+ swap_8 (orig + 8, target);
+ swap_8 (orig, target + 8);
}
ACE_INLINE void
diff --git a/tests/CDR_Array_Test.cpp b/tests/CDR_Array_Test.cpp
new file mode 100644
index 00000000000..cca75e89607
--- /dev/null
+++ b/tests/CDR_Array_Test.cpp
@@ -0,0 +1,899 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// CDR_Array_Test.cpp
+//
+// = DESCRIPTION
+// Checks ACE_OutputCDR::write_XX_array.
+// Checks ACE_InputCDR::read_XX_array.
+// Checks operator<< and operator>> for CDR Streams in
+// each of the basic CDR types.
+// Gives a measure of the speed of the ACE CDR streams wrt those operations.
+//
+// = AUTHORS
+// Cristian Ferretti <cristian_ferretti@yahoo.com>
+//
+// ============================================================================
+
+// For measuring time, choose your method:
+// Define:
+//
+// * USE_GETRUSAGE for using ACE_OS::getrusage.
+// Ticks only when process is running.
+//
+// * USE_CLOCK for using clock(2).
+// You're on your own, no ACE_OS:: support.
+// Ticks only when process is running.
+//
+// * None of the above for using ACE_High_Res_Timer.
+// Ticks independent of running state of process.
+
+// #define USE_CLOCK
+// #define USE_GETRUSAGE
+
+#if defined(USE_CLOCK)
+#include <time.h>
+#endif
+
+#include "test_config.h"
+#include "ace/Get_Opt.h"
+#include "ace/CDR_Stream.h"
+#include "ace/High_Res_Timer.h"
+
+#if defined(USE_GETRUSAGE) && !defined(ACE_HAS_GETRUSAGE)
+#error "Can't define USE_GETRUSAGE on this platform."
+#endif
+
+ACE_RCSID(tests, CDR_Array_Test, "$Id$");
+
+// Default number of elements for check buffer, for each tested CDR type.
+// Be aware that time will be affected by the buffer fitting/not fitting
+// in the cache (ie, if default_total*sizeof(T) bytes fit in the cache).
+// Also, you want that your time measuring method has a resolution
+// compatible with this buffer size, if not you will end up measuring 0.
+// You can change this value with -t option.
+static const int default_total = 32*1024;
+
+// Repeat this many times for each tested CDR type.
+// We then take the average time that took for each type and report that.
+// You can change this value with -n option.
+static const int default_niter = 5;
+
+//
+// A simple cronometer in seconds, that encapsulates our time
+// measuring method.
+//
+class Crono {
+public:
+ Crono() {}
+ ~Crono() {}
+ void start ()
+ {
+#if defined(USE_CLOCK)
+ start_ = clock ();
+#elif defined(USE_GETRUSAGE)
+ ACE_OS::getrusage (RUSAGE_SELF, &start_);
+#else
+ timer.start ();
+#endif
+ }
+ void stop ()
+ {
+#if defined(USE_CLOCK)
+ end_ = clock ();
+#elif defined(USE_GETRUSAGE)
+ ACE_OS::getrusage (RUSAGE_SELF, &end_);
+#else
+ timer.stop ();
+#endif
+ }
+ double read_seconds ()
+ {
+#if defined(USE_CLOCK)
+ return (end_ - start_) / (double) CLOCKS_PER_SEC;
+#elif defined(USE_GETRUSAGE)
+ timeval diff;
+ diff.tv_sec = end_.ru_utime.tv_sec - start_.ru_utime.tv_sec;
+ diff.tv_usec = end_.ru_utime.tv_usec - start_.ru_utime.tv_usec;
+ while (diff.tv_usec < 0)
+ {
+ --diff.tv_sec;
+ diff.tv_usec += ACE_ONE_SECOND_IN_USECS;
+ }
+
+ return diff.tv_sec + diff.tv_usec / double(ACE_ONE_SECOND_IN_USECS);
+#else
+ ACE_Time_Value tv;
+ timer.elapsed_time(tv);
+ return tv.usec () / 1000000.0;
+#endif
+ }
+private:
+#if defined(USE_CLOCK)
+ clock_t start_;
+ clock_t end_;
+#elif defined(USE_GETRUSAGE)
+ ACE_Rusage start_;
+ ACE_Rusage end_;
+#else
+ ACE_High_Res_Timer timer;
+#endif
+};
+
+//
+// Our test, performed in the constructor.
+// T is one of the CDR types.
+// H is a helper class (described later).
+//
+// All this stuff is in a class and not in template functions
+// to avoid having to deal with potential template function
+// instantiations problems.
+//
+template<class T, class H> class CDR_Test
+{
+public:
+ CDR_Test (int total, int niter, int use_array);
+ static void do_test (int total, int niter, int use_array,
+ char* srcbuf, char* dstbuf,
+ int src_offset = 0, int dst_offset = 0);
+ ~CDR_Test ();
+
+ static void ttoh (const T& t, char* s);
+
+private:
+ CDR_Test (const CDR_Test&);
+ CDR_Test& operator= (const CDR_Test&);
+};
+
+static ACE_UINT32 seal = 0xdeadbeef;
+
+void
+zero (char* p, int k)
+{
+ char* end = p + k;
+ while (p < end)
+ {
+ *p++ = '\0';
+ }
+}
+
+inline int
+max (int a, int b)
+{
+ return (a >= b) ? a : b;
+}
+
+void
+memabort ()
+{
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("new failed, aborting\n")));
+ ACE_OS::exit (1);
+}
+
+template<class T, class H>
+CDR_Test<T, H>::CDR_Test (int total, int niter, int use_array)
+{
+ if (total <= 0)
+ {
+ return ;
+ }
+
+ char* srcbuf;
+ char* dstbuf;
+ {
+ const int stotal =
+ total*sizeof(T) + sizeof(ACE_UINT32) + ACE_CDR::MAX_ALIGNMENT;
+
+ ACE_NEW(srcbuf, char[stotal]);
+ if (srcbuf == 0)
+ {
+ memabort ();
+ }
+ zero(srcbuf, stotal);
+
+ ACE_NEW(dstbuf, char[stotal]);
+ if (dstbuf == 0)
+ {
+ memabort ();
+ }
+ zero(srcbuf, stotal);
+ }
+
+ if (use_array)
+ {
+ // We want to test all the possible loop unrolling deltas.
+ int t;
+ for (t = total - 3; t <= total; t++)
+ {
+ int delta;
+ if (sizeof(long) <= sizeof(T))
+ {
+ delta = 1;
+ }
+ else
+ {
+ delta = (int) (sizeof(long)/sizeof(T));
+ }
+
+ // We want to test all the posible source/destination buffer
+ // alignment combinations.
+ int sk;
+ for (sk = 0; sk < delta; sk++)
+ {
+ int dk;
+ for (dk = 0; dk < delta; dk++)
+ {
+ int tdelta = t - max(sk, dk);
+
+ CDR_Test<T, H>::do_test(tdelta, niter, 1,
+ srcbuf, dstbuf,
+ sk, dk);
+
+ }
+ }
+ }
+ }
+ else
+ {
+ do_test(total, niter, use_array, srcbuf, dstbuf);
+ }
+
+ delete[] srcbuf;
+ delete[] dstbuf;
+}
+
+// Generate a ``interesting'' value for testing at pos `i'.
+#if 0
+// egcs-1.0.2 (egcs-2.90.27 980315) generates an internal compiler
+// error 9 with this.
+template<class T> inline T
+checkval<T> (int i)
+{
+ const int cycle = 17;
+ return T(i % cycle);
+}
+#else
+const int cycle = 17;
+#define checkval(T,x) ((T) ((x) % cycle))
+#endif
+
+static char digits[16] = {
+ '0', '1', '2', '3',
+ '4', '5', '6', '7',
+ '8', '9', 'a', 'b',
+ 'c', 'd', 'e', 'f'
+};
+
+//
+// Returns in s an hex representation of T's memory.
+// (differences in byte order will be noticed in s).
+//
+// If T = int,
+// t = 0xaabbccdd,
+// => s = "aabbccdd" for big endian machines,
+// s = "ddccbbaa" for little endian machines.
+//
+template<class T, class H> void
+CDR_Test<T, H>::ttoh (const T& t, char* s)
+{
+ const unsigned char *const p =
+ ACE_reinterpret_cast(const unsigned char*, &t);
+
+ const unsigned char* q;
+ for (q = p; q < p + sizeof(t); ++q)
+ {
+ int k = ACE_static_cast(int, *q);
+ *s++ = digits[ k >> 4 ];
+ *s++ = digits[ k & 15 ];
+ }
+
+ *s = 0;
+}
+
+void
+do_seal (char* pos)
+{
+ char* ps = ACE_reinterpret_cast(char*, &seal);
+ pos[0] = ps[0];
+ pos[1] = ps[1];
+ pos[2] = ps[2];
+ pos[3] = ps[3];
+}
+
+int
+check_seal (char* pos)
+{
+ char* ps = ACE_reinterpret_cast(char*, &seal);
+ return (pos[0] == ps[0]
+ && pos[1] == ps[1]
+ && pos[2] == ps[2]
+ && pos[3] == ps[3]);
+}
+
+//
+// returns the alignment of ptr, wrt ACE_CDR::MAX_ALIGNMENT.
+//
+int
+tellalign (char* ptr)
+{
+ int align = ACE_CDR::MAX_ALIGNMENT;
+ while (ptr != ACE_ptr_align_binary(ptr, align))
+ {
+ align = align >> 1;
+ }
+
+ return align;
+}
+
+template<class T, class H> void
+CDR_Test<T, H>::do_test (int total, int niter, int use_array,
+ char* srcbuf, char* dstbuf,
+ int src_offset, int dst_offset)
+{
+ if (!use_array)
+ {
+ dst_offset = src_offset = 0;
+ }
+
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT( "Starting Test for %s: %d elements " )
+ ACE_TEXT( "%susing arrays.\n" ),
+ ACE_TEXT( H::name ),
+ total,
+ ((use_array) ? ACE_TEXT( "" ) : ACE_TEXT( "not " ))));
+
+
+ if (!use_array && (total % 4) != 0)
+ {
+ int lasttotal = total;
+ total -= (total % 4);
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT( "Rounding from %d to %d elements.\n" ),
+ lasttotal,
+ total));
+ }
+
+ char* src = ACE_ptr_align_binary(srcbuf, sizeof(T));
+ T* idata = ACE_reinterpret_cast(T*, src);
+ idata += src_offset;
+ src = ACE_reinterpret_cast(char*, idata);
+
+ {
+ int i;
+ for (i = 0; i < total; i++)
+ {
+ idata[i] = checkval(T, i);
+ }
+ }
+
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT( "Writing data...\n" )));
+
+ char* toread = 0;
+ {
+ ACE_ASSERT(use_array || total % 4 == 0);
+
+ double totalsecs = 0.0;
+ int n;
+ for (n = 0; n < niter; n++)
+ {
+ int size = sizeof(T)*(dst_offset + total);
+ ACE_OutputCDR os (dstbuf, size);
+
+ char* const end = os.begin ()->wr_ptr() + size;
+
+ do_seal(end);
+
+ double secs = 0.0;
+ if (use_array)
+ {
+ {
+ int i;
+ for (i = 0; i < dst_offset; i++)
+ {
+ os << T(0);
+ }
+ }
+
+ if (n == 0)
+ {
+ ACE_DEBUG((LM_DEBUG,
+ "* src align = %d, dst align = %d\n",
+ tellalign (src),
+ tellalign (os.begin ()->wr_ptr ())));
+ }
+
+
+ Crono crono;
+ crono.start ();
+ H::write_array (os, idata, total);
+ crono.stop ();
+ secs = crono.read_seconds ();
+ }
+ else
+ {
+ int i = 0;
+
+ Crono crono;
+ crono.start();
+ while (i < total)
+ {
+ os << idata[i++];
+ os << idata[i++];
+ os << idata[i++];
+ os << idata[i++];
+ }
+ crono.stop ();
+ secs = crono.read_seconds ();
+ }
+
+ if (!check_seal(end))
+ {
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT( "Broken seal, aborting.\n" )));
+ ACE_OS::exit(1);
+ }
+
+ totalsecs += secs;
+
+ if (n == niter - 1)
+ {
+ toread = os.begin()->rd_ptr();
+ }
+ }
+
+ totalsecs = totalsecs / niter;
+
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT ("Writing to stream %d %s values: %f seconds.\n"),
+ total,
+ ACE_TEXT (H::name),
+ totalsecs));
+ }
+
+ {
+ int i;
+ for (i = 0; i < total; i++)
+ {
+ idata[i] = 0;
+ }
+ }
+
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT( "Reading them back in opposing byte order...\n" )));
+
+ const int opposite_byte_order = 1 - ACE_CDR_BYTE_ORDER;
+
+ {
+ double totalsecs = 0.0;
+ int n;
+ for (n = 0; n < niter; n++)
+ {
+ int size = (total + dst_offset)*sizeof(T);
+ ACE_InputCDR is (toread, size, opposite_byte_order);
+
+ char* const end = is.rd_ptr() + size;
+
+ do_seal(end);
+
+ double secs = 0.0;
+ if (use_array)
+ {
+ {
+ int i;
+ for (i = 0; i < dst_offset; i++)
+ {
+ T v;
+ is >> v;
+ }
+ }
+
+ if (n == 0)
+ {
+ ACE_DEBUG((LM_DEBUG,
+ "* src align = %d, dst align = %d\n",
+ tellalign (is.rd_ptr ()),
+ tellalign (src)));
+ }
+
+ Crono crono;
+ crono.start ();
+ H::read_array(is, idata, total);
+ crono.stop ();
+ secs = crono.read_seconds ();
+ }
+ else
+ {
+ int i = 0;
+ Crono crono;
+ crono.start ();
+ while (i < total)
+ {
+ is >> idata[i++];
+ is >> idata[i++];
+ is >> idata[i++];
+ is >> idata[i++];
+ }
+ crono.stop ();
+ secs = crono.read_seconds ();
+ }
+ totalsecs += secs;
+
+ if (!check_seal(end))
+ {
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT( "Broken seal, aborting.\n" )));
+ ACE_OS::exit(1);
+ }
+ }
+
+ totalsecs = totalsecs / niter;
+
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT ("Reading from stream %d %s values")
+ ACE_TEXT (" (byte swapping): %f seconds.\n"),
+ total,
+ ACE_TEXT (H::name),
+ totalsecs));
+ }
+
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT ("Now checking data...\n") ));
+
+ int errors = 0;
+ const int maxerrors = 6;
+
+ {
+ int i;
+ for (i = 0; i < total; i++)
+ {
+ T v;
+
+ const char* src = ACE_reinterpret_cast(const char*, (idata + i));
+ char* dst = ACE_reinterpret_cast(char*, (&v));
+
+ // Easier than writing each H::swap...
+ switch(sizeof(T))
+ {
+ case 1:
+ *dst = *src;
+ break;
+
+ case 2:
+ ACE_CDR::swap_2(src, dst);
+ break;
+
+ case 4:
+ ACE_CDR::swap_4(src, dst);
+ break;
+
+ case 8:
+ ACE_CDR::swap_8(src, dst);
+ break;
+
+ case 16:
+ ACE_CDR::swap_16(src, dst);
+ break;
+
+ default:
+ ACE_ERROR((LM_DEBUG,
+ ACE_TEXT ("Unsupported size, aborting.\n")));
+ ACE_OS::exit(1);
+ }
+
+
+ if (v != checkval(T, i))
+ {
+ static char s1[32 + 1];
+ static char s2[32 + 1];
+ CDR_Test::ttoh (v, s1);
+ CDR_Test::ttoh (checkval(T, i), s2);
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ( "Wrong value at pos %d:" )
+ ACE_TEXT ( " '%s' should be '%s'.\n" ),
+ i, s1, s2));
+ errors++;
+ if (errors == maxerrors)
+ {
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ( "%d errors found, ")
+ ACE_TEXT ( "interrupting check.\n" ),
+ errors));
+ break;
+ }
+ }
+ }
+ }
+
+ if (errors != 0)
+ {
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("Inconsistencies found, aborting.\n") ));
+ ACE_OS::exit(1);
+ }
+
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT ("Data OK, Ending %s test.\n"),
+ ACE_TEXT (H::name)));
+}
+
+template <class T, class N>
+CDR_Test<T, N>::~CDR_Test ()
+{
+}
+
+//
+// Helper Clases for the second template parameter of CDR_Test.
+// One for each tested CDR type.
+//
+
+struct DoubleHelper
+{
+ static const char* name;
+ static void read_array (ACE_InputCDR& is,
+ ACE_CDR::Double* x,
+ ACE_UINT32 n)
+ {
+ is.read_double_array (x, n);
+ }
+ static void write_array (ACE_OutputCDR& os,
+ ACE_CDR::Double* x,
+ ACE_UINT32 n)
+ {
+ os.write_double_array (x, n);
+ }
+};
+const char* DoubleHelper::name = "CDR::Double";
+
+struct FloatHelper
+{
+ static const char* name;
+ static void read_array (ACE_InputCDR& is,
+ ACE_CDR::Float* x,
+ ACE_UINT32 n)
+ {
+ is.read_float_array (x, n);
+ }
+ static void write_array (ACE_OutputCDR& os,
+ ACE_CDR::Float* x,
+ ACE_UINT32 n)
+ {
+ os.write_float_array (x, n);
+ }
+};
+const char* FloatHelper::name = "CDR::Float";
+
+struct ShortHelper
+{
+ static const char* name;
+ static void read_array (ACE_InputCDR& is,
+ ACE_CDR::Short* x,
+ ACE_UINT32 n)
+ {
+ is.read_short_array (x, n);
+ }
+ static void write_array (ACE_OutputCDR& os,
+ ACE_CDR::Short* x,
+ ACE_UINT32 n)
+ {
+ os.write_short_array (x, n);
+ }
+};
+const char* ShortHelper::name = "CDR::Short";
+
+struct LongHelper
+{
+ static const char* name;
+ static void read_array (ACE_InputCDR& is,
+ ACE_CDR::Long* x,
+ ACE_UINT32 n)
+ {
+ is.read_long_array (x, n);
+ }
+ static void write_array (ACE_OutputCDR& os,
+ ACE_CDR::Long* x,
+ ACE_UINT32 n)
+ {
+ os.write_long_array (x, n);
+ }
+};
+const char* LongHelper::name = "CDR::Long";
+
+struct LongLongHelper
+{
+ static const char* name;
+ static void read_array (ACE_InputCDR& is,
+ ACE_CDR::LongLong* x,
+ ACE_UINT32 n)
+ {
+ is.read_longlong_array (x, n);
+ }
+ static void write_array (ACE_OutputCDR& os,
+ ACE_CDR::LongLong* x,
+ ACE_UINT32 n)
+ {
+ os.write_longlong_array (x, n);
+ }
+
+};
+const char* LongLongHelper::name = "CDR::LongLong";
+
+struct CharHelper
+{
+ static const char* name;
+ static void read_array (ACE_InputCDR& is,
+ ACE_CDR::Char* x,
+ ACE_UINT32 n)
+ {
+ is.read_char_array (x, n);
+ }
+ static void write_array (ACE_OutputCDR& os,
+ ACE_CDR::Char* x,
+ ACE_UINT32 n)
+ {
+ os.write_char_array (x, n);
+ }
+};
+const char* CharHelper::name = "CDR::Char";
+
+void usage (ACE_TCHAR* cmd)
+{
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("Usage: %s ")
+ ACE_TEXT ("[-n n] " )
+ ACE_TEXT ("[[-d n|-f n|-q n|-w n|-h n|-c n|-t n] | [-t n]]\n")
+ ACE_TEXT (" -n n: average time for n iterations.\n")
+ ACE_TEXT (" -d n: n double precision floating point\n")
+ ACE_TEXT (" -f n: n single precision floating point\n")
+ ACE_TEXT (" -q n: n quadwords (int64).\n")
+ ACE_TEXT (" -w n: n words (int32).\n")
+ ACE_TEXT (" -h n: n halfwords (int16).\n")
+ ACE_TEXT (" -c n: n chars.\n")
+ ACE_TEXT (" -t n: n iterations for every type.\n")
+ ACE_TEXT (" n must be >= 16 for dfqwhct.\n")
+ ACE_TEXT (" If you provide one of dfqwhc, then only the\n")
+ ACE_TEXT (" corresponding type tests will be performed.\n"),
+ cmd));
+ ACE_OS::exit(1);
+}
+
+int
+main (int argc, ACE_TCHAR *argv[])
+{
+ ACE_START_TEST (ACE_TEXT ("CDR_Array_Test"));
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("This is ACE Version %u.%u.%u\n\n"),
+ ACE::major_version (),
+ ACE::minor_version(),
+ ACE::beta_version()));
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("d:f:q:w:h:c:t:n:"));
+ int dtotal = 0;
+ int ftotal = 0;
+ int qtotal = 0;
+ int wtotal = 0;
+ int htotal = 0;
+ int ctotal = 0;
+ int total = 0;
+ int niter = 0;
+
+ struct { int c; int *v; } opts[] = {
+ { 'd', &dtotal },
+ { 'f', &ftotal },
+ { 'q', &qtotal },
+ { 'w', &wtotal },
+ { 'h', &htotal },
+ { 'c', &ctotal },
+ { 't', &total },
+ { 'n', &niter },
+ };
+
+ int n = sizeof(opts)/sizeof(opts[0]);
+
+ int opt;
+ while ((opt = get_opt ()) != EOF)
+ {
+ int got = 0;
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ if (opts[i].c == opt)
+ {
+ *(opts[i].v) = ACE_OS::atoi (get_opt.optarg);
+ got = 1;
+ break;
+ }
+ }
+
+ if (!got)
+ {
+ usage(argv[0]);
+ }
+ }
+
+ if (total == 0)
+ {
+ total = default_total;
+ }
+ else
+ {
+ if (total < 16)
+ {
+ usage(argv[0]);
+ }
+ }
+
+ if (niter == 0)
+ {
+ niter = default_niter;
+ }
+
+ if (dtotal == 0
+ && ftotal == 0
+ && qtotal == 0
+ && wtotal == 0
+ && htotal == 0
+ && ctotal == 0)
+ {
+ dtotal = ftotal = qtotal = wtotal = htotal = ctotal = total;
+ }
+
+ int use_array;
+ for (use_array = 0; use_array < 2; use_array++)
+ {
+ {
+ CDR_Test<ACE_CDR::Double, DoubleHelper>
+ test (dtotal, niter, use_array);
+ }
+ {
+ CDR_Test<ACE_CDR::Float, FloatHelper>
+ test (ftotal, niter, use_array);
+ }
+ {
+ CDR_Test<ACE_CDR::LongLong, LongLongHelper>
+ test (qtotal, niter, use_array);
+ }
+ {
+ CDR_Test<ACE_CDR::Long, LongHelper>
+ test (wtotal, niter, use_array);
+ }
+ {
+ CDR_Test<ACE_CDR::Short, ShortHelper>
+ test (htotal, niter, use_array);
+ }
+ {
+ CDR_Test<ACE_CDR::Char, CharHelper>
+ test (ctotal, niter, use_array);
+ }
+ }
+
+ ACE_END_TEST;
+ return 0;
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class CDR_Test<ACE_CDR::Double, DoubleHelper>;
+template class CDR_Test<ACE_CDR::Float, FloatHelper>;
+template class CDR_Test<ACE_CDR::LongLong, LongLongHelper>;
+template class CDR_Test<ACE_CDR::Long, LongHelper>;
+template class CDR_Test<ACE_CDR::Short, ShortHelper>;
+template class CDR_Test<ACE_CDR::Char, CharHelper>;
+
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate CDR_Test<ACE_CDR::Double, DoubleHelper>
+#pragma instantiate CDR_Test<ACE_CDR::Float, FloatHelper>
+#pragma instantiate CDR_Test<ACE_CDR::LongLong, LongLongHelper>
+#pragma instantiate CDR_Test<ACE_CDR::Long, LongHelper>
+#pragma instantiate CDR_Test<ACE_CDR::Short, ShortHelper>
+#pragma instantiate CDR_Test<ACE_CDR::Char, CharHelper>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/tests/CDR_Array_Test.dsp b/tests/CDR_Array_Test.dsp
new file mode 100644
index 00000000000..dfbb238b841
--- /dev/null
+++ b/tests/CDR_Array_Test.dsp
@@ -0,0 +1,101 @@
+# Microsoft Developer Studio Project File - Name="CDR_Array_Test" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+# TARGTYPE "Win32 (ALPHA) Console Application" 0x0603
+
+CFG=CDR_Array_Test - Win32 PharLap ETS Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "CDR_Array_Test.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "CDR_Array_Test.mak" CFG="CDR_Array_Test - Win32 PharLap ETS Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "CDR_Array_Test - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "CDR_Array_Test - Win32 Alpha Debug" (based on "Win32 (ALPHA) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+
+!IF "$(CFG)" == "CDR_Array_Test - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\CDR_Array_Test\Debug"
+# PROP BASE Intermediate_Dir ".\CDR_Array_Test\Debug"
+# PROP BASE Target_Dir ".\CDR_Array_Test"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "."
+# PROP Intermediate_Dir ".\DLL\Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ".\CDR_Array_Test"
+CPP=cl.exe
+# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /YX /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /Zi /Od /I "..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /FD /c
+# SUBTRACT CPP /YX
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:I386 /libpath:"..\ace"
+
+!ELSEIF "$(CFG)" == "CDR_Array_Test - Win32 Alpha Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "CDR_Array_Test\Alpha Debug"
+# PROP BASE Intermediate_Dir "CDR_Array_Test\Alpha Debug"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir "CDR_Array_Test"
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir "CDR_Array_Test"
+CPP=cl.exe
+# ADD BASE CPP /nologo /Gt0 /W3 /GX /Zi /Od /I"..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /MTd /c
+# ADD CPP /nologo /Gt0 /W3 /GX /Zi /Od /I"..\\" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /MDd /c
+# SUBTRACT CPP /YX
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 wsock32.lib aced.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:console /debug /machine:ALPHA /libpath:"..\ace"
+# ADD LINK32 aced.lib /nologo /subsystem:console /debug /machine:ALPHA /libpath:"..\ace"
+
+!ENDIF
+
+# Begin Target
+
+# Name "CDR_Array_Test - Win32 Debug"
+# Name "CDR_Array_Test - Win32 Alpha Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"
+# Begin Source File
+
+SOURCE=.\CDR_Array_Test.cpp
+
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/tests/CDR_Array_Test.icc b/tests/CDR_Array_Test.icc
new file mode 100644
index 00000000000..f3dcf14c56c
--- /dev/null
+++ b/tests/CDR_Array_Test.icc
@@ -0,0 +1,15 @@
+// $Id$
+
+include "vacpp_setup.icc"
+option
+ link(libSearchPath, platformLibSearchPath),
+ incl(searchPath, ".."),
+ link(linkWithMultiThreadLib,yes),
+ link(debug)
+ {
+ target type (exe) "CDR_Array_Test"
+ {
+ source type (cpp) "CDR_Array_Test.cpp"
+ source platformLinkLibs
+ }
+ }
diff --git a/tests/CDR_File_Test.cpp b/tests/CDR_File_Test.cpp
index 34fba990146..b0351ec2db6 100644
--- a/tests/CDR_File_Test.cpp
+++ b/tests/CDR_File_Test.cpp
@@ -47,7 +47,9 @@ public:
// Default constructor.
CDR_Test (ACE_CDR::Char o,
+ ACE_CDR::Short s,
ACE_CDR::Long w,
+ ACE_CDR::LongLong lw,
ACE_CDR::Float f,
ACE_CDR::Double d);
// Constructor.
@@ -57,7 +59,9 @@ public:
private:
ACE_CDR::Char char_;
- ACE_CDR::Long word_;
+ ACE_CDR::Short word2_;
+ ACE_CDR::Long word4_;
+ ACE_CDR::LongLong word8_;
ACE_CDR::Float fpoint_;
ACE_CDR::Double dprec_;
};
@@ -66,27 +70,46 @@ ostream &
operator << (ostream &os,
const CDR_Test &t)
{
- os << "Char: " << t.char_ << endl
- << "Long: " << t.word_ << endl
- << "Float: " << t.fpoint_ << endl
- << "Double: " << t.dprec_ << endl;
+ os << "Char: " << t.char_ << endl
+ << "Short: " << t.word2_ << endl
+ << "Long: " << t.word4_ << endl
+#if !defined(_MSC_VER)
+ << "LongLong: " << t.word8_ << endl
+#else
+ << "LongLong 1st half: "
+ << hex
+ << ACE_reinterpret_cast(ACE_UINT32, (t.word8_ >> 32))
+ << dec << endl
+ << "LongLong 2nd half: "
+ << hex
+ << ACE_reinterpret_cast(ACE_UINT32, (t.word8_ & 0xffffffff))
+ << dec << endl
+#endif
+ << "Float: " << t.fpoint_ << endl
+ << "Double: " << t.dprec_ << endl;
return os;
}
CDR_Test::CDR_Test (void)
: char_ (0),
- word_ (0),
+ word2_ (0),
+ word4_ (0),
+ word8_ (0),
fpoint_ (0.0),
dprec_ (0.0)
{
}
CDR_Test::CDR_Test (ACE_CDR::Char o,
+ ACE_CDR::Short s,
ACE_CDR::Long w,
+ ACE_CDR::LongLong lw,
ACE_CDR::Float f,
ACE_CDR::Double d)
: char_ (o),
- word_ (w),
+ word2_ (s),
+ word4_ (w),
+ word8_ (lw),
fpoint_ (f),
dprec_ (d)
{
@@ -96,7 +119,9 @@ void
operator << (ACE_OutputCDR &os, const CDR_Test &t)
{
os << t.char_;
- os << t.word_;
+ os << t.word2_;
+ os << t.word4_;
+ os << t.word8_;
os << t.fpoint_;
os << t.dprec_;
}
@@ -105,7 +130,9 @@ void
operator >> (ACE_InputCDR &is, CDR_Test &t)
{
is >> t.char_;
- is >> t.word_;
+ is >> t.word2_;
+ is >> t.word4_;
+ is >> t.word8_;
is >> t.fpoint_;
is >> t.dprec_;
}
@@ -114,7 +141,9 @@ int
CDR_Test::operator == (const CDR_Test &rhs)
{
return this->char_ == rhs.char_
- && this->word_ == rhs.word_
+ && this->word2_ == rhs.word2_
+ && this->word4_ == rhs.word4_
+ && this->word8_ == rhs.word8_
&& this->fpoint_ == rhs.fpoint_
&& this->dprec_ == rhs.dprec_;
}
@@ -127,6 +156,14 @@ run_test (int write_file,
{
if (write_file)
{
+ char byte_order = ACE_CDR_BYTE_ORDER;
+ size_t n = file.send (&byte_order, 1);
+ if (n != 1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("send failed on %p\n"),
+ filename),
+ -1);
+
ACE_OutputCDR output_cdr (0,
ACE_CDR_BYTE_ORDER,
0,
@@ -147,9 +184,9 @@ run_test (int write_file,
filename,
ACE_CDR_BYTE_ORDER ? "little" : "big"));
- ssize_t n = file.send (output_mb->rd_ptr (),
- output_mb->length ());
- if (n != (ssize_t) output_mb->length())
+ n = file.send (output_mb->rd_ptr (),
+ output_mb->length ());
+ if (n != (size_t) output_mb->length())
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("send failed on %p\n"),
filename),
@@ -164,10 +201,12 @@ run_test (int write_file,
filename),
-1);
+ size_t msgsize = info.size_ - 1;
+
// Allocate the input buffer
char *buffer;
ACE_NEW_RETURN (buffer,
- char[info.size_],
+ char[msgsize],
-1);
// Make sure <buffer> is released automagically.
ACE_Auto_Basic_Array_Ptr<char> b (buffer);
@@ -179,28 +218,37 @@ run_test (int write_file,
ACE_TEXT ("%p\n"),
filename),
-1);
- // Read the file into the buffer.
- ssize_t size = file.recv (buffer,
- info.size_);
- if (size != info.size_)
+
+ char byte_order;
+ size_t size = file.recv (&byte_order, 1);
+ if (size != 1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("Read %d bytes, rather than expected ")
+ ACE_TEXT ("1 bytes\n"),
+ size),
+ -1);
+
+ // Read the cdr data from the file into the buffer.
+ size = file.recv (buffer, msgsize);
+ if (size != msgsize)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("Read %d bytes, rather than expected ")
ACE_TEXT ("%d bytes\n"),
size,
- info.size_),
+ msgsize),
-1);
// Create message block for the whole file. Ensure that it is
// aligned to properly handle the double.
- ACE_Message_Block mb (ACE_CDR::MAX_ALIGNMENT + info.size_);
+ ACE_Message_Block mb (ACE_CDR::MAX_ALIGNMENT + msgsize);
ACE_CDR::mb_align (&mb);
- mb.copy (buffer,
- info.size_);
+
+ mb.copy (buffer, msgsize);
// Create CDR input stream from the message block.
ACE_InputCDR input_cdr (&mb);
- input_cdr.reset_byte_order (ACE_CDR_BYTE_ORDER);
+ input_cdr.reset_byte_order ((int) byte_order);
ACE_DEBUG ((LM_DEBUG,
ACE_TEXT ("Reading file %s in %s endian format...\n"),
@@ -220,15 +268,65 @@ run_test (int write_file,
return 0;
}
+static void
+usage(ACE_TCHAR* cmd)
+{
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Usage: %s ")
+ ACE_TEXT ("[-f filename [-w|-r]]"),
+ cmd));
+ ACE_OS::exit(1);
+}
+
// Main function
int
-main (int, ACE_TCHAR *[])
+main (int argc, ACE_TCHAR *argv[])
{
ACE_START_TEST (ACE_TEXT ("CDR_File_Test"));
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("This is ACE Version %u.%u.%u\n\n"),
+ ACE::major_version (),
+ ACE::minor_version(),
+ ACE::beta_version()));
+
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("f:rw"));
+ int opt;
+ int reading = 1;
+ int writing = 1;
+ ACE_TCHAR* fn = 0;
+ while ((opt = get_opt ()) != EOF)
+ {
+ switch (opt)
+ {
+ case 'f':
+ fn = get_opt.optarg;
+ break;
+ case 'r':
+ writing = 0;
+ break;
+ case 'w':
+ reading = 0;
+ break;
+ case '?':
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if ((!reading || !writing) && fn == 0)
+ {
+ usage(argv[0]);
+ }
+
+ if (!reading && !writing)
+ {
+ usage(argv[0]);
+ }
+
// Create a temporary filename.
- ACE_FILE_Addr filename (ACE_sap_any_cast (ACE_FILE_Addr &));
+ ACE_FILE_Addr filename ((fn == 0) ? ACE_sap_any_cast (ACE_FILE_Addr &) : fn);
ACE_FILE_Connector connector;
ACE_FILE_IO file;
@@ -239,12 +337,24 @@ main (int, ACE_TCHAR *[])
0,
ACE_Addr::sap_any,
0,
- O_RDWR | O_CREAT,
+ ((writing) ? (O_RDWR | O_CREAT) : O_RDONLY),
ACE_DEFAULT_FILE_PERMS) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
ACE_TEXT ("connect failed for %p\n"),
filename.get_path_name ()),
1);
+
+ if (fn == 0)
+ {
+ // Unlink this file right away so that it is automatically removed
+ // when the process exits.
+ if (file.unlink () == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("unlink failed for %p\n"),
+ filename.get_path_name ()),
+ 1);
+ }
+
// Unlink this file right away so that it is automatically removed
// when the process exits.
else if (file.unlink () == -1)
@@ -253,21 +363,29 @@ main (int, ACE_TCHAR *[])
filename.get_path_name ()),
1);
CDR_Test cdr_test ('a',
- 1000,
+ 0x00ff,
+ 0xaabbccdd,
+ 0x01234567,
1.54321f,
1.12345);
- // First write the file.
- run_test (1,
- file,
- filename.get_path_name (),
- cdr_test);
-
- // Then read the file.
- run_test (0,
- file,
- filename.get_path_name (),
- cdr_test);
+ if (writing)
+ {
+ // write the file.
+ run_test (1,
+ file,
+ filename.get_path_name (),
+ cdr_test);
+ }
+
+ if (reading)
+ {
+ // read the file.
+ run_test (0,
+ file,
+ filename.get_path_name (),
+ cdr_test);
+ }
ACE_END_TEST;
return 0;
diff --git a/tests/Makefile b/tests/Makefile
index adfd7aae714..c9d9bbb8f7d 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -21,6 +21,7 @@ BIN = Aio_Platform_Test \
Cached_Conn_Test \
Capabilities_Test \
CDR_File_Test \
+ CDR_Array_Test \
CDR_Test \
Collection_Test \
Conn_Test \
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b1f843bcda8..00a783b845c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -62,6 +62,8 @@ check_PROGRAMS = \
Cached_Conn_Test \
Capabilities_Test \
CDR_Test \
+ CDR_File_Test \
+ CDR_Array_Test \
Collection_Test \
Conn_Test \
DLL_Test \
diff --git a/tests/Makefile.bor b/tests/Makefile.bor
index d2d4efb35ea..fd8a2d24059 100644
--- a/tests/Makefile.bor
+++ b/tests/Makefile.bor
@@ -16,6 +16,8 @@ TESTS = \
Cached_Accept_Conn_Test \
Capabilities_Test \
CDR_Test \
+ CDR_File_Test \
+ CDR_Array_Test \
Collection_Test \
Conn_Test \
DLList_Test \
diff --git a/tests/run_tests.bat b/tests/run_tests.bat
index dd30bf06770..b1ce8d9b07c 100644
--- a/tests/run_tests.bat
+++ b/tests/run_tests.bat
@@ -96,6 +96,8 @@ call %run_cmd% %dopure% %platform% Cached_Conn_Test
call %run_cmd% %dopure% %platform% Cached_Accept_Conn_Test
call %run_cmd% %dopure% %platform% Capabilities_Test
call %run_cmd% %dopure% %platform% CDR_Test
+call %run_cmd% %dopure% %platform% CDR_File_Test
+call %run_cmd% %dopure% %platform% CDR_Array_Test
call %run_cmd% %dopure% %platform% Collection_Test
call %run_cmd% %dopure% %platform% Conn_Test
call %run_cmd% %dopure% %platform% DLL_Test
diff --git a/tests/run_tests.lst b/tests/run_tests.lst
index 5db64650009..646d29ec18b 100644
--- a/tests/run_tests.lst
+++ b/tests/run_tests.lst
@@ -5,6 +5,7 @@ Capabilities_Test
Atomic_Op_Test
Auto_IncDec_Test
Object_Manager_Test
+CDR_Array_Test
CDR_File_Test
CDR_Test
Semaphore_Test
diff --git a/tests/run_tests.vxworks b/tests/run_tests.vxworks
index d3728e3e1fe..d106fdd33f8 100644
--- a/tests/run_tests.vxworks
+++ b/tests/run_tests.vxworks
@@ -48,6 +48,17 @@ ld < CDR_Test
write 2, "CDR_Test ", 9
ace_main; unld "CDR_Test"
+ld < CDR_Array_Test
+write 2, "CDR_Array_Test ", 9
+ace_main; unld "CDR_Array_Test"
+
+##
+## @@ I'm not sure if File_Test can run on vxworks.
+##
+## ld < CDR_File_Test
+## write 2, "CDR_File_Test ", 9
+## ace_main; unld "CDR_File_Test"
+
ld < DLList_Test
write 2, "DLList_Test ", 13
ace_main; unld "DLList_Test"
diff --git a/tests/tests.dsw b/tests/tests.dsw
index 69336a7c9f3..86abc511ed6 100644
--- a/tests/tests.dsw
+++ b/tests/tests.dsw
@@ -87,6 +87,18 @@ Package=<4>
###############################################################################
+Project: "CDR_Array_Test"=.\CDR_Array_Test.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
Project: "CDR_Test"=.\CDR_Test.dsp - Package Owner=<4>
Package=<5>