summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TAO/ChangeLog-98c46
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/Naming_Utils.cpp4
-rw-r--r--TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.h2
-rw-r--r--TAO/tao/GIOP.cpp14
-rw-r--r--TAO/tao/IIOP_Interpreter.cpp97
-rw-r--r--TAO/tao/IIOP_Interpreter.h9
-rw-r--r--TAO/tao/IIOP_ORB.cpp20
-rw-r--r--TAO/tao/ORB.cpp10
-rw-r--r--TAO/tao/Sequence.cpp179
-rw-r--r--TAO/tao/Sequence.h90
-rw-r--r--TAO/tao/Sequence.i68
-rw-r--r--TAO/tao/Sequence_T.cpp2
-rw-r--r--TAO/tao/Sequence_T.h2
-rw-r--r--TAO/tao/Sequence_T.i155
-rw-r--r--TAO/tao/decode.cpp46
-rw-r--r--TAO/tao/orbconf.h11
-rw-r--r--TAO/tests/Makefile1
-rw-r--r--TAO/tests/OctetSeq/Makefile604
-rw-r--r--TAO/tests/OctetSeq/OctetSeq.cpp242
-rw-r--r--TAO/tests/OctetSeq/svc.conf49
-rw-r--r--TAO/tests/OctetSeq/test.idl24
21 files changed, 1582 insertions, 93 deletions
diff --git a/TAO/ChangeLog-98c b/TAO/ChangeLog-98c
index b2237049bc6..5512c5e2486 100644
--- a/TAO/ChangeLog-98c
+++ b/TAO/ChangeLog-98c
@@ -1,3 +1,49 @@
+Tue May 12 16:53:18 1998 Carlos O'Ryan <coryan@cs.wustl.edu>
+
+ * tao/orbconf.h:
+ * tao/Sequence.h:
+ * tao/Sequence.i:
+ * tao/Sequence.cpp:
+ * tao/Sequence_T.h:
+ * tao/Sequence_T.i:
+ * tao/Sequence_T.cpp:
+ * tao/decode.cpp:
+ Unbounded Sequences of octets are specialized so their
+ demarshalling (and eventually their marshalling) is implemented
+ by increasing the reference count on the CDR stream message
+ block and then setting the buffer as a pointer to that stream.
+ The buffers are copied upon assingment or copy ctor.
+ The feature is enabled by the macro TAO_NO_COPY_OCTET_SEQUENCES,
+ by default the macro is defined in $TAO_ROOT/tao/orbconf.h
+ and only applies if the CDR stream owns its buffer, in other
+ words the optimization is disabled when the buffer is allocated
+ on the stack or is not allocated by the CDR stream.
+
+ * tao/IIOP_Interpreter.h:
+ * tao/IIOP_Interpreter.cpp:
+ If the octet sequence is enabled then the size of a sequence
+ depends on its basic type.
+
+ * tao/ORB.cpp:
+ If the octet sequence optimization is enabled we don't need to
+ instantiate TAO_Unbounded_Sequence<CORBA::Octet>.
+
+ * tests/Makefile:
+ * tests/OctetSeq/Makefile:
+ * tests/OctetSeq/svc.conf:
+ * tests/OctetSeq/test.idl:
+ * tests/OctetSeq/OctetSeq.cpp:
+ Added a simple test that just writes an octet sequence in a CDR
+ stream and then reads it back. The test compares the time
+ against a char sequence.
+
+ * tao/GIOP.cpp:
+ Changed several system exceptions from COMPLETED_MAYBE to
+ COMPLETED_NO.
+
+ * orbsvcs/orbsvcs/Sched/Config_Scheduler.h:
+ Added missing forward declaration for ACE_Scheduler.
+
Tue May 12 16:48:46 1998 Seth Benjamin Widoff <sbw1@waltz.cs.wustl.edu>
* tao/corba.h:
diff --git a/TAO/orbsvcs/orbsvcs/Naming/Naming_Utils.cpp b/TAO/orbsvcs/orbsvcs/Naming/Naming_Utils.cpp
index df100138d6d..119a0c1a799 100644
--- a/TAO/orbsvcs/orbsvcs/Naming/Naming_Utils.cpp
+++ b/TAO/orbsvcs/orbsvcs/Naming/Naming_Utils.cpp
@@ -109,7 +109,7 @@ TAO_Naming_Server::init (CORBA::ORB_ptr orb,
TAO_CHECK_ENV;
ACE_DEBUG ((LM_DEBUG,
- "listening as object <%s>\n",
+ "NameService IOR is <%s>\n",
this->naming_service_ior_.in ()));
#if defined (ACE_HAS_IP_MULTICAST)
@@ -203,7 +203,7 @@ TAO_Naming_Server::init (CORBA::ORB_ptr orb,
TAO_CHECK_ENV;
ACE_DEBUG ((LM_DEBUG,
- "listening as object <%s>\n",
+ "NameService IOR is <%s>\n",
this->naming_service_ior_.in ()));
// Bind our context into the default name server.
diff --git a/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.h b/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.h
index e9485f7b51b..63cb06961ba 100644
--- a/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.h
+++ b/TAO/orbsvcs/orbsvcs/Sched/Config_Scheduler.h
@@ -8,6 +8,8 @@
#include "orbsvcs/RtecSchedulerS.h"
#include "orbsvcs/Event_Service_Constants.h"
+class ACE_Scheduler;
+
class TAO_ORBSVCS_Export ACE_Config_Scheduler
: public POA_RtecScheduler::Scheduler
// = TITLE
diff --git a/TAO/tao/GIOP.cpp b/TAO/tao/GIOP.cpp
index 79e91c99b94..9a73097d71f 100644
--- a/TAO/tao/GIOP.cpp
+++ b/TAO/tao/GIOP.cpp
@@ -323,7 +323,7 @@ TAO_GIOP::recv_request (TAO_SVC_HANDLER *&handler,
CDR::mb_align (msg.start_);
if (CDR::grow (msg.start_, TAO_GIOP_HEADER_LEN) == -1)
{
- env.exception (new CORBA::NO_MEMORY (CORBA::COMPLETED_MAYBE));
+ env.exception (new CORBA::NO_MEMORY (CORBA::COMPLETED_NO));
return TAO_GIOP::MessageError;
}
@@ -361,7 +361,7 @@ TAO_GIOP::recv_request (TAO_SVC_HANDLER *&handler,
/* NOTREACHED */
}
- env.exception (new CORBA::COMM_FAILURE (CORBA::COMPLETED_MAYBE));
+ env.exception (new CORBA::COMM_FAILURE (CORBA::COMPLETED_NO));
ACE_TIMEPROBE (" -> GIOP::recv_request - fail");
return TAO_GIOP::MessageError;
}
@@ -377,7 +377,7 @@ TAO_GIOP::recv_request (TAO_SVC_HANDLER *&handler,
&& header [2] == 'O'
&& header [3] == 'P'))
{
- env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); // header
+ env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_NO));
ACE_DEBUG ((LM_DEBUG, "bad header, magic word\n"));
ACE_TIMEPROBE (" -> GIOP::recv_request - fail");
return TAO_GIOP::MessageError;
@@ -389,7 +389,7 @@ TAO_GIOP::recv_request (TAO_SVC_HANDLER *&handler,
if (!(header [4] == TAO_GIOP_MessageHeader::MY_MAJOR
&& header [5] <= TAO_GIOP_MessageHeader::MY_MINOR))
{
- env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_MAYBE)); // header
+ env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_NO));
ACE_DEBUG ((LM_DEBUG, "bad header, version\n"));
ACE_TIMEPROBE (" -> GIOP::recv_request - fail");
return TAO_GIOP::MessageError;
@@ -418,7 +418,7 @@ TAO_GIOP::recv_request (TAO_SVC_HANDLER *&handler,
if (CDR::grow (msg.start_, TAO_GIOP_HEADER_LEN + message_size) == -1)
{
- env.exception (new CORBA::NO_MEMORY (CORBA::COMPLETED_MAYBE));
+ env.exception (new CORBA::NO_MEMORY (CORBA::COMPLETED_NO));
return TAO_GIOP::MessageError;
}
@@ -461,7 +461,7 @@ TAO_GIOP::recv_request (TAO_SVC_HANDLER *&handler,
}
// clean up, and ...
- env.exception (new CORBA::COMM_FAILURE (CORBA::COMPLETED_MAYBE)); // body
+ env.exception (new CORBA::COMM_FAILURE (CORBA::COMPLETED_NO));
ACE_DEBUG ((LM_DEBUG, "couldn't read rest of message\n"));
ACE_TIMEPROBE (" -> GIOP::recv_request - fail");
return TAO_GIOP::MessageError;
@@ -497,7 +497,7 @@ TAO_GIOP_Invocation::TAO_GIOP_Invocation (IIOP_Object *data,
opname_ (operation),
do_rsvp_ (is_roundtrip),
my_request_id_ (0),
- out_stream_ (buffer, sizeof buffer),
+ out_stream_ (CDR::DEFAULT_BUFSIZE), /* (buffer, sizeof buffer), */
inp_stream_ (out_stream_),
handler_ (0)
{
diff --git a/TAO/tao/IIOP_Interpreter.cpp b/TAO/tao/IIOP_Interpreter.cpp
index 917e237ba03..5a7e104320f 100644
--- a/TAO/tao/IIOP_Interpreter.cpp
+++ b/TAO/tao/IIOP_Interpreter.cpp
@@ -34,7 +34,11 @@ TAO_IIOP_Interpreter::table_[CORBA::TC_KIND_COUNT] =
{ 0, 1, 0, skip_encapsulation }, // CORBA::tk_enum
{ 0, 1, 0, skip_long }, // CORBA::tk_string
+#if defined (TAO_NO_COPY_OCTET_SEQUENCES)
+ { 0, 1, calc_seq_attributes, 0 }, // CORBA::tk_sequence
+#else
{ 0, 1, 0, skip_encapsulation }, // CORBA::tk_sequence
+#endif
{ 0, 1, calc_array_attributes, 0 }, // CORBA::tk_array
// = Two TCKind values added in 94-11-7
@@ -165,7 +169,9 @@ declare_entry (CORBA::Principal_ptr, tk_Principal);
declare_entry (CORBA::Object_ptr, tk_objref);
declare_entry (CORBA::String, tk_string);
+#if !defined (TAO_NO_COPY_OCTET_SEQUENCES)
declare_entry (TAO_opaque, tk_sequence);
+#endif
declare_entry (CORBA::LongLong, tk_longlong);
declare_entry (CORBA::ULongLong, tk_ulonglong);
@@ -203,7 +209,9 @@ TAO_IIOP_Interpreter::init (void)
sizeof (generic_enum);
setup_entry (CORBA::String, tk_string);
+#if !defined (TAO_NO_COPY_OCTET_SEQUENCES)
setup_entry (TAO_opaque, tk_sequence);
+#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
setup_entry (CORBA::LongLong, tk_longlong);
setup_entry (CORBA::ULongLong, tk_ulonglong);
@@ -806,6 +814,95 @@ TAO_IIOP_Interpreter::calc_array_attributes (TAO_InputCDR *stream,
return member_size * (size_t) member_count;
}
+#if defined (TAO_NO_COPY_OCTET_SEQUENCES)
+// Calculate size and alignment of a sequence.
+// If octet sequence optimizations are enabled the size of octet
+// sequences differ from the size of a regular sequence.
+
+size_t
+TAO_IIOP_Interpreter::calc_seq_attributes (TAO_InputCDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env)
+{
+ CORBA::TCKind kind;
+
+ // Get the "kind" ... if this is an indirection, this is a guess
+ // which will soon be updated.
+ CORBA::ULong temp;
+ if (stream->read_ulong (temp) == CORBA::B_FALSE)
+ {
+ env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
+ return 0;
+ }
+
+ if (temp == ~0)
+ {
+ // Get indirection, sanity check it, set up new stream pointing
+ // there.
+ //
+ // XXX access to "real" size limit for this typecode and use it
+ // to check for errors before indirect and to limit the new
+ // stream's length. ULONG_MAX is too much!
+ CORBA::Long offset;
+ if (!stream->read_long (offset)
+ || offset >= -8
+ || ((-offset) & 0x03) != 0)
+ {
+ env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
+ return 0;
+ }
+ // Notice how we change the sign of the offset to estimate the
+ // maximum size.
+ TAO_InputCDR indirected_stream (*stream, -offset, offset);
+
+ // Fetch indirected-to TCKind; this *cannot* be an indirection
+ // again because multiple indirections are non-complaint.
+ if (indirected_stream.read_ulong (temp) == CORBA::B_FALSE
+ || temp == ~0)
+ {
+ env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
+ return 0;
+ }
+ }
+
+ kind = ACE_static_cast(CORBA::TCKind, temp);
+
+ // Skip the rest of the stream because we don't use it.
+ if (stream->skip_bytes (stream->length ()) == CORBA::B_FALSE)
+ {
+ env.exception (new CORBA::BAD_TYPECODE (CORBA::COMPLETED_NO));
+ return 0;
+ }
+
+ size_t size;
+ if (kind == CORBA::tk_octet)
+ {
+ declare_entry (TAO_opaque, tk_sequence);
+ align_struct_tk_sequence align;
+ size = sizeof (TAO_opaque);
+#if defined (TAO_HAS_FIXED_BYTE_ALIGNMENT)
+ alignment = 1;
+#else
+ alignment =
+ (char*)&align.two - (char*)&align.one - TAO_MAXIMUM_NATIVE_TYPE_SIZE;
+#endif /* TAO_HAS_FIXED_BYTE_ALIGNMENT */
+ }
+ else
+ {
+ declare_entry (TAO_Unbounded_Sequence<CORBA::Long>, tk_sequence);
+ size = sizeof (TAO_Unbounded_Sequence<CORBA::Long>);
+ align_struct_tk_sequence align;
+#if defined (TAO_HAS_FIXED_BYTE_ALIGNMENT)
+ alignment = 1;
+#else
+ alignment =
+ (char*)&align.two - (char*)&align.one - TAO_MAXIMUM_NATIVE_TYPE_SIZE;
+#endif /* TAO_HAS_FIXED_BYTE_ALIGNMENT */
+ }
+ return size;
+}
+#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
+
// Cast the discriminant values to the right type and compare them.
CORBA::Boolean
diff --git a/TAO/tao/IIOP_Interpreter.h b/TAO/tao/IIOP_Interpreter.h
index cde2272a517..a9a5d4a4782 100644
--- a/TAO/tao/IIOP_Interpreter.h
+++ b/TAO/tao/IIOP_Interpreter.h
@@ -164,6 +164,15 @@ public:
// Calculate size and alignment for a structure.
+#if defined (TAO_NO_COPY_OCTET_SEQUENCES)
+ static size_t calc_seq_attributes (TAO_InputCDR *stream,
+ size_t &alignment,
+ CORBA::Environment &env);
+ // Calculate size and alignment for a sequence, most of them have
+ // the same requirements, but for the sequences of Octets that are
+ // optimized to minimize copying.
+#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
+
static size_t calc_exception_attributes (TAO_InputCDR *stream,
size_t &alignment,
CORBA::Environment &env);
diff --git a/TAO/tao/IIOP_ORB.cpp b/TAO/tao/IIOP_ORB.cpp
index cb8198c270d..acadf8d8e17 100644
--- a/TAO/tao/IIOP_ORB.cpp
+++ b/TAO/tao/IIOP_ORB.cpp
@@ -150,13 +150,12 @@ ior_string_to_object (CORBA::String str,
// Unhex the bytes, and make a CDR deencapsulation stream from the
// resulting data.
- size_t bufsize =
- 1 + ACE_OS::strlen ((char *) str) / 2 + CDR::MAX_ALIGNMENT;
- char *non_aligned_buffer;
- ACE_NEW_RETURN (non_aligned_buffer,
- char [bufsize],
- CORBA_Object::_nil ());
- char *buffer = ptr_align_binary (non_aligned_buffer, CDR::MAX_ALIGNMENT);
+ ACE_Message_Block mb (ACE_OS::strlen ((char *) str) / 2 + 1
+ + CDR::MAX_ALIGNMENT);
+
+ CDR::mb_align (&mb);
+
+ char *buffer = mb.rd_ptr ();
char *tmp = (char *) str;
size_t len = 0;
@@ -177,7 +176,6 @@ ior_string_to_object (CORBA::String str,
if (tmp [0] && !isspace (tmp [0]))
{
- delete [] non_aligned_buffer;
env.exception (new CORBA::BAD_PARAM (CORBA::COMPLETED_NO));
return 0;
}
@@ -185,7 +183,10 @@ ior_string_to_object (CORBA::String str,
// Create deencapsulation stream ... then unmarshal objref from that
// stream.
- TAO_InputCDR stream (buffer + 1, len - 1, buffer[0]);
+ int byte_order = *(mb.rd_ptr ());
+ mb.rd_ptr (1);
+ mb.wr_ptr (len);
+ TAO_InputCDR stream (&mb, byte_order);
CORBA::Object_ptr objref;
if (stream.decode (CORBA::_tc_Object,
@@ -193,7 +194,6 @@ ior_string_to_object (CORBA::String str,
env) != CORBA::TypeCode::TRAVERSE_CONTINUE)
objref = 0;
- delete [] non_aligned_buffer;
return objref;
}
diff --git a/TAO/tao/ORB.cpp b/TAO/tao/ORB.cpp
index b8a01d79571..3347c2cc1c9 100644
--- a/TAO/tao/ORB.cpp
+++ b/TAO/tao/ORB.cpp
@@ -699,8 +699,13 @@ CORBA::ORB_init (int &argc,
}
#define TAO_HASH_ADDR ACE_Hash_Addr<ACE_INET_Addr>
+
#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+#if !defined (TAO_NO_COPY_OCTET_SEQUENCES)
template class TAO_Unbounded_Sequence<CORBA::Octet>;
+#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
+
template class ACE_Dynamic_Service<TAO_Server_Strategy_Factory>;
template class ACE_Dynamic_Service<TAO_Client_Strategy_Factory>;
template class ACE_Cached_Connect_Strategy<TAO_Client_Connection_Handler, TAO_SOCK_CONNECTOR, ACE_SYNCH_RW_MUTEX>;
@@ -715,8 +720,13 @@ template class ACE_Hash_Map_Manager<TAO_HASH_ADDR, TAO_Client_Connection_Handler
template class ACE_Hash_Map_Iterator_Base<TAO_HASH_ADDR, TAO_Client_Connection_Handler *, ACE_SYNCH_NULL_MUTEX>;
template class ACE_Hash_Map_Iterator<TAO_HASH_ADDR, TAO_Client_Connection_Handler *, ACE_SYNCH_NULL_MUTEX>;
template class ACE_Hash_Map_Reverse_Iterator<TAO_HASH_ADDR, TAO_Client_Connection_Handler *, ACE_SYNCH_NULL_MUTEX>;
+
#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#if !defined (TAO_NO_COPY_OCTET_SEQUENCES)
#pragma instantiate TAO_Unbounded_Sequence<CORBA::Octet>
+#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
+
#pragma instantiate ACE_Dynamic_Service<TAO_Server_Strategy_Factory>
#pragma instantiate ACE_Dynamic_Service<TAO_Client_Strategy_Factory>
#pragma instantiate ACE_Cached_Connect_Strategy<TAO_Client_Connection_Handler, TAO_SOCK_CONNECTOR, ACE_SYNCH_RW_MUTEX>
diff --git a/TAO/tao/Sequence.cpp b/TAO/tao/Sequence.cpp
index 42258139c90..0b5c18d14c1 100644
--- a/TAO/tao/Sequence.cpp
+++ b/TAO/tao/Sequence.cpp
@@ -231,3 +231,182 @@ TAO_Unbounded_String_Sequence::_shrink_buffer (CORBA::ULong nl,
tmp[i] = 0;
}
}
+
+// ****************************************************************
+
+#if defined (TAO_NO_COPY_OCTET_SEQUENCES)
+TAO_Unbounded_Sequence<CORBA::Octet>::
+TAO_Unbounded_Sequence (const TAO_Unbounded_Sequence<CORBA::Octet> &rhs)
+ : TAO_Unbounded_Base_Sequence (rhs),
+ mb_ (0)
+{
+ CORBA::Octet *tmp1 = TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (this->maximum_);
+ CORBA::Octet * const tmp2 = ACE_reinterpret_cast (CORBA::Octet * ACE_CAST_CONST, rhs.buffer_);
+
+ for (CORBA::ULong i = 0; i < this->length_; ++i)
+ tmp1[i] = tmp2[i];
+
+ this->buffer_ = tmp1;
+}
+
+TAO_Unbounded_Sequence<CORBA::Octet> &
+TAO_Unbounded_Sequence<CORBA::Octet>::operator= (const TAO_Unbounded_Sequence<CORBA::Octet> &rhs)
+{
+ if (this == &rhs)
+ return *this;
+
+ if (this->mb_ != 0)
+ {
+ ACE_Message_Block::release (this->mb_);
+ this->buffer_ =
+ TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (rhs.length_);
+ }
+ else if (this->release_)
+ {
+ if (this->maximum_ < rhs.length_)
+ {
+ // free the old buffer
+ CORBA::Octet *tmp = ACE_reinterpret_cast (CORBA::Octet *,
+ this->buffer_);
+ TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (tmp);
+ this->buffer_ =
+ TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (rhs.length_);
+ }
+ }
+ else
+ this->buffer_ =
+ TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (rhs.length_);
+
+ TAO_Unbounded_Base_Sequence::operator= (rhs);
+
+ CORBA::Octet *tmp1 = ACE_reinterpret_cast (CORBA::Octet *, this->buffer_);
+ CORBA::Octet * const tmp2 = ACE_reinterpret_cast (CORBA::Octet * ACE_CAST_CONST, rhs.buffer_);
+
+ for (CORBA::ULong i = 0; i < this->length_; ++i)
+ tmp1[i] = tmp2[i];
+
+ return *this;
+}
+
+TAO_Unbounded_Sequence<CORBA::Octet>::~TAO_Unbounded_Sequence (void)
+{
+ this->_deallocate_buffer ();
+}
+
+void
+TAO_Unbounded_Sequence<CORBA::Octet>::_allocate_buffer (CORBA::ULong length)
+{
+ CORBA::Octet *tmp = TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (length);
+
+ if (this->buffer_ != 0)
+ {
+ CORBA::Octet *old = ACE_reinterpret_cast (CORBA::Octet *, this->buffer_);
+
+ for (CORBA::ULong i = 0; i < this->length_; ++i)
+ tmp[i] = old[i];
+
+ if (this->release_)
+ {
+ if (this->mb_ == 0)
+ TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (old);
+ else
+ {
+ ACE_Message_Block::release (this->mb_);
+ this->mb_ = 0;
+ }
+ }
+ }
+
+ this->buffer_ = tmp;
+}
+
+CORBA::Octet *
+TAO_Unbounded_Sequence<CORBA::Octet>::get_buffer (CORBA::Boolean orphan)
+{
+ CORBA::Octet *result = 0;
+ if (orphan == CORBA::B_FALSE)
+ {
+ // We retain ownership.
+
+ if (this->buffer_ == 0)
+ {
+ // The buffer was not allocated, we must allocate it now.
+ result = TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (this->length_);
+ this->buffer_ = result;
+ }
+ else
+ {
+ result =
+ ACE_reinterpret_cast (CORBA::Octet*,this->buffer_);
+ }
+ }
+ else if (this->mb_ != 0) // (orphan == CORBA::B_TRUE)
+ {
+ // We must create a copy anyway:
+ // the user is supposed to call freebuf() to release the
+ // buffer, but the buffer is inside a Message_Block...
+ // We thought about storing the pointer to the Message_Block
+ // somewhere at the beginning of the buffer (before the actual
+ // data), but that will not work in 64 bit machines when the
+ // buffer comes from a CDR stream.
+ //
+ result = TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (this->length_);
+ ACE_OS::memcpy (result, this->buffer_, this->length_);
+ }
+ else if (this->release_ != CORBA::B_FALSE)
+ {
+ // We set the state back to default and relinquish
+ // ownership.
+ result = ACE_reinterpret_cast(CORBA::Octet*,this->buffer_);
+ this->maximum_ = 0;
+ this->length_ = 0;
+ this->buffer_ = 0;
+ this->release_ = CORBA::B_FALSE;
+ }
+ /* else
+ // Oops, it's not our buffer to relinquish...
+ return 0;
+ */
+ return result;
+}
+
+void
+TAO_Unbounded_Sequence<CORBA::Octet>::replace (CORBA::ULong max,
+ CORBA::ULong length,
+ CORBA::Octet *data,
+ CORBA::Boolean release)
+{
+ this->maximum_ = max;
+ this->length_ = length;
+ if (this->mb_ != 0)
+ {
+ ACE_Message_Block::release (this->mb_);
+ this->mb_ = 0;
+ }
+ else if (this->buffer_ && this->release_ == CORBA::B_TRUE)
+ {
+ CORBA::Octet* tmp = ACE_reinterpret_cast(CORBA::Octet*,this->buffer_);
+ TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (tmp);
+ }
+ this->buffer_ = data;
+ this->release_ = release;
+}
+
+void TAO_Unbounded_Sequence<CORBA::Octet>::_deallocate_buffer (void)
+{
+ if (this->mb_ == 0
+ && this->buffer_ != 0
+ && this->release_ != 0)
+ {
+ CORBA::Octet *tmp = ACE_reinterpret_cast (CORBA::Octet *, this->buffer_);
+ TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (tmp);
+ }
+ else
+ {
+ ACE_Message_Block::release (this->mb_);
+ this->mb_ = 0;
+ }
+ this->buffer_ = 0;
+}
+
+#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
diff --git a/TAO/tao/Sequence.h b/TAO/tao/Sequence.h
index 7d7c62bd921..5db81018867 100644
--- a/TAO/tao/Sequence.h
+++ b/TAO/tao/Sequence.h
@@ -95,6 +95,8 @@ protected:
// destroyed.
};
+// ****************************************************************
+
class TAO_Export TAO_Unbounded_Base_Sequence : public TAO_Base_Sequence
{
// = TITLE
@@ -139,6 +141,8 @@ protected:
// Assume ownership and set length to 0.
};
+// ****************************************************************
+
class TAO_Export TAO_Bounded_Base_Sequence : public TAO_Base_Sequence
{
// = TITLE
@@ -234,6 +238,8 @@ private:
// control memory managment semantics.
};
+// ****************************************************************
+
class TAO_Export TAO_Unbounded_String_Sequence : public TAO_Unbounded_Base_Sequence
{
// =TITLE
@@ -348,6 +354,90 @@ public:
CORBA::ULong old_length);
};
+// ****************************************************************
+
+#if defined (TAO_NO_COPY_OCTET_SEQUENCES)
+class ACE_Message_Block;
+template<class T> class TAO_Unbounded_Sequence;
+// forward declaration, we are going to specialize that template
+// here.
+// The template itself requires this file so every user of the
+// template should also see the specialization.
+
+class TAO_Export TAO_Unbounded_Sequence<CORBA::Octet> : public TAO_Unbounded_Base_Sequence
+{
+ // = TITLE
+ // An unbounded sequence of Octets
+ //
+ // = DESCRIPTION
+ // Marshalling and demarshalling cctet sequences can be highly
+ // optimize, for instance at demarshalling we don't require a copy
+ // from the CDR buffer to the octet sequence buffer, we can simply
+ // hold a duplicate of the underlying ACE_Message_Block.
+ // Specializing the TAO_Unbounded_Sequence<T> parametric
+ // class, is an excellent way to achieve this optimizations.
+ //
+public:
+ friend class TAO_Marshal_Sequence;
+ // For efficient marshalling and demarshalling.
+
+ TAO_Unbounded_Sequence<CORBA::Octet> (void);
+ TAO_Unbounded_Sequence<CORBA::Octet> (CORBA::ULong max);
+ TAO_Unbounded_Sequence<CORBA::Octet> (CORBA::ULong max,
+ CORBA::ULong length,
+ CORBA::Octet *data,
+ CORBA::Boolean release = 0);
+ ~TAO_Unbounded_Sequence (void);
+ // see TAO_Unbounded_Sequence in "Sequence_T.h"
+
+ TAO_Unbounded_Sequence (const TAO_Unbounded_Sequence<CORBA::Octet> &);
+ TAO_Unbounded_Sequence<CORBA::Octet>& operator= (const TAO_Unbounded_Sequence<CORBA::Octet> &);
+ // The copy constructor and assignment operators *do* copy the data,
+ // though we could simply duplicate the ref count in the
+ // ACE_Message_Block this will change the semantics for this
+ // operations.
+
+ CORBA::Octet &operator[] (CORBA::ULong);
+ const CORBA::Octet &operator[] (CORBA::ULong) const;
+ // See the general description in "Sequence_T.h"
+
+ // = Static operations.
+
+ static CORBA::Octet *allocbuf (CORBA::ULong);
+ // Allocate storage for the sequence, please note that the storage
+ // is always held in a ACE_Message_Block.
+
+ static void freebuf (CORBA::Octet *);
+ // Free the storage.
+
+ virtual void _allocate_buffer (CORBA::ULong length);
+ virtual void _deallocate_buffer (void);
+ // Implement the methods for all the sequence, please seee
+ // TAO_Base_Sequence.
+
+ // = orbos/98-01-11 proposed extensions.
+ CORBA::Octet *get_buffer (CORBA::Boolean orphan = CORBA::B_FALSE);
+ const CORBA::Octet *get_buffer (void) const;
+ void replace (CORBA::ULong max,
+ CORBA::ULong length,
+ CORBA::Octet *data,
+ CORBA::Boolean release = CORBA::B_FALSE);
+ // See the general description of this methods in "Sequence_T.h".
+
+ // = TAO extension
+ ACE_Message_Block* mb (void);
+ // returns a duplicate of the underlying message block, it is the
+ // caller responsability to release the copy (IMHO this is
+ // consistent with the CORBA calling semantics, return values are
+ // owned by the caller).
+
+private:
+ ACE_Message_Block* mb_;
+};
+#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
+
+// ****************************************************************
+
#if defined (__ACE_INLINE__)
#include "tao/Sequence.i"
#endif /* __ACE_INLINE__ */
diff --git a/TAO/tao/Sequence.i b/TAO/tao/Sequence.i
index 206a4b76752..74bf9c49134 100644
--- a/TAO/tao/Sequence.i
+++ b/TAO/tao/Sequence.i
@@ -222,3 +222,71 @@ TAO_Unbounded_String_Sequence::operator[] (CORBA::ULong index) const
ACE_reinterpret_cast (char **ACE_CAST_CONST, this->buffer_);
return TAO_String_Manager (tmp + index, this->release_);
}
+
+// ****************************************************************
+
+#if defined (TAO_NO_COPY_OCTET_SEQUENCES)
+ACE_INLINE CORBA::Octet *
+TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (CORBA::ULong size)
+{
+ return new CORBA::Octet[size];
+}
+
+ACE_INLINE void
+TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (CORBA::Octet *buffer)
+{
+ delete [] buffer;
+}
+
+ACE_INLINE
+TAO_Unbounded_Sequence<CORBA::Octet>::TAO_Unbounded_Sequence (void)
+ : mb_ (0)
+{
+}
+
+ACE_INLINE
+TAO_Unbounded_Sequence<CORBA::Octet>::TAO_Unbounded_Sequence (CORBA::ULong maximum)
+ : TAO_Unbounded_Base_Sequence (maximum,
+ TAO_Unbounded_Sequence<CORBA::Octet>::allocbuf (maximum)),
+ mb_ (0)
+{
+}
+
+ACE_INLINE
+TAO_Unbounded_Sequence<CORBA::Octet>::TAO_Unbounded_Sequence (CORBA::ULong maximum,
+ CORBA::ULong length,
+ CORBA::Octet *data,
+ CORBA::Boolean release)
+ : TAO_Unbounded_Base_Sequence (maximum, length, data, release),
+ mb_ (0)
+{
+}
+
+ACE_INLINE const CORBA::Octet *
+TAO_Unbounded_Sequence<CORBA::Octet>::get_buffer (void) const
+{
+ return ACE_reinterpret_cast(const CORBA::Octet * ACE_CAST_CONST, this->buffer_);
+}
+
+ACE_INLINE CORBA::Octet &
+TAO_Unbounded_Sequence<CORBA::Octet>::operator[] (CORBA::ULong i)
+{
+ ACE_ASSERT (i < this->maximum_);
+ CORBA::Octet* tmp = ACE_reinterpret_cast(CORBA::Octet*,this->buffer_);
+ return tmp[i];
+}
+
+ACE_INLINE const CORBA::Octet &
+TAO_Unbounded_Sequence<CORBA::Octet>::operator[] (CORBA::ULong i) const
+{
+ ACE_ASSERT (i < this->maximum_);
+ CORBA::Octet * const tmp = ACE_reinterpret_cast (CORBA::Octet* ACE_CAST_CONST, this->buffer_);
+ return tmp[i];
+}
+
+ACE_INLINE ACE_Message_Block*
+TAO_Unbounded_Sequence<CORBA::Octet>::mb (void)
+{
+ return ACE_Message_Block::duplicate (this->mb_);
+}
+#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
diff --git a/TAO/tao/Sequence_T.cpp b/TAO/tao/Sequence_T.cpp
index 097df14b76c..2af87489898 100644
--- a/TAO/tao/Sequence_T.cpp
+++ b/TAO/tao/Sequence_T.cpp
@@ -76,7 +76,7 @@ void TAO_Unbounded_Sequence<T>::_allocate_buffer (CORBA::ULong length)
tmp[i] = old[i];
if (this->release_)
- delete[] old;
+ TAO_Unbounded_Sequence<T>::freebuf (old);
}
this->buffer_ = tmp;
diff --git a/TAO/tao/Sequence_T.h b/TAO/tao/Sequence_T.h
index 14560d732be..9a5601ae42b 100644
--- a/TAO/tao/Sequence_T.h
+++ b/TAO/tao/Sequence_T.h
@@ -68,9 +68,9 @@ public:
static void freebuf (T *);
// Free the sequence.
- // @@ What do these methods do? (i.e., please add comments).
virtual void _allocate_buffer (CORBA::ULong length);
virtual void _deallocate_buffer (void);
+ // Implement the TAO_Base_Sequence methods (see Sequence.h)
// = orbos/98-01-11 proposed extensions.
T *get_buffer (CORBA::Boolean orphan = CORBA::B_FALSE);
diff --git a/TAO/tao/Sequence_T.i b/TAO/tao/Sequence_T.i
index 15015f25b21..5c06708a01e 100644
--- a/TAO/tao/Sequence_T.i
+++ b/TAO/tao/Sequence_T.i
@@ -5,43 +5,82 @@
// Operations on the generic unbounded sequence class.
// ***************************************************
+template <class T> ACE_INLINE T *
+TAO_Unbounded_Sequence<T>::allocbuf (CORBA::ULong size)
+{
+ return new T[size];
+}
+
+template <class T> ACE_INLINE void
+TAO_Unbounded_Sequence<T>::freebuf (T *buffer)
+{
+ delete [] buffer;
+}
+
template <class T> ACE_INLINE
TAO_Unbounded_Sequence<T>::TAO_Unbounded_Sequence (void)
{
}
+template <class T> ACE_INLINE
+TAO_Unbounded_Sequence<T>::TAO_Unbounded_Sequence (CORBA::ULong maximum)
+ : TAO_Unbounded_Base_Sequence (maximum,
+ TAO_Unbounded_Sequence<T>::allocbuf (maximum))
+{
+}
+
+template <class T> ACE_INLINE
+TAO_Unbounded_Sequence<T>::TAO_Unbounded_Sequence (CORBA::ULong maximum,
+ CORBA::ULong length,
+ T *data,
+ CORBA::Boolean release)
+ : TAO_Unbounded_Base_Sequence (maximum, length, data, release)
+{
+}
+
template <class T> ACE_INLINE T *
TAO_Unbounded_Sequence<T>::get_buffer (CORBA::Boolean orphan)
{
+ T *result = 0;
if (orphan == CORBA::B_FALSE)
{
// We retain ownership.
if (this->buffer_ == 0)
- this->buffer_ = (void *) new T[this->length_];
+ {
+ result = TAO_Unbounded_Sequence<T>::allocbuf (this->length_);
+ this->buffer_ = result;
+ }
+ else
+ {
+ result =
+ ACE_reinterpret_cast (T*, this->buffer_);
+ }
}
else // if (orphan == CORBA::B_TRUE)
{
- if (this->release_ == CORBA::B_FALSE)
- // Oops, it's not our buffer to relinquish...
- return 0;
- else
+ if (this->release_ != CORBA::B_FALSE)
{
// We set the state back to default and relinquish
// ownership.
+ result = ACE_reinterpret_cast(T*,this->buffer_);
this->maximum_ = 0;
this->length_ = 0;
this->buffer_ = 0;
this->release_ = CORBA::B_FALSE;
}
+ /* else
+ // Oops, it's not our buffer to relinquish...
+ return 0;
+ */
}
- return (T *) this->buffer_;
+ return result;
}
template <class T> ACE_INLINE const T *
TAO_Unbounded_Sequence<T>::get_buffer (void) const
{
- return (const T *) this->buffer_;
+ return ACE_reinterpret_cast(const T *, this->buffer_);
}
template <class T> ACE_INLINE void
@@ -53,27 +92,15 @@ TAO_Unbounded_Sequence<T>::replace (CORBA::ULong max,
this->maximum_ = max;
this->length_ = length;
if (this->buffer_ && this->release_ == CORBA::B_TRUE)
+ {
+ T *tmp = ACE_reinterpret_cast(T*,this->buffer_);
+ TAO_Unbounded_Sequence<CORBA::Octet>::freebuf (tmp);
+ }
TAO_Unbounded_Sequence<T>::freebuf ((T *) this->buffer_);
this->buffer_ = data;
this->release_ = release;
}
-template <class T> ACE_INLINE
-TAO_Unbounded_Sequence<T>::TAO_Unbounded_Sequence (CORBA::ULong maximum)
- : TAO_Unbounded_Base_Sequence (maximum,
- TAO_Unbounded_Sequence<T>::allocbuf (maximum))
-{
-}
-
-template <class T> ACE_INLINE
-TAO_Unbounded_Sequence<T>::TAO_Unbounded_Sequence (CORBA::ULong maximum,
- CORBA::ULong length,
- T *data,
- CORBA::Boolean release)
- : TAO_Unbounded_Base_Sequence (maximum, length, data, release)
-{
-}
-
template <class T> ACE_INLINE T &
TAO_Unbounded_Sequence<T>::operator[] (CORBA::ULong i)
{
@@ -90,54 +117,74 @@ TAO_Unbounded_Sequence<T>::operator[] (CORBA::ULong i) const
return tmp[i];
}
-template <class T> ACE_INLINE T *
-TAO_Unbounded_Sequence<T>::allocbuf (CORBA::ULong size)
+// ***************************************************
+// operations on the generic Bounded sequence class
+// ***************************************************
+
+template <class T, CORBA::ULong MAX> ACE_INLINE T *
+TAO_Bounded_Sequence<T, MAX>::allocbuf (CORBA::ULong)
{
- return new T[size];
+ return new T[MAX];
}
-template <class T> ACE_INLINE void
-TAO_Unbounded_Sequence<T>::freebuf (T *buffer)
+template <class T, CORBA::ULong MAX> ACE_INLINE void
+TAO_Bounded_Sequence<T, MAX>::freebuf (T *buffer)
{
delete [] buffer;
}
-// ***************************************************
-// operations on the generic Bounded sequence class
-// ***************************************************
+template <class T, CORBA::ULong MAX> ACE_INLINE
+TAO_Bounded_Sequence<T, MAX>::TAO_Bounded_Sequence (void)
+{
+}
+
+template <class T, CORBA::ULong MAX> ACE_INLINE
+TAO_Bounded_Sequence<T, MAX>::TAO_Bounded_Sequence (CORBA::ULong length,
+ T *data,
+ CORBA::Boolean release)
+ : TAO_Bounded_Base_Sequence (length, MAX, data, release)
+{
+}
template <class T, CORBA::ULong MAX> ACE_INLINE T *
TAO_Bounded_Sequence<T, MAX>::get_buffer (CORBA::Boolean orphan)
{
+ T *result = 0;
if (orphan == CORBA::B_FALSE)
{
// We retain ownership.
if (this->buffer_ == 0)
- this->buffer_ = (void *) new T[this->maximum_];
+ {
+ result = TAO_Bounded_Sequence<T,MAX>::allocbuf (this->maximum_);
+ this->buffer_ = result;
+ }
+ else
+ {
+ result =
+ ACE_reinterpret_cast (T*, this->buffer_);
+ }
}
else // if (orphan == CORBA::B_TRUE)
{
- if (this->release_ == CORBA::B_FALSE)
- // Oops, it's not our buffer to relinquish...
- return 0;
- else
+ if (this->release_ != CORBA::B_FALSE)
{
// We set the state back to default and relinquish
// ownership.
+ result = ACE_reinterpret_cast(T*,this->buffer_);
this->maximum_ = 0;
this->length_ = 0;
this->buffer_ = 0;
this->release_ = CORBA::B_FALSE;
}
}
- return (T *) this->buffer_;
+ return result;
}
template <class T, CORBA::ULong MAX> ACE_INLINE const T *
TAO_Bounded_Sequence<T, MAX>::get_buffer (void) const
{
- return (const T *) this->buffer_;
+ return ACE_reinterpret_cast(const T *, this->buffer_);
}
template <class T, CORBA::ULong MAX> ACE_INLINE void
@@ -149,24 +196,14 @@ TAO_Bounded_Sequence<T, MAX>::replace (CORBA::ULong max,
this->maximum_ = max;
this->length_ = length;
if (this->buffer_ && this->release_ == CORBA::B_TRUE)
- TAO_Bounded_Sequence<T, MAX>::freebuf ((T *) this->buffer_);
+ {
+ T* tmp = ACE_reinterpret_cast(T*, this->buffer_);
+ TAO_Bounded_Sequence<T, MAX>::freebuf (tmp);
+ }
this->buffer_ = data;
this->release_ = release;
}
-template <class T, CORBA::ULong MAX> ACE_INLINE
-TAO_Bounded_Sequence<T, MAX>::TAO_Bounded_Sequence (void)
-{
-}
-
-template <class T, CORBA::ULong MAX> ACE_INLINE
-TAO_Bounded_Sequence<T, MAX>::TAO_Bounded_Sequence (CORBA::ULong length,
- T *data,
- CORBA::Boolean release)
- : TAO_Bounded_Base_Sequence (length, MAX, data, release)
-{
-}
-
template <class T, CORBA::ULong MAX> ACE_INLINE T &
TAO_Bounded_Sequence<T, MAX>::operator[] (CORBA::ULong i)
{
@@ -179,22 +216,10 @@ template <class T, CORBA::ULong MAX> ACE_INLINE const T &
TAO_Bounded_Sequence<T, MAX>::operator[] (CORBA::ULong i) const
{
ACE_ASSERT (i < this->maximum_);
- const T* tmp = ACE_reinterpret_cast (const T*,this->buffer_);
+ const T* tmp = ACE_reinterpret_cast (const T* ACE_CAST_CONST,this->buffer_);
return tmp[i];
}
-template <class T, CORBA::ULong MAX> ACE_INLINE T *
-TAO_Bounded_Sequence<T, MAX>::allocbuf (CORBA::ULong)
-{
- return new T[MAX];
-}
-
-template <class T, CORBA::ULong MAX> ACE_INLINE void
-TAO_Bounded_Sequence<T, MAX>::freebuf (T *buffer)
-{
- delete [] buffer;
-}
-
// *************************************************************
// Inline operations for class TAO_Object_Manager<T>
// *************************************************************
diff --git a/TAO/tao/decode.cpp b/TAO/tao/decode.cpp
index c9f4b2bb48a..5afcdc6bb39 100644
--- a/TAO/tao/decode.cpp
+++ b/TAO/tao/decode.cpp
@@ -1057,15 +1057,12 @@ TAO_Marshal_Sequence::decode (CORBA::TypeCode_ptr tc,
// here, on the "be gracious in what you accept" principle. We
// don't generate illegal sequences (i.e. length > bounds).
- continue_decoding = stream->read_ulong (seq->length_);
- seq->maximum_ = seq->length_;
- seq->release_ = 1;
- seq->buffer_ = 0;
+ continue_decoding = stream->read_ulong (bounds);
if (continue_decoding)
{
// No point decoding an empty sequence.
- if (seq->length_ > 0)
+ if (bounds > 0)
{
// Get element typecode.
tc2 = tc->content_type (env);
@@ -1076,14 +1073,41 @@ TAO_Marshal_Sequence::decode (CORBA::TypeCode_ptr tc,
if (env.exception () == 0)
{
- bounds = seq->length_;
+#if defined (TAO_NO_COPY_OCTET_SEQUENCES)
+ // The treatment of octet sequences is completely
+ // different.
+ if (tc2->kind_ == CORBA::tk_octet
+ && ACE_BIT_DISABLED (stream->start ()->flags (),
+ ACE_Message_Block::DONT_DELETE))
+ {
+ TAO_Unbounded_Sequence<CORBA::Octet>* seq2 =
+ ACE_dynamic_cast(TAO_Unbounded_Sequence<CORBA::Octet>*, seq);
+ seq2->_deallocate_buffer ();
+ seq2->mb_ = stream->start ()->duplicate ();
+ seq2->buffer_ = seq2->mb_->rd_ptr ();
+ seq2->maximum_ = bounds;
+ seq2->length_ = bounds;
+ stream->skip_bytes (bounds);
+ return CORBA::TypeCode::TRAVERSE_CONTINUE;
+ }
+#endif /* defined (TAO_NO_COPY_OCTET_SEQUENCES) */
// Allocate the buffer using the virtual
// _allocate_buffer method, hence the right
// constructors are invoked and size for the array
// is OK. The sequence will release it, since its
// release_ field is 1.
- seq->_allocate_buffer (bounds);
+ if (seq->maximum_ < bounds)
+ {
+ seq->_deallocate_buffer ();
+ seq->maximum_ = bounds;
+ seq->release_ = 1;
+ seq->buffer_ = 0;
+ seq->_allocate_buffer (bounds);
+ }
+ // In any case the sequence length is changed.
+ seq->length_ = bounds;
+
value = (char *) seq->buffer_;
@@ -1136,6 +1160,14 @@ TAO_Marshal_Sequence::decode (CORBA::TypeCode_ptr tc,
break;
case CORBA::tk_char:
+ // For primitives, compute the size only once
+ continue_decoding = continue_decoding &&
+ stream->read_char_array
+ ((CORBA::Char *) value, bounds);
+ if (continue_decoding == CORBA::B_TRUE)
+ return CORBA::TypeCode::TRAVERSE_CONTINUE;
+ break;
+
case CORBA::tk_octet:
// For primitives, compute the size only once
continue_decoding = continue_decoding &&
diff --git a/TAO/tao/orbconf.h b/TAO/tao/orbconf.h
index dee6eaaf6dc..6f11bd03b26 100644
--- a/TAO/tao/orbconf.h
+++ b/TAO/tao/orbconf.h
@@ -133,6 +133,17 @@
// #define TAO_DISABLE_SWAP_ON_READ
//
+//
+// For some applications it is important to optimize octet sequences
+// and minimize the number of copies made of the sequence buffer.
+// TAO supports this optimizations by sharing the CDR stream buffer
+// and the octet sequences buffer via ACE_Message_Block's.
+// This feature can be disabled for: debugging, performance
+// comparisons, complaince checking (the octet sequences add an API to
+// access the underlying message block).
+//
+#define TAO_NO_COPY_OCTET_SEQUENCES
+
// BC++ seems to have a different convention for detecting Win32 than
// VC++.
diff --git a/TAO/tests/Makefile b/TAO/tests/Makefile
index 4aebdf4609a..541b4c88a9e 100644
--- a/TAO/tests/Makefile
+++ b/TAO/tests/Makefile
@@ -15,6 +15,7 @@ DIRS = Cubit \
Param_Test \
Thruput \
CDR \
+ OctetSeq \
# The following tests have not been updated yet
# Demux_Test
diff --git a/TAO/tests/OctetSeq/Makefile b/TAO/tests/OctetSeq/Makefile
new file mode 100644
index 00000000000..6849cc85fc4
--- /dev/null
+++ b/TAO/tests/OctetSeq/Makefile
@@ -0,0 +1,604 @@
+#----------------------------------------------------------------------------
+#
+# $Id$
+#
+#----------------------------------------------------------------------------
+
+#----------------------------------------------------------------------------
+# Local macros
+#----------------------------------------------------------------------------
+
+ifndef TAO_ROOT
+ TAO_ROOT = $(ACE_ROOT)/TAO
+endif # ! TAO_ROOT
+
+LDLIBS = -lTAO
+LDFLAGS += -L$(TAO_ROOT)/tao
+
+IDL_HDR = testC.h testS.h
+IDL_SRC = testC.cpp testS.cpp
+
+PROG_SRCS = \
+ OctetSeq.cpp \
+
+LSRC = $(PROG_SRCS) $(IDL_SRC)
+
+OCTETSEQ_OBJS = testC.o testS.o OctetSeq.o
+
+BIN = OctetSeq
+BUILD = $(BIN)
+VLDLIBS = $(LDLIBS:%=%$(VAR))
+VBIN = $(BIN:%=%$(VAR))
+
+#----------------------------------------------------------------------------
+# Include macros and targets
+#----------------------------------------------------------------------------
+
+include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU
+include $(ACE_ROOT)/include/makeinclude/macros.GNU
+include $(TAO_ROOT)/rules.tao.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.common.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU
+#include $(ACE_ROOT)/include/makeinclude/rules.bin.GNU
+include $(ACE_ROOT)/include/makeinclude/rules.local.GNU
+
+CPPFLAGS += -I$(TAO_ROOT) -I$(TAO_ROOT)/tao/compat $(TSS_ORB_FLAG)#-H
+
+OctetSeq: $(addprefix $(VDIR),$(OCTETSEQ_OBJS))
+ $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK)
+
+.PRECIOUS: $(IDL_HDR) $(IDL_SRC)
+
+clean:
+ -/bin/rm -rf *.o $(BIN) obj.* core Templates.DB .make.state
+
+realclean: clean
+ -/bin/rm -rf testC.* testS.*
+
+# DO NOT DELETE THIS LINE -- g++dep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+.obj/OctetSeq.o .obj/OctetSeq.so .shobj/OctetSeq.o .shobj/OctetSeq.so: OctetSeq.cpp \
+ $(ACE_ROOT)/ace/Get_Opt.h \
+ $(ACE_ROOT)/ace/ACE.h \
+ $(ACE_ROOT)/ace/OS.h \
+ $(ACE_ROOT)/ace/inc_user_config.h \
+ $(ACE_ROOT)/ace/config.h \
+ $(ACE_ROOT)/ace/streams.h \
+ $(ACE_ROOT)/ace/Basic_Types.h \
+ $(ACE_ROOT)/ace/Basic_Types.i \
+ $(ACE_ROOT)/ace/OS.i \
+ $(ACE_ROOT)/ace/Trace.h \
+ $(ACE_ROOT)/ace/Log_Msg.h \
+ $(ACE_ROOT)/ace/Log_Record.h \
+ $(ACE_ROOT)/ace/ACE.i \
+ $(ACE_ROOT)/ace/Log_Priority.h \
+ $(ACE_ROOT)/ace/Log_Record.i \
+ $(ACE_ROOT)/ace/Get_Opt.i \
+ $(ACE_ROOT)/ace/High_Res_Timer.h \
+ $(ACE_ROOT)/ace/High_Res_Timer.i \
+ $(TAO_ROOT)/tao/corba.h \
+ $(TAO_ROOT)/tao/orbconf.h \
+ $(ACE_ROOT)/ace/SOCK_Stream.h \
+ $(ACE_ROOT)/ace/SOCK_IO.h \
+ $(ACE_ROOT)/ace/SOCK.h \
+ $(ACE_ROOT)/ace/Addr.h \
+ $(ACE_ROOT)/ace/Addr.i \
+ $(ACE_ROOT)/ace/IPC_SAP.h \
+ $(ACE_ROOT)/ace/IPC_SAP.i \
+ $(ACE_ROOT)/ace/SOCK.i \
+ $(ACE_ROOT)/ace/SOCK_IO.i \
+ $(ACE_ROOT)/ace/INET_Addr.h \
+ $(ACE_ROOT)/ace/INET_Addr.i \
+ $(ACE_ROOT)/ace/SOCK_Stream.i \
+ $(ACE_ROOT)/ace/Synch_T.h \
+ $(ACE_ROOT)/ace/Event_Handler.h \
+ $(ACE_ROOT)/ace/Event_Handler.i \
+ $(ACE_ROOT)/ace/Synch.h \
+ $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(ACE_ROOT)/ace/Synch.i \
+ $(ACE_ROOT)/ace/Synch_T.i \
+ $(ACE_ROOT)/ace/Thread.h \
+ $(ACE_ROOT)/ace/Thread.i \
+ $(ACE_ROOT)/ace/Atomic_Op.i \
+ $(ACE_ROOT)/ace/Hash_Map_Manager.h \
+ $(ACE_ROOT)/ace/SString.h \
+ $(ACE_ROOT)/ace/SString.i \
+ $(ACE_ROOT)/ace/SOCK_Acceptor.h \
+ $(ACE_ROOT)/ace/Time_Value.h \
+ $(ACE_ROOT)/ace/SOCK_Acceptor.i \
+ $(ACE_ROOT)/ace/SOCK_Connector.h \
+ $(ACE_ROOT)/ace/SOCK_Connector.i \
+ $(ACE_ROOT)/ace/Strategies.h \
+ $(ACE_ROOT)/ace/Strategies_T.h \
+ $(ACE_ROOT)/ace/Service_Config.h \
+ $(ACE_ROOT)/ace/Service_Object.h \
+ $(ACE_ROOT)/ace/Shared_Object.h \
+ $(ACE_ROOT)/ace/Shared_Object.i \
+ $(ACE_ROOT)/ace/Service_Object.i \
+ $(ACE_ROOT)/ace/Signal.h \
+ $(ACE_ROOT)/ace/Containers.h \
+ $(ACE_ROOT)/ace/Containers.i \
+ $(ACE_ROOT)/ace/Signal.i \
+ $(ACE_ROOT)/ace/Object_Manager.h \
+ $(ACE_ROOT)/ace/Object_Manager.i \
+ $(ACE_ROOT)/ace/Managed_Object.h \
+ $(ACE_ROOT)/ace/Managed_Object.i \
+ $(ACE_ROOT)/ace/Service_Config.i \
+ $(ACE_ROOT)/ace/Reactor.h \
+ $(ACE_ROOT)/ace/Handle_Set.h \
+ $(ACE_ROOT)/ace/Handle_Set.i \
+ $(ACE_ROOT)/ace/Timer_Queue.h \
+ $(ACE_ROOT)/ace/Timer_Queue_T.h \
+ $(ACE_ROOT)/ace/Free_List.h \
+ $(ACE_ROOT)/ace/Free_List.i \
+ $(ACE_ROOT)/ace/Timer_Queue_T.i \
+ $(ACE_ROOT)/ace/Reactor.i \
+ $(ACE_ROOT)/ace/Reactor_Impl.h \
+ $(ACE_ROOT)/ace/Svc_Conf_Tokens.h \
+ $(ACE_ROOT)/ace/Synch_Options.h \
+ $(ACE_ROOT)/ace/Connector.h \
+ $(ACE_ROOT)/ace/Map_Manager.h \
+ $(ACE_ROOT)/ace/Map_Manager.i \
+ $(ACE_ROOT)/ace/Svc_Handler.h \
+ $(ACE_ROOT)/ace/Task.h \
+ $(ACE_ROOT)/ace/Thread_Manager.h \
+ $(ACE_ROOT)/ace/Thread_Manager.i \
+ $(ACE_ROOT)/ace/Task.i \
+ $(ACE_ROOT)/ace/Task_T.h \
+ $(ACE_ROOT)/ace/Message_Queue.h \
+ $(ACE_ROOT)/ace/Message_Block.h \
+ $(ACE_ROOT)/ace/Malloc.h \
+ $(ACE_ROOT)/ace/Malloc.i \
+ $(ACE_ROOT)/ace/Malloc_T.h \
+ $(ACE_ROOT)/ace/Malloc_T.i \
+ $(ACE_ROOT)/ace/Memory_Pool.h \
+ $(ACE_ROOT)/ace/Mem_Map.h \
+ $(ACE_ROOT)/ace/Mem_Map.i \
+ $(ACE_ROOT)/ace/Memory_Pool.i \
+ $(ACE_ROOT)/ace/Message_Block.i \
+ $(ACE_ROOT)/ace/IO_Cntl_Msg.h \
+ $(ACE_ROOT)/ace/Message_Queue.i \
+ $(ACE_ROOT)/ace/Task_T.i \
+ $(ACE_ROOT)/ace/Dynamic.h \
+ $(ACE_ROOT)/ace/Dynamic.i \
+ $(ACE_ROOT)/ace/Singleton.h \
+ $(ACE_ROOT)/ace/Singleton.i \
+ $(ACE_ROOT)/ace/Svc_Handler.i \
+ $(ACE_ROOT)/ace/Connector.i \
+ $(ACE_ROOT)/ace/Acceptor.h \
+ $(ACE_ROOT)/ace/Acceptor.i \
+ $(TAO_ROOT)/tao/compat/objbase.h \
+ $(TAO_ROOT)/tao/compat/initguid.h \
+ $(TAO_ROOT)/tao/Align.h \
+ $(TAO_ROOT)/tao/ORB.h \
+ $(TAO_ROOT)/tao/Sequence.h \
+ $(TAO_ROOT)/tao/Sequence.i \
+ $(TAO_ROOT)/tao/Sequence_T.h \
+ $(TAO_ROOT)/tao/Sequence_T.i \
+ $(TAO_ROOT)/tao/Object_KeyC.h \
+ $(TAO_ROOT)/tao/Object_KeyC.i \
+ $(TAO_ROOT)/tao/ORB.i \
+ $(TAO_ROOT)/tao/Exception.h \
+ $(TAO_ROOT)/tao/Exception.i \
+ $(TAO_ROOT)/tao/Any.h \
+ $(TAO_ROOT)/tao/Any.i \
+ $(TAO_ROOT)/tao/params.h \
+ $(TAO_ROOT)/tao/params.i \
+ $(TAO_ROOT)/tao/Client_Strategy_Factory.h \
+ $(TAO_ROOT)/tao/Server_Strategy_Factory.h \
+ $(TAO_ROOT)/tao/default_client.h \
+ $(TAO_ROOT)/tao/default_client.i \
+ $(TAO_ROOT)/tao/default_server.h \
+ $(TAO_ROOT)/tao/ORB_Strategies_T.h \
+ $(TAO_ROOT)/tao/ORB_Strategies_T.i \
+ $(TAO_ROOT)/tao/default_server.i \
+ $(TAO_ROOT)/tao/NVList.h \
+ $(TAO_ROOT)/tao/NVList.i \
+ $(TAO_ROOT)/tao/Principal.h \
+ $(TAO_ROOT)/tao/Request.h \
+ $(TAO_ROOT)/tao/Request.i \
+ $(TAO_ROOT)/tao/Stub.h \
+ $(TAO_ROOT)/tao/Stub.i \
+ $(TAO_ROOT)/tao/Object.h \
+ $(TAO_ROOT)/tao/Object.i \
+ $(TAO_ROOT)/tao/Server_Request.h \
+ $(TAO_ROOT)/tao/Server_Request.i \
+ $(TAO_ROOT)/tao/Typecode.h \
+ $(TAO_ROOT)/tao/Typecode.i \
+ $(TAO_ROOT)/tao/Marshal.h \
+ $(TAO_ROOT)/tao/Marshal.i \
+ $(TAO_ROOT)/tao/CDR.h \
+ $(TAO_ROOT)/tao/CDR.i \
+ $(TAO_ROOT)/tao/PolicyC.h \
+ $(TAO_ROOT)/tao/PolicyC.i \
+ $(TAO_ROOT)/tao/POA.h \
+ $(TAO_ROOT)/tao/POAC.h \
+ $(TAO_ROOT)/tao/POAC.i \
+ $(TAO_ROOT)/tao/Servant_Base.h \
+ $(TAO_ROOT)/tao/POAS.h \
+ $(TAO_ROOT)/tao/PolicyS.h \
+ $(TAO_ROOT)/tao/PolicyS.i \
+ $(TAO_ROOT)/tao/POAS.i \
+ $(TAO_ROOT)/tao/Object_Table.h \
+ $(TAO_ROOT)/tao/Connect.h \
+ $(TAO_ROOT)/tao/Connect.i \
+ $(TAO_ROOT)/tao/ORB_Core.h \
+ $(TAO_ROOT)/tao/ORB_Core.i \
+ $(ACE_ROOT)/ace/Dynamic_Service.h \
+ $(TAO_ROOT)/tao/Operation_Table.h \
+ $(TAO_ROOT)/tao/debug.h \
+ $(TAO_ROOT)/tao/IIOP_Object.h \
+ $(TAO_ROOT)/tao/IIOP_Object.i \
+ $(TAO_ROOT)/tao/IIOP_ORB.h \
+ $(TAO_ROOT)/tao/IIOP_ORB.i \
+ $(TAO_ROOT)/tao/IIOP_Interpreter.h \
+ $(TAO_ROOT)/tao/GIOP.h \
+ $(TAO_ROOT)/tao/GIOP.i \
+ $(TAO_ROOT)/tao/singletons.h \
+ testC.h testC.i
+.obj/testC.o .obj/testC.so .shobj/testC.o .shobj/testC.so: testC.cpp testC.h \
+ $(TAO_ROOT)/tao/corba.h \
+ $(TAO_ROOT)/tao/orbconf.h \
+ $(ACE_ROOT)/ace/OS.h \
+ $(ACE_ROOT)/ace/inc_user_config.h \
+ $(ACE_ROOT)/ace/config.h \
+ $(ACE_ROOT)/ace/streams.h \
+ $(ACE_ROOT)/ace/Basic_Types.h \
+ $(ACE_ROOT)/ace/Basic_Types.i \
+ $(ACE_ROOT)/ace/OS.i \
+ $(ACE_ROOT)/ace/Trace.h \
+ $(ACE_ROOT)/ace/Log_Msg.h \
+ $(ACE_ROOT)/ace/Log_Record.h \
+ $(ACE_ROOT)/ace/ACE.h \
+ $(ACE_ROOT)/ace/ACE.i \
+ $(ACE_ROOT)/ace/Log_Priority.h \
+ $(ACE_ROOT)/ace/Log_Record.i \
+ $(ACE_ROOT)/ace/Get_Opt.h \
+ $(ACE_ROOT)/ace/Get_Opt.i \
+ $(ACE_ROOT)/ace/SOCK_Stream.h \
+ $(ACE_ROOT)/ace/SOCK_IO.h \
+ $(ACE_ROOT)/ace/SOCK.h \
+ $(ACE_ROOT)/ace/Addr.h \
+ $(ACE_ROOT)/ace/Addr.i \
+ $(ACE_ROOT)/ace/IPC_SAP.h \
+ $(ACE_ROOT)/ace/IPC_SAP.i \
+ $(ACE_ROOT)/ace/SOCK.i \
+ $(ACE_ROOT)/ace/SOCK_IO.i \
+ $(ACE_ROOT)/ace/INET_Addr.h \
+ $(ACE_ROOT)/ace/INET_Addr.i \
+ $(ACE_ROOT)/ace/SOCK_Stream.i \
+ $(ACE_ROOT)/ace/Synch_T.h \
+ $(ACE_ROOT)/ace/Event_Handler.h \
+ $(ACE_ROOT)/ace/Event_Handler.i \
+ $(ACE_ROOT)/ace/Synch.h \
+ $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(ACE_ROOT)/ace/Synch.i \
+ $(ACE_ROOT)/ace/Synch_T.i \
+ $(ACE_ROOT)/ace/Thread.h \
+ $(ACE_ROOT)/ace/Thread.i \
+ $(ACE_ROOT)/ace/Atomic_Op.i \
+ $(ACE_ROOT)/ace/Hash_Map_Manager.h \
+ $(ACE_ROOT)/ace/SString.h \
+ $(ACE_ROOT)/ace/SString.i \
+ $(ACE_ROOT)/ace/SOCK_Acceptor.h \
+ $(ACE_ROOT)/ace/Time_Value.h \
+ $(ACE_ROOT)/ace/SOCK_Acceptor.i \
+ $(ACE_ROOT)/ace/SOCK_Connector.h \
+ $(ACE_ROOT)/ace/SOCK_Connector.i \
+ $(ACE_ROOT)/ace/Strategies.h \
+ $(ACE_ROOT)/ace/Strategies_T.h \
+ $(ACE_ROOT)/ace/Service_Config.h \
+ $(ACE_ROOT)/ace/Service_Object.h \
+ $(ACE_ROOT)/ace/Shared_Object.h \
+ $(ACE_ROOT)/ace/Shared_Object.i \
+ $(ACE_ROOT)/ace/Service_Object.i \
+ $(ACE_ROOT)/ace/Signal.h \
+ $(ACE_ROOT)/ace/Containers.h \
+ $(ACE_ROOT)/ace/Containers.i \
+ $(ACE_ROOT)/ace/Signal.i \
+ $(ACE_ROOT)/ace/Object_Manager.h \
+ $(ACE_ROOT)/ace/Object_Manager.i \
+ $(ACE_ROOT)/ace/Managed_Object.h \
+ $(ACE_ROOT)/ace/Managed_Object.i \
+ $(ACE_ROOT)/ace/Service_Config.i \
+ $(ACE_ROOT)/ace/Reactor.h \
+ $(ACE_ROOT)/ace/Handle_Set.h \
+ $(ACE_ROOT)/ace/Handle_Set.i \
+ $(ACE_ROOT)/ace/Timer_Queue.h \
+ $(ACE_ROOT)/ace/Timer_Queue_T.h \
+ $(ACE_ROOT)/ace/Free_List.h \
+ $(ACE_ROOT)/ace/Free_List.i \
+ $(ACE_ROOT)/ace/Timer_Queue_T.i \
+ $(ACE_ROOT)/ace/Reactor.i \
+ $(ACE_ROOT)/ace/Reactor_Impl.h \
+ $(ACE_ROOT)/ace/Svc_Conf_Tokens.h \
+ $(ACE_ROOT)/ace/Synch_Options.h \
+ $(ACE_ROOT)/ace/Connector.h \
+ $(ACE_ROOT)/ace/Map_Manager.h \
+ $(ACE_ROOT)/ace/Map_Manager.i \
+ $(ACE_ROOT)/ace/Svc_Handler.h \
+ $(ACE_ROOT)/ace/Task.h \
+ $(ACE_ROOT)/ace/Thread_Manager.h \
+ $(ACE_ROOT)/ace/Thread_Manager.i \
+ $(ACE_ROOT)/ace/Task.i \
+ $(ACE_ROOT)/ace/Task_T.h \
+ $(ACE_ROOT)/ace/Message_Queue.h \
+ $(ACE_ROOT)/ace/Message_Block.h \
+ $(ACE_ROOT)/ace/Malloc.h \
+ $(ACE_ROOT)/ace/Malloc.i \
+ $(ACE_ROOT)/ace/Malloc_T.h \
+ $(ACE_ROOT)/ace/Malloc_T.i \
+ $(ACE_ROOT)/ace/Memory_Pool.h \
+ $(ACE_ROOT)/ace/Mem_Map.h \
+ $(ACE_ROOT)/ace/Mem_Map.i \
+ $(ACE_ROOT)/ace/Memory_Pool.i \
+ $(ACE_ROOT)/ace/Message_Block.i \
+ $(ACE_ROOT)/ace/IO_Cntl_Msg.h \
+ $(ACE_ROOT)/ace/Message_Queue.i \
+ $(ACE_ROOT)/ace/Task_T.i \
+ $(ACE_ROOT)/ace/Dynamic.h \
+ $(ACE_ROOT)/ace/Dynamic.i \
+ $(ACE_ROOT)/ace/Singleton.h \
+ $(ACE_ROOT)/ace/Singleton.i \
+ $(ACE_ROOT)/ace/Svc_Handler.i \
+ $(ACE_ROOT)/ace/Connector.i \
+ $(ACE_ROOT)/ace/Acceptor.h \
+ $(ACE_ROOT)/ace/Acceptor.i \
+ $(TAO_ROOT)/tao/compat/objbase.h \
+ $(TAO_ROOT)/tao/compat/initguid.h \
+ $(TAO_ROOT)/tao/Align.h \
+ $(TAO_ROOT)/tao/ORB.h \
+ $(TAO_ROOT)/tao/Sequence.h \
+ $(TAO_ROOT)/tao/Sequence.i \
+ $(TAO_ROOT)/tao/Sequence_T.h \
+ $(TAO_ROOT)/tao/Sequence_T.i \
+ $(TAO_ROOT)/tao/Object_KeyC.h \
+ $(TAO_ROOT)/tao/Object_KeyC.i \
+ $(TAO_ROOT)/tao/ORB.i \
+ $(TAO_ROOT)/tao/Exception.h \
+ $(TAO_ROOT)/tao/Exception.i \
+ $(TAO_ROOT)/tao/Any.h \
+ $(TAO_ROOT)/tao/Any.i \
+ $(TAO_ROOT)/tao/params.h \
+ $(TAO_ROOT)/tao/params.i \
+ $(TAO_ROOT)/tao/Client_Strategy_Factory.h \
+ $(TAO_ROOT)/tao/Server_Strategy_Factory.h \
+ $(TAO_ROOT)/tao/default_client.h \
+ $(TAO_ROOT)/tao/default_client.i \
+ $(TAO_ROOT)/tao/default_server.h \
+ $(TAO_ROOT)/tao/ORB_Strategies_T.h \
+ $(TAO_ROOT)/tao/ORB_Strategies_T.i \
+ $(TAO_ROOT)/tao/default_server.i \
+ $(TAO_ROOT)/tao/NVList.h \
+ $(TAO_ROOT)/tao/NVList.i \
+ $(TAO_ROOT)/tao/Principal.h \
+ $(TAO_ROOT)/tao/Request.h \
+ $(TAO_ROOT)/tao/Request.i \
+ $(TAO_ROOT)/tao/Stub.h \
+ $(TAO_ROOT)/tao/Stub.i \
+ $(TAO_ROOT)/tao/Object.h \
+ $(TAO_ROOT)/tao/Object.i \
+ $(TAO_ROOT)/tao/Server_Request.h \
+ $(TAO_ROOT)/tao/Server_Request.i \
+ $(TAO_ROOT)/tao/Typecode.h \
+ $(TAO_ROOT)/tao/Typecode.i \
+ $(TAO_ROOT)/tao/Marshal.h \
+ $(TAO_ROOT)/tao/Marshal.i \
+ $(TAO_ROOT)/tao/CDR.h \
+ $(TAO_ROOT)/tao/CDR.i \
+ $(TAO_ROOT)/tao/PolicyC.h \
+ $(TAO_ROOT)/tao/PolicyC.i \
+ $(TAO_ROOT)/tao/POA.h \
+ $(TAO_ROOT)/tao/POAC.h \
+ $(TAO_ROOT)/tao/POAC.i \
+ $(TAO_ROOT)/tao/Servant_Base.h \
+ $(TAO_ROOT)/tao/POAS.h \
+ $(TAO_ROOT)/tao/PolicyS.h \
+ $(TAO_ROOT)/tao/PolicyS.i \
+ $(TAO_ROOT)/tao/POAS.i \
+ $(TAO_ROOT)/tao/Object_Table.h \
+ $(TAO_ROOT)/tao/Connect.h \
+ $(TAO_ROOT)/tao/Connect.i \
+ $(TAO_ROOT)/tao/ORB_Core.h \
+ $(TAO_ROOT)/tao/ORB_Core.i \
+ $(ACE_ROOT)/ace/Dynamic_Service.h \
+ $(TAO_ROOT)/tao/Operation_Table.h \
+ $(TAO_ROOT)/tao/debug.h \
+ $(TAO_ROOT)/tao/IIOP_Object.h \
+ $(TAO_ROOT)/tao/IIOP_Object.i \
+ $(TAO_ROOT)/tao/IIOP_ORB.h \
+ $(TAO_ROOT)/tao/IIOP_ORB.i \
+ $(TAO_ROOT)/tao/IIOP_Interpreter.h \
+ $(TAO_ROOT)/tao/GIOP.h \
+ $(TAO_ROOT)/tao/GIOP.i \
+ $(TAO_ROOT)/tao/singletons.h \
+ testC.i testS.h testS.i
+.obj/testS.o .obj/testS.so .shobj/testS.o .shobj/testS.so: testS.cpp testS.h testC.h \
+ $(TAO_ROOT)/tao/corba.h \
+ $(TAO_ROOT)/tao/orbconf.h \
+ $(ACE_ROOT)/ace/OS.h \
+ $(ACE_ROOT)/ace/inc_user_config.h \
+ $(ACE_ROOT)/ace/config.h \
+ $(ACE_ROOT)/ace/streams.h \
+ $(ACE_ROOT)/ace/Basic_Types.h \
+ $(ACE_ROOT)/ace/Basic_Types.i \
+ $(ACE_ROOT)/ace/OS.i \
+ $(ACE_ROOT)/ace/Trace.h \
+ $(ACE_ROOT)/ace/Log_Msg.h \
+ $(ACE_ROOT)/ace/Log_Record.h \
+ $(ACE_ROOT)/ace/ACE.h \
+ $(ACE_ROOT)/ace/ACE.i \
+ $(ACE_ROOT)/ace/Log_Priority.h \
+ $(ACE_ROOT)/ace/Log_Record.i \
+ $(ACE_ROOT)/ace/Get_Opt.h \
+ $(ACE_ROOT)/ace/Get_Opt.i \
+ $(ACE_ROOT)/ace/SOCK_Stream.h \
+ $(ACE_ROOT)/ace/SOCK_IO.h \
+ $(ACE_ROOT)/ace/SOCK.h \
+ $(ACE_ROOT)/ace/Addr.h \
+ $(ACE_ROOT)/ace/Addr.i \
+ $(ACE_ROOT)/ace/IPC_SAP.h \
+ $(ACE_ROOT)/ace/IPC_SAP.i \
+ $(ACE_ROOT)/ace/SOCK.i \
+ $(ACE_ROOT)/ace/SOCK_IO.i \
+ $(ACE_ROOT)/ace/INET_Addr.h \
+ $(ACE_ROOT)/ace/INET_Addr.i \
+ $(ACE_ROOT)/ace/SOCK_Stream.i \
+ $(ACE_ROOT)/ace/Synch_T.h \
+ $(ACE_ROOT)/ace/Event_Handler.h \
+ $(ACE_ROOT)/ace/Event_Handler.i \
+ $(ACE_ROOT)/ace/Synch.h \
+ $(ACE_ROOT)/ace/SV_Semaphore_Complex.h \
+ $(ACE_ROOT)/ace/SV_Semaphore_Simple.h \
+ $(ACE_ROOT)/ace/SV_Semaphore_Simple.i \
+ $(ACE_ROOT)/ace/SV_Semaphore_Complex.i \
+ $(ACE_ROOT)/ace/Synch.i \
+ $(ACE_ROOT)/ace/Synch_T.i \
+ $(ACE_ROOT)/ace/Thread.h \
+ $(ACE_ROOT)/ace/Thread.i \
+ $(ACE_ROOT)/ace/Atomic_Op.i \
+ $(ACE_ROOT)/ace/Hash_Map_Manager.h \
+ $(ACE_ROOT)/ace/SString.h \
+ $(ACE_ROOT)/ace/SString.i \
+ $(ACE_ROOT)/ace/SOCK_Acceptor.h \
+ $(ACE_ROOT)/ace/Time_Value.h \
+ $(ACE_ROOT)/ace/SOCK_Acceptor.i \
+ $(ACE_ROOT)/ace/SOCK_Connector.h \
+ $(ACE_ROOT)/ace/SOCK_Connector.i \
+ $(ACE_ROOT)/ace/Strategies.h \
+ $(ACE_ROOT)/ace/Strategies_T.h \
+ $(ACE_ROOT)/ace/Service_Config.h \
+ $(ACE_ROOT)/ace/Service_Object.h \
+ $(ACE_ROOT)/ace/Shared_Object.h \
+ $(ACE_ROOT)/ace/Shared_Object.i \
+ $(ACE_ROOT)/ace/Service_Object.i \
+ $(ACE_ROOT)/ace/Signal.h \
+ $(ACE_ROOT)/ace/Containers.h \
+ $(ACE_ROOT)/ace/Containers.i \
+ $(ACE_ROOT)/ace/Signal.i \
+ $(ACE_ROOT)/ace/Object_Manager.h \
+ $(ACE_ROOT)/ace/Object_Manager.i \
+ $(ACE_ROOT)/ace/Managed_Object.h \
+ $(ACE_ROOT)/ace/Managed_Object.i \
+ $(ACE_ROOT)/ace/Service_Config.i \
+ $(ACE_ROOT)/ace/Reactor.h \
+ $(ACE_ROOT)/ace/Handle_Set.h \
+ $(ACE_ROOT)/ace/Handle_Set.i \
+ $(ACE_ROOT)/ace/Timer_Queue.h \
+ $(ACE_ROOT)/ace/Timer_Queue_T.h \
+ $(ACE_ROOT)/ace/Free_List.h \
+ $(ACE_ROOT)/ace/Free_List.i \
+ $(ACE_ROOT)/ace/Timer_Queue_T.i \
+ $(ACE_ROOT)/ace/Reactor.i \
+ $(ACE_ROOT)/ace/Reactor_Impl.h \
+ $(ACE_ROOT)/ace/Svc_Conf_Tokens.h \
+ $(ACE_ROOT)/ace/Synch_Options.h \
+ $(ACE_ROOT)/ace/Connector.h \
+ $(ACE_ROOT)/ace/Map_Manager.h \
+ $(ACE_ROOT)/ace/Map_Manager.i \
+ $(ACE_ROOT)/ace/Svc_Handler.h \
+ $(ACE_ROOT)/ace/Task.h \
+ $(ACE_ROOT)/ace/Thread_Manager.h \
+ $(ACE_ROOT)/ace/Thread_Manager.i \
+ $(ACE_ROOT)/ace/Task.i \
+ $(ACE_ROOT)/ace/Task_T.h \
+ $(ACE_ROOT)/ace/Message_Queue.h \
+ $(ACE_ROOT)/ace/Message_Block.h \
+ $(ACE_ROOT)/ace/Malloc.h \
+ $(ACE_ROOT)/ace/Malloc.i \
+ $(ACE_ROOT)/ace/Malloc_T.h \
+ $(ACE_ROOT)/ace/Malloc_T.i \
+ $(ACE_ROOT)/ace/Memory_Pool.h \
+ $(ACE_ROOT)/ace/Mem_Map.h \
+ $(ACE_ROOT)/ace/Mem_Map.i \
+ $(ACE_ROOT)/ace/Memory_Pool.i \
+ $(ACE_ROOT)/ace/Message_Block.i \
+ $(ACE_ROOT)/ace/IO_Cntl_Msg.h \
+ $(ACE_ROOT)/ace/Message_Queue.i \
+ $(ACE_ROOT)/ace/Task_T.i \
+ $(ACE_ROOT)/ace/Dynamic.h \
+ $(ACE_ROOT)/ace/Dynamic.i \
+ $(ACE_ROOT)/ace/Singleton.h \
+ $(ACE_ROOT)/ace/Singleton.i \
+ $(ACE_ROOT)/ace/Svc_Handler.i \
+ $(ACE_ROOT)/ace/Connector.i \
+ $(ACE_ROOT)/ace/Acceptor.h \
+ $(ACE_ROOT)/ace/Acceptor.i \
+ $(TAO_ROOT)/tao/compat/objbase.h \
+ $(TAO_ROOT)/tao/compat/initguid.h \
+ $(TAO_ROOT)/tao/Align.h \
+ $(TAO_ROOT)/tao/ORB.h \
+ $(TAO_ROOT)/tao/Sequence.h \
+ $(TAO_ROOT)/tao/Sequence.i \
+ $(TAO_ROOT)/tao/Sequence_T.h \
+ $(TAO_ROOT)/tao/Sequence_T.i \
+ $(TAO_ROOT)/tao/Object_KeyC.h \
+ $(TAO_ROOT)/tao/Object_KeyC.i \
+ $(TAO_ROOT)/tao/ORB.i \
+ $(TAO_ROOT)/tao/Exception.h \
+ $(TAO_ROOT)/tao/Exception.i \
+ $(TAO_ROOT)/tao/Any.h \
+ $(TAO_ROOT)/tao/Any.i \
+ $(TAO_ROOT)/tao/params.h \
+ $(TAO_ROOT)/tao/params.i \
+ $(TAO_ROOT)/tao/Client_Strategy_Factory.h \
+ $(TAO_ROOT)/tao/Server_Strategy_Factory.h \
+ $(TAO_ROOT)/tao/default_client.h \
+ $(TAO_ROOT)/tao/default_client.i \
+ $(TAO_ROOT)/tao/default_server.h \
+ $(TAO_ROOT)/tao/ORB_Strategies_T.h \
+ $(TAO_ROOT)/tao/ORB_Strategies_T.i \
+ $(TAO_ROOT)/tao/default_server.i \
+ $(TAO_ROOT)/tao/NVList.h \
+ $(TAO_ROOT)/tao/NVList.i \
+ $(TAO_ROOT)/tao/Principal.h \
+ $(TAO_ROOT)/tao/Request.h \
+ $(TAO_ROOT)/tao/Request.i \
+ $(TAO_ROOT)/tao/Stub.h \
+ $(TAO_ROOT)/tao/Stub.i \
+ $(TAO_ROOT)/tao/Object.h \
+ $(TAO_ROOT)/tao/Object.i \
+ $(TAO_ROOT)/tao/Server_Request.h \
+ $(TAO_ROOT)/tao/Server_Request.i \
+ $(TAO_ROOT)/tao/Typecode.h \
+ $(TAO_ROOT)/tao/Typecode.i \
+ $(TAO_ROOT)/tao/Marshal.h \
+ $(TAO_ROOT)/tao/Marshal.i \
+ $(TAO_ROOT)/tao/CDR.h \
+ $(TAO_ROOT)/tao/CDR.i \
+ $(TAO_ROOT)/tao/PolicyC.h \
+ $(TAO_ROOT)/tao/PolicyC.i \
+ $(TAO_ROOT)/tao/POA.h \
+ $(TAO_ROOT)/tao/POAC.h \
+ $(TAO_ROOT)/tao/POAC.i \
+ $(TAO_ROOT)/tao/Servant_Base.h \
+ $(TAO_ROOT)/tao/POAS.h \
+ $(TAO_ROOT)/tao/PolicyS.h \
+ $(TAO_ROOT)/tao/PolicyS.i \
+ $(TAO_ROOT)/tao/POAS.i \
+ $(TAO_ROOT)/tao/Object_Table.h \
+ $(TAO_ROOT)/tao/Connect.h \
+ $(TAO_ROOT)/tao/Connect.i \
+ $(TAO_ROOT)/tao/ORB_Core.h \
+ $(TAO_ROOT)/tao/ORB_Core.i \
+ $(ACE_ROOT)/ace/Dynamic_Service.h \
+ $(TAO_ROOT)/tao/Operation_Table.h \
+ $(TAO_ROOT)/tao/debug.h \
+ $(TAO_ROOT)/tao/IIOP_Object.h \
+ $(TAO_ROOT)/tao/IIOP_Object.i \
+ $(TAO_ROOT)/tao/IIOP_ORB.h \
+ $(TAO_ROOT)/tao/IIOP_ORB.i \
+ $(TAO_ROOT)/tao/IIOP_Interpreter.h \
+ $(TAO_ROOT)/tao/GIOP.h \
+ $(TAO_ROOT)/tao/GIOP.i \
+ $(TAO_ROOT)/tao/singletons.h \
+ testC.i testS.i
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
diff --git a/TAO/tests/OctetSeq/OctetSeq.cpp b/TAO/tests/OctetSeq/OctetSeq.cpp
new file mode 100644
index 00000000000..ac6b094c464
--- /dev/null
+++ b/TAO/tests/OctetSeq/OctetSeq.cpp
@@ -0,0 +1,242 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests/CDR
+//
+// = FILENAME
+// octetseq.cpp
+//
+// = DESCRIPTION
+// TAO optimizes octet sequences, this test verifies that the
+// optimizations do not break any code and that they effectively
+// improve performance.
+//
+// = AUTHORS
+// Carlos O'Ryan
+//
+// ============================================================================
+
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+
+#include "tao/corba.h"
+#include "tao/debug.h"
+#include "testC.h"
+
+static int
+test_write_octet (TAO_OutputCDR &cdr,
+ char* buf, int bufsize,
+ CORBA::Environment& env)
+{
+ Test::OctetSeq os (bufsize, bufsize, (CORBA::Octet*)buf);
+
+ cdr.encode (Test::_tc_OctetSeq_seq, &os, 0, env);
+ if (env.exception () != 0)
+ return -1;
+ return 0;
+}
+
+static int
+test_read_octet (TAO_InputCDR &cdr,
+ char* buf, int bufsize,
+ CORBA::Environment& env)
+{
+ Test::OctetSeq os;
+
+ cdr.decode (Test::_tc_OctetSeq_seq, &os, 0, env);
+ if (env.exception () != 0 ||
+ os.length () != bufsize
+ /* || ACE_OS::memcmp( buf, os.get_buffer (), bufsize) != 0 */)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "OCTET: problem demarshalling or unmatched buffer\n"));
+ return -1;
+ }
+ return 0;
+}
+
+static int
+test_write_char (TAO_OutputCDR &cdr,
+ char* buf, int bufsize,
+ CORBA::Environment& env)
+{
+ Test::CharSeq cs (bufsize, bufsize, buf);
+
+ cdr.encode (Test::_tc_CharSeq_seq, &cs, 0, env);
+ if (env.exception () != 0)
+ return -1;
+ return 0;
+}
+
+static int
+test_read_char (TAO_InputCDR &cdr,
+ char* buf, int bufsize,
+ CORBA::Environment& env)
+{
+ Test::CharSeq cs;
+
+ cdr.decode (Test::_tc_CharSeq_seq, &cs, 0, env);
+ if (env.exception () != 0 ||
+ cs.length () != bufsize
+ /* || ACE_OS::memcmp( buf, cs.get_buffer (), bufsize) != 0 */)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "CHAR: problem demarshalling or unmatched buffer\n"));
+ return -1;
+ }
+ return 0;
+}
+
+typedef
+int (*Writer)(TAO_OutputCDR& cdr,
+ char* buf, int bufsize,
+ CORBA::Environment& env);
+typedef
+int (*Reader)(TAO_InputCDR& cdr,
+ char* buf, int bufsize,
+ CORBA::Environment& env);
+
+int
+run (char* buf, int bufsize,
+ int n, int lo, int s,
+ const char* name,
+ Writer writer, Reader reader,
+ CORBA::Environment& env)
+{
+ for (int x = lo; x <= bufsize; x += s)
+ {
+ ACE_High_Res_Timer writing;
+ ACE_High_Res_Timer reading;
+
+ for (int i = 0; i < n; ++i)
+ {
+ writing.start_incr ();
+ TAO_OutputCDR output (bufsize + 4);
+
+ if (writer (output, buf, x, env) != 0)
+ return -1;
+ writing.stop_incr ();
+
+ reading.start_incr ();
+ TAO_InputCDR input (output);
+ if (reader (input, buf, x, env) != 0)
+ return -1;
+ reading.stop_incr ();
+ }
+ double m = n;
+
+ ACE_Time_Value wtv;
+ writing.elapsed_time_incr (wtv);
+ ACE_hrtime_t wusecs = wtv.sec ();
+ wusecs *= ACE_static_cast (ACE_UINT32, ACE_ONE_SECOND_IN_USECS);
+ wusecs += wtv.usec ();
+
+ ACE_Time_Value rtv;
+ reading.elapsed_time_incr (rtv);
+ ACE_hrtime_t rusecs = rtv.sec ();
+ rusecs *= ACE_static_cast (ACE_UINT32, ACE_ONE_SECOND_IN_USECS);
+ rusecs += rtv.usec ();
+
+ double write_average = wusecs / m;
+ double read_average = rusecs / m;
+ ACE_DEBUG ((LM_DEBUG,
+ "%s: %d %.3f %.3f\n",
+ name, x, write_average, read_average));
+ }
+ return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+ TAO_TRY
+ {
+ CORBA::ORB_var orb = CORBA::ORB_init (argc,
+ argv,
+ 0,
+ TAO_TRY_ENV);
+ TAO_CHECK_ENV;
+
+ int n = 64;
+ int lo = 64;
+ int hi = 128000;
+ int s = 4;
+
+ ACE_Get_Opt get_opt (argc, argv, "n:l:h:s:");
+ int opt;
+
+ while ((opt = get_opt ()) != EOF)
+ {
+ switch (opt)
+ {
+ case 'n':
+ n = ACE_OS::atoi (get_opt.optarg);
+ break;
+ case 'l':
+ lo = ACE_OS::atoi (get_opt.optarg);
+ break;
+ case 'h':
+ hi = ACE_OS::atoi (get_opt.optarg);
+ break;
+ case 's':
+ s = ACE_OS::atoi (get_opt.optarg);
+ break;
+ case '?':
+ default:
+ ACE_DEBUG ((LM_DEBUG,
+ "Usage: %s "
+ "-l low "
+ "-h high "
+ "-s step "
+ "-n n "
+ "\n"
+ "Writes and then reads octet sequences to a CDR stream "
+ "starting from <low> up to <high> incrementing "
+ "by <step>, at each step run <n> iterations to "
+ "average."
+ "\n",
+ argv[0]));
+ return -1;
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "Running:\n"
+ " low: %d\n"
+ " hi : %d\n"
+ " s : %d\n"
+ " n : %d\n",
+ lo, hi, s, n));
+
+ // Create a "big" buffer and fill it up.
+ char* buf = new char[hi];
+ CORBA::Long l = 0xdeadbeef;
+ for (int i = 0; i < hi / sizeof (l); ++i)
+ {
+ ACE_OS::memcpy (buf + sizeof (l) * i, &l, sizeof (l));
+ }
+
+ if (run (buf, hi,
+ n, lo, s,
+ "OCTET", test_write_octet, test_read_octet,
+ TAO_TRY_ENV) != 0)
+ return 1;
+ TAO_CHECK_ENV;
+
+ if (run (buf, hi,
+ n, lo, s,
+ "CHAR", test_write_char, test_read_char,
+ TAO_TRY_ENV) != 0)
+ return 1;
+ TAO_CHECK_ENV;
+ delete[] buf;
+ }
+ TAO_CATCHANY
+ {
+ TAO_TRY_ENV.print_exception ("OctetSeq");
+ }
+ TAO_ENDTRY;
+
+ return 0;
+}
diff --git a/TAO/tests/OctetSeq/svc.conf b/TAO/tests/OctetSeq/svc.conf
new file mode 100644
index 00000000000..43c6a486c92
--- /dev/null
+++ b/TAO/tests/OctetSeq/svc.conf
@@ -0,0 +1,49 @@
+# $Id$
+#
+# This file contains a sample ACE_Service_Config configuration
+# file specifying the strategy factories utilized by an application
+# using TAO. There are currently only two possible factories:
+# Client_Strategy_Factory and Server_Strategy_Factory. These names
+# must be used as the second argument to their corresponding line,
+# because that's what the ORB uses to find the desired factory.
+#
+# Note that there are two unordinary characteristics of the way *this*
+# file is set up:
+# - both client and server strategies are specified in the same
+# file, which would only make sense for co-located clients & servers
+# - both of the factories are actually sourced out of libTAO.so
+# (TAO.DLL on Win32), and they would normally be in a separate
+# dll from the TAO ORB Core.
+#
+# The options which can be passed to the Resource Factory are:
+#
+# -ORBresources <which>
+# where <which> can be 'global' to specify globally-held resources,
+# or 'tss' to specify thread-specific resources.
+#
+# The options which can be passed to the Client are:
+# <none currently>
+#
+# The options which can be passed to the Server are:
+#
+# -ORBconcurrency <which>
+# where <which> can be 'thread-per-connection' to specify
+# use of the ACE_Threaded_Strategy concurrency strategy,
+# or 'reactive' to specify use of the ACE_Reactive_Strategy
+# concurrency strategy.
+#
+# -ORBthreadflags <flags>
+# specifies the default thread flags to use, where <flags> is a
+# logical OR'ing of the flags THR_DETACHED, THR_BOUND, THR_NEW_LWP,
+# THR_SUSPENDED, or THR_DAEMON. Note that not every flag may be valid
+# on every platform.
+#
+# -ORBdemuxstrategy <which>
+# where <which> can be one of 'dynamic', 'linear', 'active', or 'user',
+# and specifies the type of object lookup strategy used internally.
+# -ORBtablesize <unsigned>
+# specifies the size of the object table
+#
+dynamic Resource_Factory Service_Object * TAO:_make_TAO_Resource_Factory() "-ORBresources global"
+dynamic Client_Strategy_Factory Service_Object * TAO:_make_TAO_Default_Client_Strategy_Factory()
+dynamic Server_Strategy_Factory Service_Object * TAO:_make_TAO_Default_Server_Strategy_Factory() "-ORBconcurrency reactive -ORBdemuxstrategy dynamic -ORBtablesize 128"
diff --git a/TAO/tests/OctetSeq/test.idl b/TAO/tests/OctetSeq/test.idl
new file mode 100644
index 00000000000..1413d3e88f3
--- /dev/null
+++ b/TAO/tests/OctetSeq/test.idl
@@ -0,0 +1,24 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO/tests/OctetSeq
+//
+// = FILENAME
+// test.idl
+//
+// = DESCRIPTION
+// Simple IDL file to generate the TypeCodes for sequence<octet>,
+// sequence<char>.
+//
+// = AUTHORS
+// Carlos O'Ryan
+//
+// ============================================================================
+
+module Test
+{
+ typedef sequence<octet> OctetSeq;
+ typedef sequence<char> CharSeq;
+};