summaryrefslogtreecommitdiff
path: root/TAO/tao
diff options
context:
space:
mode:
authorcoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-08-14 20:12:03 +0000
committercoryan <coryan@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1998-08-14 20:12:03 +0000
commitda49b08671e5d87c9996bb0bcc63c661447f83b2 (patch)
tree4b92710abc7aef7d79efb811391b9254038b5480 /TAO/tao
parent66e74009620c1297b07ce26dab97f586ed76edc7 (diff)
downloadATCD-da49b08671e5d87c9996bb0bcc63c661447f83b2.tar.gz
ChangeLogTag:Fri Aug 14 14:44:49 1998 Carlos O'Ryan <coryan@cs.wustl.edu>
Diffstat (limited to 'TAO/tao')
-rw-r--r--TAO/tao/IIOP_Interpreter.cpp2
-rw-r--r--TAO/tao/Object.cpp16
-rw-r--r--TAO/tao/Object.h40
-rw-r--r--TAO/tao/Object.i8
-rw-r--r--TAO/tao/Sequence.cpp15
-rw-r--r--TAO/tao/Sequence.h17
-rw-r--r--TAO/tao/Sequence_T.cpp347
-rw-r--r--TAO/tao/Sequence_T.h128
-rw-r--r--TAO/tao/Sequence_T.i55
-rw-r--r--TAO/tao/corba.h1
-rw-r--r--TAO/tao/decode.cpp40
-rw-r--r--TAO/tao/deep_free.cpp9
-rw-r--r--TAO/tao/encode.cpp38
-rw-r--r--TAO/tao/orbconf.h4
-rw-r--r--TAO/tao/varout.cpp55
-rw-r--r--TAO/tao/varout.h96
-rw-r--r--TAO/tao/varout.i100
17 files changed, 916 insertions, 55 deletions
diff --git a/TAO/tao/IIOP_Interpreter.cpp b/TAO/tao/IIOP_Interpreter.cpp
index 674519ec16b..ff93db56664 100644
--- a/TAO/tao/IIOP_Interpreter.cpp
+++ b/TAO/tao/IIOP_Interpreter.cpp
@@ -168,7 +168,7 @@ declare_entry (CORBA::Any, tk_any);
declare_entry (CORBA::TypeCode_ptr, tk_TypeCode);
declare_entry (CORBA::Principal_ptr, tk_Principal);
-declare_entry (CORBA::Object_ptr, tk_objref);
+declare_entry (TAO_Object_Field_T<CORBA_Object>, tk_objref);
declare_entry (CORBA::String, tk_string);
#if !defined (TAO_NO_COPY_OCTET_SEQUENCES)
diff --git a/TAO/tao/Object.cpp b/TAO/tao/Object.cpp
index 7f3fc766d9e..8f6904e327d 100644
--- a/TAO/tao/Object.cpp
+++ b/TAO/tao/Object.cpp
@@ -257,3 +257,19 @@ CORBA::Object::_use_locate_requests (CORBA::Boolean use_it)
iiopobj->use_locate_requests (use_it);
}
+
+// ****************************************************************
+
+TAO_Object_Field::~TAO_Object_Field (void)
+{
+}
+
+#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
+
+template class TAO_Object_Field_T<CORBA_Object>;
+
+#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
+
+#pragma instantiate TAO_Object_Field_T<CORBA_Object>
+
+#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */
diff --git a/TAO/tao/Object.h b/TAO/tao/Object.h
index 58ae31182f0..0850f510974 100644
--- a/TAO/tao/Object.h
+++ b/TAO/tao/Object.h
@@ -28,15 +28,22 @@
class TAO_ServantBase;
class STUB_Object;
+class CORBA_Object;
+typedef CORBA_Object* CORBA_Object_ptr;
+
class TAO_Export CORBA_Object
{
public:
- static CORBA::Object_ptr _duplicate (CORBA::Object_ptr obj);
+ static CORBA_Object_ptr _duplicate (CORBA_Object_ptr obj);
// increment the ref count
- static CORBA::Object_ptr _nil (void);
+ static CORBA_Object_ptr _nil (void);
// return a NUL object
+ static CORBA_Object_ptr _narrow (CORBA_Object_ptr obj,
+ CORBA::Environment& env);
+ // no-op it is just here to simplify some templates.
+
// These calls correspond to over-the-wire operations, or at least
// do so in many common cases. The normal implementation assumes a
// particular simple, efficient, protocol-neutral interface for
@@ -197,6 +204,35 @@ private:
CORBA::Object_ptr &ptr_;
};
+class TAO_Object_Field
+{
+ // = TITLE
+ // Base class to represent fields (in structures) corresponding to
+ // object references.
+ //
+ // = DESCRIPTION
+ // When an object reference appears in a structure the marshaling
+ // and demarhsaling of the structure gets complicated:
+ // the interpreter can only marshal CORBA_Object_ptr when it
+ // dermarshal it creates on of those objects.
+ // The downcasting to the right type must be executed by classes
+ // with compile-time knowledge of the object type.
+ // The solution addopted in TAO is to create a special manager
+ // class for that field called TAO_Object_Field_T<T> (see
+ // varout.h), this class serves as an abstract interface to
+ // manipulate instances of those classes (by the interpreter, of
+ // course).
+ //
+public:
+ virtual ~TAO_Object_Field (void);
+ // destructor
+
+ virtual void _downcast (CORBA_Object* base_ptr,
+ CORBA_Environment& env) = 0;
+ virtual CORBA_Object* _upcast (void) = 0;
+ virtual void _release (void) = 0;
+};
+
#if defined (__ACE_INLINE__)
# include "tao/Object.i"
#endif /* __ACE_INLINE__ */
diff --git a/TAO/tao/Object.i b/TAO/tao/Object.i
index 98ece395a43..aa84c3361c2 100644
--- a/TAO/tao/Object.i
+++ b/TAO/tao/Object.i
@@ -24,7 +24,7 @@ CORBA_Object::_decr_refcnt (void)
}
ACE_INLINE CORBA_Object_ptr
-CORBA_Object::_duplicate (CORBA::Object_ptr obj)
+CORBA_Object::_duplicate (CORBA_Object_ptr obj)
{
if (obj)
obj->_incr_refcnt ();
@@ -39,6 +39,12 @@ CORBA_Object::_nil (void)
return 0;
}
+ACE_INLINE CORBA_Object_ptr
+CORBA_Object::_narrow (CORBA_Object_ptr obj, CORBA::Environment&)
+{
+ return obj;
+}
+
ACE_INLINE CORBA::Boolean
CORBA::is_nil (CORBA::Object_ptr obj)
{
diff --git a/TAO/tao/Sequence.cpp b/TAO/tao/Sequence.cpp
index 7538f768bd7..aa5faa52340 100644
--- a/TAO/tao/Sequence.cpp
+++ b/TAO/tao/Sequence.cpp
@@ -21,6 +21,21 @@ void TAO_Base_Sequence::_shrink_buffer (CORBA::ULong, CORBA::ULong)
// default is no op.
}
+void
+TAO_Base_Sequence::_downcast (void*,
+ CORBA_Object*,
+ CORBA_Environment &)
+{
+ // default is no op.
+ // @@ TODO Maybe throw an exception?
+}
+
+CORBA_Object*
+TAO_Base_Sequence::_upcast (void*) const
+{
+ return 0;
+}
+
// *************************************************************
// Operations for class TAO_Unbounded_Base_Sequence
// *************************************************************
diff --git a/TAO/tao/Sequence.h b/TAO/tao/Sequence.h
index 816845bc653..a765cdd4660 100644
--- a/TAO/tao/Sequence.h
+++ b/TAO/tao/Sequence.h
@@ -18,6 +18,9 @@
#if !defined (TAO_SEQUENCE_H)
# define TAO_SEQUENCE_H
+class CORBA_Object;
+class CORBA_Environment;
+
class TAO_Export TAO_Base_Sequence
{
// = TITLE
@@ -55,6 +58,16 @@ public:
// release the objects only from position <0> to <length-1>; so
// shrink and then delete could result in a memory leak.
+ virtual void _downcast (void* target,
+ CORBA_Object* src,
+ CORBA_Environment &env);
+ // Used for sequences of objects to downcast a recently demarshalled
+ // object reference into the right type.
+
+ virtual CORBA_Object* _upcast (void* src) const;
+ // Used for sequences of object to convert from the derived type
+ // into the Object class.
+
protected:
TAO_Base_Sequence (void);
// Default constructor.
@@ -461,6 +474,10 @@ private:
// ****************************************************************
+
+
+// ****************************************************************
+
#if defined (__ACE_INLINE__)
#include "tao/Sequence.i"
#endif /* __ACE_INLINE__ */
diff --git a/TAO/tao/Sequence_T.cpp b/TAO/tao/Sequence_T.cpp
index af795395a12..34ca0ad9d28 100644
--- a/TAO/tao/Sequence_T.cpp
+++ b/TAO/tao/Sequence_T.cpp
@@ -125,19 +125,8 @@ operator= (const TAO_Bounded_Sequence<T, MAX> &rhs)
if (this->release_)
{
-#if 0
// We never need to reallocate the buffer because they are
// always of size MAX.
- if (this->maximum_ < rhs.maximum_)
- {
- // free the old buffer
- T *tmp = ACE_reinterpret_cast (T *,
- this->buffer_);
- TAO_Bounded_Sequence<T>::freebuf (tmp);
- this->buffer_ =
- TAO_Bounded_Sequence<T>::allocbuf (rhs.maximum_);
- }
-#endif /* 0 */
}
else
this->buffer_ =
@@ -372,7 +361,7 @@ template<class T> void
TAO_Unbounded_Object_Sequence<T>::_shrink_buffer (CORBA::ULong nl,
CORBA::ULong ol)
{
- T **tmp = ACE_reinterpret_cast (T**, this->buffer_);
+ T **tmp = ACE_static_cast (T**, this->buffer_);
for (CORBA::ULong i = nl; i < ol; ++i)
{
@@ -381,6 +370,24 @@ TAO_Unbounded_Object_Sequence<T>::_shrink_buffer (CORBA::ULong nl,
}
}
+template <class T> void
+TAO_Unbounded_Object_Sequence<T>::_downcast (void* target,
+ CORBA_Object* src,
+ CORBA_Environment &env)
+{
+ T **tmp = ACE_static_cast (T**, target);
+
+ *tmp = T::_narrow (src, env);
+}
+
+template <class T> CORBA_Object*
+TAO_Unbounded_Object_Sequence<T>::_upcast (void* src) const
+{
+ T **tmp = ACE_static_cast (T**, src);
+
+ return *tmp;
+}
+
// *************************************************************
// Operations for class TAO_Bounded_Object_Sequence
// *************************************************************
@@ -425,14 +432,6 @@ TAO_Bounded_Object_Sequence<T, MAX>::operator=
}
// No need to reallocate the buffer since it is always of size
// MAX
-#if 0
- if (this->maximum_ < rhs.maximum_)
- {
- TAO_Bounded_Object_Sequence<T, MAX>::freebuf (tmp);
- this->buffer_ =
- TAO_Bounded_Object_Sequence<T, MAX>::allocbuf (rhs.maximum_);
- }
-#endif /* 0 */
}
else
this->buffer_ =
@@ -508,6 +507,304 @@ TAO_Bounded_Object_Sequence<T, MAX>::_shrink_buffer (CORBA::ULong nl,
}
}
+template <class T, CORBA::ULong MAX> void
+TAO_Bounded_Object_Sequence<T, MAX>::_downcast (void* target,
+ CORBA_Object* src,
+ CORBA_Environment &env)
+{
+ T **tmp = ACE_static_cast (T**, target);
+
+ *tmp = T::_narrow (src, env);
+}
+
+template <class T, CORBA::ULong MAX> CORBA_Object*
+TAO_Bounded_Object_Sequence<T, MAX>::_upcast (void* src) const
+{
+ T **tmp = ACE_static_cast (T**, src);
+
+ return *tmp;
+}
+
+// *************************************************************
+// Operations for class TAO_Unbounded_Pseudo_Sequence
+// *************************************************************
+
+// constructor for unbounded seq
+template <class T>
+TAO_Unbounded_Pseudo_Sequence<T>::
+TAO_Unbounded_Pseudo_Sequence (CORBA::ULong maximum)
+ : TAO_Unbounded_Base_Sequence (maximum,
+ TAO_Unbounded_Pseudo_Sequence<T>::allocbuf (maximum))
+{
+}
+
+template <class T>
+TAO_Unbounded_Pseudo_Sequence<T>::
+TAO_Unbounded_Pseudo_Sequence (const TAO_Unbounded_Pseudo_Sequence<T> &rhs)
+ : TAO_Unbounded_Base_Sequence (rhs)
+{
+ T **tmp1 = TAO_Unbounded_Pseudo_Sequence<T>::allocbuf (this->maximum_);
+ T ** const tmp2 = ACE_reinterpret_cast (T ** ACE_CAST_CONST, rhs.buffer_);
+
+ for (CORBA::ULong i = 0; i < rhs.length_; ++i)
+ tmp1[i] = T::_duplicate (tmp2[i]);
+
+ this->buffer_ = tmp1;
+}
+
+template<class T>
+TAO_Unbounded_Pseudo_Sequence<T>::~TAO_Unbounded_Pseudo_Sequence (void)
+{
+ this->_deallocate_buffer ();
+}
+
+// assignment operator
+template <class T>
+TAO_Unbounded_Pseudo_Sequence<T>&
+TAO_Unbounded_Pseudo_Sequence<T>::
+operator= (const TAO_Unbounded_Pseudo_Sequence<T> &rhs)
+{
+ if (this == &rhs)
+ return *this;
+
+ if (this->release_)
+ {
+ T **tmp = ACE_reinterpret_cast (T **,
+ this->buffer_);
+
+ for (CORBA::ULong i = 0; i < this->length_; ++i)
+ {
+ CORBA::release (tmp[i]);
+ tmp[i] = T::_nil ();
+ }
+ if (this->maximum_ < rhs.maximum_)
+ {
+ TAO_Unbounded_Pseudo_Sequence<T>::freebuf (tmp);
+ this->buffer_ =
+ TAO_Unbounded_Pseudo_Sequence<T>::allocbuf (rhs.maximum_);
+ }
+ }
+ else
+ this->buffer_ =
+ TAO_Unbounded_Pseudo_Sequence<T>::allocbuf (rhs.maximum_);
+
+ TAO_Unbounded_Base_Sequence::operator= (rhs);
+
+ T **tmp1 = ACE_reinterpret_cast (T **, this->buffer_);
+ T ** const tmp2 = ACE_reinterpret_cast (T ** ACE_CAST_CONST, rhs.buffer_);
+
+ for (CORBA::ULong i = 0; i < rhs.length_; ++i)
+ tmp1[i] = T::_duplicate (tmp2[i]);
+
+ return *this;
+}
+
+template <class T> T **
+TAO_Unbounded_Pseudo_Sequence<T>::allocbuf (CORBA::ULong nelems)
+{
+ T **buf;
+
+ ACE_NEW_RETURN (buf, T*[nelems], 0);
+
+ for (CORBA::ULong i = 0; i < nelems; i++)
+ buf[i] = T::_nil ();
+
+ return buf;
+}
+
+template <class T> void
+TAO_Unbounded_Pseudo_Sequence<T>::freebuf (T **buffer)
+{
+ if (buffer == 0)
+ return;
+
+ // {orbos/97-05-15:16.11} The freebuf function ensures that the
+ // destructor for each element is called before the buffer is
+ // destroyed, except for string elements, which are freed using
+ // string_free(), and object reference elements, which are freed
+ // using release(). The freebuf function will ignore null pointers
+ // passed to it.
+
+ // @@ How are we supposed to implement that! We don't know the
+ // length of the buffer here.
+ // Mark the length in the first four bytes? For the moment we let
+ // that be.
+
+ delete[] buffer;
+}
+
+template<class T>
+void TAO_Unbounded_Pseudo_Sequence<T>::_allocate_buffer (CORBA::ULong length)
+{
+ T **tmp = TAO_Unbounded_Pseudo_Sequence<T>::allocbuf (length);
+
+ if (this->buffer_ != 0)
+ {
+ T **old = ACE_reinterpret_cast (T**, this->buffer_);
+ for (CORBA::ULong i = 0; i < this->length_; ++i)
+ // Only call duplicate when we did not own the previous
+ // buffer, since after this method we own it we must also own
+ // the objects. If we already own the objects there is no
+ // need to copy them, if we did we would also have to remove
+ // the old instances.
+ if (!this->release_)
+ tmp[i] = T::_duplicate (old[i]);
+ else
+ tmp[i] = old[i];
+
+ if (this->release_)
+ delete[] old;
+ }
+ this->buffer_ = tmp;
+}
+
+template<class T>
+void TAO_Unbounded_Pseudo_Sequence<T>::_deallocate_buffer (void)
+{
+ if (this->buffer_ == 0 || this->release_ == 0)
+ return;
+ T **tmp = ACE_reinterpret_cast (T**, this->buffer_);
+ for (CORBA::ULong i = 0; i < this->length_; ++i)
+ {
+ CORBA::release (tmp[i]);
+ tmp[i] = T::_nil ();
+ }
+ TAO_Unbounded_Pseudo_Sequence<T>::freebuf (tmp);
+ this->buffer_ = 0;
+}
+
+template<class T> void
+TAO_Unbounded_Pseudo_Sequence<T>::_shrink_buffer (CORBA::ULong nl,
+ CORBA::ULong ol)
+{
+ T **tmp = ACE_static_cast (T**, this->buffer_);
+
+ for (CORBA::ULong i = nl; i < ol; ++i)
+ {
+ CORBA::release (tmp[i]);
+ tmp[i] = T::_nil ();
+ }
+}
+
+// *************************************************************
+// Operations for class TAO_Bounded_Pseudo_Sequence
+// *************************************************************
+
+template <class T, CORBA::ULong MAX>
+TAO_Bounded_Pseudo_Sequence<T, MAX>::
+TAO_Bounded_Pseudo_Sequence (void)
+ : TAO_Bounded_Base_Sequence (MAX,
+ TAO_Bounded_Pseudo_Sequence<T, MAX>::allocbuf (MAX))
+{
+}
+
+template <class T, CORBA::ULong MAX>
+TAO_Bounded_Pseudo_Sequence<T, MAX>::
+TAO_Bounded_Pseudo_Sequence (const TAO_Bounded_Pseudo_Sequence<T, MAX> &rhs)
+ : TAO_Bounded_Base_Sequence (rhs)
+{
+ T **tmp1 =
+ TAO_Bounded_Pseudo_Sequence<T, MAX>::allocbuf (MAX);
+ T ** const tmp2 = ACE_reinterpret_cast (T** ACE_CAST_CONST, rhs.buffer_);
+ for (CORBA::ULong i = 0; i < rhs.length_; i++)
+ tmp1[i] = T::_duplicate (tmp2[i]);
+ this->buffer_ = tmp1;
+}
+
+template <class T, CORBA::ULong MAX>
+TAO_Bounded_Pseudo_Sequence<T, MAX>&
+TAO_Bounded_Pseudo_Sequence<T, MAX>::operator=
+(const TAO_Bounded_Pseudo_Sequence<T, MAX> &rhs)
+{
+ if (this == &rhs)
+ return *this;
+
+ if (this->release_)
+ {
+ T **tmp = ACE_reinterpret_cast (T **, this->buffer_);
+
+ for (CORBA::ULong i = 0; i < this->length_; ++i)
+ {
+ CORBA::release (tmp[i]);
+ tmp[i] = T::_nil ();
+ }
+ // No need to reallocate the buffer since it is always of size
+ // MAX
+ }
+ else
+ this->buffer_ =
+ TAO_Bounded_Pseudo_Sequence<T, MAX>::allocbuf (rhs.maximum_);
+
+ TAO_Bounded_Base_Sequence::operator= (rhs);
+
+ T **tmp1 = ACE_reinterpret_cast (T **, this->buffer_);
+ T ** const tmp2 = ACE_reinterpret_cast (T ** ACE_CAST_CONST, rhs.buffer_);
+ for (CORBA::ULong i=0; i < rhs.length_; ++i)
+ tmp1[i] = T::_duplicate (tmp2[i]);
+ return *this;
+}
+
+template <class T, CORBA::ULong MAX> T **
+TAO_Bounded_Pseudo_Sequence<T, MAX>::allocbuf (CORBA::ULong)
+{
+ T **buf;
+
+ ACE_NEW_RETURN (buf, T*[MAX], 0);
+
+ for (CORBA::ULong i = 0; i < MAX; i++)
+ buf[i] = T::_nil ();
+
+ return buf;
+}
+
+template <class T, CORBA::ULong MAX> void
+TAO_Bounded_Pseudo_Sequence<T, MAX>::freebuf (T **buffer)
+{
+ // How much do we deallocate? Easy! allocbuf() always creates MAX
+ // elements and initialize them to T::_nil(). So we can be
+ // complaint and call CORBA::release() on each one.
+ for (CORBA::ULong i = 0; i < MAX; ++i)
+ if (buffer[i] != T::_nil ())
+ {
+ CORBA::release (buffer[i]);
+ buffer[i] = T::_nil ();
+ }
+
+ delete[] buffer;
+}
+
+template<class T, CORBA::ULong MAX> void
+TAO_Bounded_Pseudo_Sequence<T, MAX>::_allocate_buffer (CORBA::ULong length)
+{
+ // For this class memory is never reallocated so the implementation
+ // is *really* simple.
+ this->buffer_ =
+ TAO_Bounded_Pseudo_Sequence<T, MAX>::allocbuf (length);
+}
+
+template<class T, CORBA::ULong MAX>
+void TAO_Bounded_Pseudo_Sequence<T, MAX>::_deallocate_buffer (void)
+{
+ if (this->buffer_ == 0 || this->release_ == 0)
+ return;
+ T **tmp = ACE_reinterpret_cast (T **, this->buffer_);
+ TAO_Bounded_Pseudo_Sequence<T, MAX>::freebuf (tmp);
+ this->buffer_ = 0;
+}
+
+template<class T, CORBA::ULong MAX> void
+TAO_Bounded_Pseudo_Sequence<T, MAX>::_shrink_buffer (CORBA::ULong nl,
+ CORBA::ULong ol)
+{
+ T **tmp = ACE_reinterpret_cast (T **, this->buffer_);
+
+ for (CORBA::ULong i = nl; i < ol; ++i)
+ {
+ CORBA::release (tmp[i]);
+ tmp[i] = T::_nil ();
+ }
+}
+
// *************************************************************
// Operations for class TAO_Bounded_String_Sequence
// *************************************************************
@@ -553,14 +850,8 @@ TAO_Bounded_String_Sequence<MAX>::operator=
CORBA::string_free (tmp[i]);
tmp[i] = 0;
}
-#if 0
- if (this->maximum_ < rhs.maximum_)
- {
- TAO_Bounded_String_Sequence<T, MAX>::freebuf (tmp);
- this->buffer_ =
- TAO_Unbounded_String_Sequence<T, MAX>::allocbuf (rhs.maximum_);
- }
-#endif /* 0 */
+ // No need to reallocate because the buffer is supposed to be of
+ // <MAX> size.
}
else
this->buffer_ =
diff --git a/TAO/tao/Sequence_T.h b/TAO/tao/Sequence_T.h
index 9a5601ae42b..d1863ca1e13 100644
--- a/TAO/tao/Sequence_T.h
+++ b/TAO/tao/Sequence_T.h
@@ -310,10 +310,10 @@ class TAO_Unbounded_Object_Sequence : public TAO_Unbounded_Base_Sequence
// pseudo objects, object references and strings.
// = SPEC
- // 16.8 Mapping for Structured Types
- // The mapping for struct, union, and sequence (but not array) is a
- // C++ struct or class with a default constructor, a copy
- // constructor, an assignment operator, and a destructor.
+ // 16.8 Mapping for Structured Types
+ // The mapping for struct, union, and sequence (but not array) is a
+ // C++ struct or class with a default constructor, a copy
+ // constructor, an assignment operator, and a destructor.
//
public:
// = Initialization and termination methods.
@@ -412,6 +412,10 @@ public:
virtual void _deallocate_buffer (void);
virtual void _shrink_buffer (CORBA::ULong new_length,
CORBA::ULong old_length);
+ virtual void _downcast (void* target,
+ CORBA_Object* src,
+ CORBA_Environment &env);
+ virtual CORBA_Object* _upcast (void* src) const;
};
// *************************************************************
@@ -423,9 +427,8 @@ class TAO_Bounded_Object_Sequence : public TAO_Bounded_Base_Sequence
// Parametric sequence for types that require managers.
//
// = DESCRIPTION
- // Some IDL types require that sequences on them have a "manager"
- // class, in charge of handling the object lifetime, examples are
- // pseudo objects, object references and strings.
+ // Please see the documentation for the unbounded case.
+ //
public:
// = Initialization and termination methods.
@@ -465,6 +468,117 @@ public:
virtual void _deallocate_buffer (void);
virtual void _shrink_buffer (CORBA::ULong new_length,
CORBA::ULong old_length);
+ virtual void _downcast (void* target,
+ CORBA_Object* src,
+ CORBA_Environment &env);
+ virtual CORBA_Object* _upcast (void* src) const;
+};
+
+// *************************************************************
+
+template<class T>
+class TAO_Unbounded_Pseudo_Sequence : public TAO_Unbounded_Base_Sequence
+{
+ // = TITLE
+ // Parametric sequence for pseudo objects.
+ //
+ // = DESCRIPTION
+ // Some IDL types (including pseudo objects) require that
+ // sequences on them have a "manager" class, in charge of handling
+ // the object lifetime.
+ // This parametric class implements those sequences. In general
+ // the sequence is similar to Object_Sequente, except for some
+ // TAO internal details. The complete documentation of each method
+ // is provided in TAO_Unbounded_Object_Sequece
+public:
+ // = Initialization and termination methods.
+
+ TAO_Unbounded_Pseudo_Sequence (void);
+ // default ctor
+
+ TAO_Unbounded_Pseudo_Sequence (CORBA::ULong max);
+ // Constructor with a "hint" for the maximum capacity.
+
+ TAO_Unbounded_Pseudo_Sequence (CORBA::ULong maximum,
+ CORBA::ULong length,
+ T* *data,
+ CORBA::Boolean release=0);
+ // Constructor with a given buffer.
+
+ TAO_Unbounded_Pseudo_Sequence(const TAO_Unbounded_Pseudo_Sequence<T> &);
+ // Copy ctor, deep copies.
+
+ ~TAO_Unbounded_Pseudo_Sequence (void);
+ // dtor releases all the contained elements.
+
+ TAO_Unbounded_Pseudo_Sequence<T> &operator= (const TAO_Unbounded_Pseudo_Sequence <T> &);
+ // The assignment operator first releases all object reference
+ // members and frees all string members, and then performs a
+ // deepcopy to create a new structure.
+
+ TAO_Object_Manager<T> operator[] (CORBA::ULong index) const;
+ // read-write accessor
+
+ static T **allocbuf (CORBA::ULong);
+ // The allocbuf function allocates a vector of T elements that can
+ // be passed to the T *data constructor.
+
+ static void freebuf (T **);
+ // Release all the elements.
+
+ // The Base_Sequence functions, please see "tao/Sequence.h"
+ virtual void _allocate_buffer (CORBA::ULong length);
+ virtual void _deallocate_buffer (void);
+ virtual void _shrink_buffer (CORBA::ULong new_length,
+ CORBA::ULong old_length);
+};
+
+// *************************************************************
+
+template<class T, CORBA::ULong MAX>
+class TAO_Bounded_Pseudo_Sequence : public TAO_Bounded_Base_Sequence
+{
+ // = TITLE
+ // Bounded version of TAO_Unbounded_Psuedo_Sequence.
+ //
+ // = DESCRIPTION
+ // Please see the documentation for the unbounded case.
+ //
+public:
+ // = Initialization and termination methods.
+
+ TAO_Bounded_Pseudo_Sequence (void);
+ // default ctor.
+
+ TAO_Bounded_Pseudo_Sequence (CORBA::ULong length,
+ T* *value,
+ CORBA::Boolean release=0);
+ // Constructor from data.
+
+ TAO_Bounded_Pseudo_Sequence (const TAO_Bounded_Pseudo_Sequence<T,MAX> &);
+ // Copy constructor.
+
+ ~TAO_Bounded_Pseudo_Sequence (void);
+ // destructor
+
+ TAO_Bounded_Pseudo_Sequence &operator= (const TAO_Bounded_Pseudo_Sequence<T,MAX> &);
+ // Assignment from another Bounded sequence.
+
+ TAO_Object_Manager<T> operator[] (CORBA::ULong index) const;
+ // Read-write accessor.
+
+ static T **allocbuf (CORBA::ULong length);
+ // Allocate storage for a sequence..
+
+ static void freebuf (T **buffer);
+ // Free a buffer allocated by allocbuf() and release each element on
+ // it.
+
+ // The Base_Sequence functions, please see "tao/sequence.h"
+ virtual void _allocate_buffer (CORBA::ULong length);
+ virtual void _deallocate_buffer (void);
+ virtual void _shrink_buffer (CORBA::ULong new_length,
+ CORBA::ULong old_length);
};
// *************************************************************
diff --git a/TAO/tao/Sequence_T.i b/TAO/tao/Sequence_T.i
index eaca5865c42..8ab52ad0560 100644
--- a/TAO/tao/Sequence_T.i
+++ b/TAO/tao/Sequence_T.i
@@ -313,6 +313,61 @@ TAO_Bounded_Object_Sequence<T, MAX>::operator[] (CORBA::ULong index) const
}
// *************************************************************
+// class TAO_Unbounded_Pseudo_Sequence
+// *************************************************************
+
+//default constructor
+template <class T> ACE_INLINE
+TAO_Unbounded_Pseudo_Sequence<T>::TAO_Unbounded_Pseudo_Sequence (void)
+{
+}
+
+template <class T> ACE_INLINE
+TAO_Unbounded_Pseudo_Sequence<T>::
+TAO_Unbounded_Pseudo_Sequence (CORBA::ULong maximum,
+ CORBA::ULong length,
+ T* *value,
+ CORBA::Boolean release)
+ : TAO_Unbounded_Base_Sequence (maximum, length, value, release)
+{
+}
+
+template <class T> ACE_INLINE TAO_Object_Manager<T>
+TAO_Unbounded_Pseudo_Sequence<T>::operator[] (CORBA::ULong index) const
+{
+ ACE_ASSERT (index < this->maximum_);
+ T ** const tmp = ACE_reinterpret_cast (T ** ACE_CAST_CONST, this->buffer_);
+ return TAO_Object_Manager<T> (tmp + index, this->release_);
+}
+
+// *************************************************************
+// class TAO_Bounded_Pseudo_Sequence
+// *************************************************************
+
+template<class T, CORBA::ULong MAX> ACE_INLINE
+TAO_Bounded_Pseudo_Sequence<T,MAX>::~TAO_Bounded_Pseudo_Sequence (void)
+{
+ this->_deallocate_buffer ();
+}
+
+template <class T, CORBA::ULong MAX> ACE_INLINE
+TAO_Bounded_Pseudo_Sequence<T,MAX>::
+TAO_Bounded_Pseudo_Sequence (CORBA::ULong length,
+ T **value,
+ CORBA::Boolean release)
+ : TAO_Bounded_Base_Sequence (MAX, length, value, release)
+{
+}
+
+template <class T, CORBA::ULong MAX> ACE_INLINE TAO_Object_Manager<T>
+TAO_Bounded_Pseudo_Sequence<T, MAX>::operator[] (CORBA::ULong index) const
+{
+ ACE_ASSERT (index < this->maximum_);
+ T **const tmp = ACE_reinterpret_cast (T ** ACE_CAST_CONST, this->buffer_);
+ return TAO_Object_Manager<T> (tmp + index, this->release_);
+}
+
+// *************************************************************
// class TAO_Bounded_String_Sequence
// *************************************************************
diff --git a/TAO/tao/corba.h b/TAO/tao/corba.h
index 5ee93974f74..665110dfd2b 100644
--- a/TAO/tao/corba.h
+++ b/TAO/tao/corba.h
@@ -175,6 +175,7 @@ operator>>(TAO_InputCDR&, TAO_opaque&);
#include "tao/Request.h"
#include "tao/Stub.h"
#include "tao/Object.h"
+#include "tao/varout.h"
#include "tao/Typecode.h"
// Marshaling
diff --git a/TAO/tao/decode.cpp b/TAO/tao/decode.cpp
index 13c0ffc1731..86664cb6bd9 100644
--- a/TAO/tao/decode.cpp
+++ b/TAO/tao/decode.cpp
@@ -799,7 +799,6 @@ TAO_Marshal_Struct::decode (CORBA::TypeCode_ptr tc,
stream->read_wchar (*(CORBA::WChar *) data);
break;
case CORBA::tk_TypeCode:
- case CORBA::tk_objref:
case CORBA::tk_any:
case CORBA::tk_Principal:
case CORBA::tk_struct:
@@ -812,6 +811,17 @@ TAO_Marshal_Struct::decode (CORBA::TypeCode_ptr tc,
case CORBA::tk_wstring:
retval = stream->decode (param, data, 0, env);
break;
+
+ case CORBA::tk_objref:
+ {
+ CORBA_Object_ptr object;
+ retval = stream->decode (param, &object, 0, env);
+ TAO_Object_Field* field =
+ ACE_static_cast(TAO_Object_Field*, data);
+ field->_downcast (object, env);
+ }
+ break;
+
default:
break;
}
@@ -1237,7 +1247,6 @@ TAO_Marshal_Sequence::decode (CORBA::TypeCode_ptr tc,
break;
// handle all aggregate types here
- case CORBA::tk_objref:
case CORBA::tk_string:
case CORBA::tk_wstring:
case CORBA::tk_any:
@@ -1260,6 +1269,26 @@ TAO_Marshal_Sequence::decode (CORBA::TypeCode_ptr tc,
if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE)
return CORBA::TypeCode::TRAVERSE_CONTINUE;
break;
+
+ case CORBA::tk_objref:
+ {
+ size = sizeof (CORBA_Object_ptr);
+ while (bounds-- &&
+ retval == CORBA::TypeCode::TRAVERSE_CONTINUE)
+ {
+ CORBA_Object_ptr ptr;
+ retval = stream->decode (tc2, &ptr, 0, env);
+ if (env.exception () != 0) break;
+ seq->_downcast (value, ptr, env);
+ if (env.exception () != 0) break;
+ CORBA::release (ptr);
+ value += size;
+ }
+ if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE)
+ return retval;
+ }
+ break;
+
default:
break;
} // end of switch
@@ -1269,9 +1298,10 @@ TAO_Marshal_Sequence::decode (CORBA::TypeCode_ptr tc,
else
return CORBA::TypeCode::TRAVERSE_CONTINUE;
}
- // error exit
- env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_NO));
- dmsg ("marshaling TAO_Marshal_Sequence::decode detected error");
+ // If an error was detected but no exception was raised then raise a
+ // marshal exception.
+ if (env.exception () == 0)
+ env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_NO));
return CORBA::TypeCode::TRAVERSE_STOP;
}
diff --git a/TAO/tao/deep_free.cpp b/TAO/tao/deep_free.cpp
index 3e73054bc22..140be7b3dbd 100644
--- a/TAO/tao/deep_free.cpp
+++ b/TAO/tao/deep_free.cpp
@@ -216,9 +216,16 @@ TAO_Marshal_Struct::deep_free (CORBA::TypeCode_ptr tc,
case CORBA::tk_Principal:
retval = TAO_Marshal_Principal::deep_free (param, source, dest, env);
break;
+
case CORBA::tk_objref:
- retval = TAO_Marshal_ObjRef::deep_free (param, source, dest, env);
+ {
+ TAO_Object_Field* field =
+ ACE_static_cast (TAO_Object_Field*,source);
+ field->_release ();
+ retval = CORBA::TypeCode::TRAVERSE_CONTINUE;
+ }
break;
+
case CORBA::tk_struct:
retval = TAO_Marshal_Struct::deep_free (param, source, dest, env);
break;
diff --git a/TAO/tao/encode.cpp b/TAO/tao/encode.cpp
index 53fa33609e9..00b63cca8c7 100644
--- a/TAO/tao/encode.cpp
+++ b/TAO/tao/encode.cpp
@@ -440,9 +440,19 @@ TAO_Marshal_Struct::encode (CORBA::TypeCode_ptr tc,
case CORBA::tk_string:
case CORBA::tk_wstring:
case CORBA::tk_TypeCode:
- case CORBA::tk_objref:
retval = stream->encode (param, data, 0, env);
break;
+
+ case CORBA::tk_objref:
+ {
+ TAO_Object_Field* field =
+ ACE_static_cast(TAO_Object_Field*, data);
+ CORBA_Object_ptr ptr =
+ field->_upcast ();
+ retval = stream->encode (param, &ptr, 0, env);
+ }
+ break;
+
default:
break;
}
@@ -865,7 +875,6 @@ TAO_Marshal_Sequence::encode (CORBA::TypeCode_ptr tc,
case CORBA::tk_any:
case CORBA::tk_TypeCode:
case CORBA::tk_Principal:
- case CORBA::tk_objref:
case CORBA::tk_struct:
case CORBA::tk_union:
case CORBA::tk_string:
@@ -885,6 +894,24 @@ TAO_Marshal_Sequence::encode (CORBA::TypeCode_ptr tc,
if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE)
return CORBA::TypeCode::TRAVERSE_CONTINUE;
break;
+
+ case CORBA::tk_objref:
+ {
+ size = sizeof (CORBA_Object_ptr);
+ while (bounds-- &&
+ retval == CORBA::TypeCode::TRAVERSE_CONTINUE)
+ {
+ CORBA_Object_ptr ptr =
+ seq->_upcast (value);
+ retval = stream->encode (tc2, &ptr, 0, env);
+ if (env.exception () != 0) break;
+ value += size;
+ }
+ if (retval == CORBA::TypeCode::TRAVERSE_CONTINUE)
+ return retval;
+ }
+ break;
+
default:
break;
} // end of switch
@@ -902,9 +929,10 @@ TAO_Marshal_Sequence::encode (CORBA::TypeCode_ptr tc,
return CORBA::TypeCode::TRAVERSE_CONTINUE;
}
- // error exit
- env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_NO));
- dmsg ("marshaling TAO_Marshal_Sequence::encode detected error");
+ // If an error was detected but no exception was raised then raise a
+ // marshal exception.
+ if (env.exception () == 0)
+ env.exception (new CORBA::MARSHAL (CORBA::COMPLETED_NO));
return CORBA::TypeCode::TRAVERSE_STOP;
}
diff --git a/TAO/tao/orbconf.h b/TAO/tao/orbconf.h
index 130e754bc24..8685f827c03 100644
--- a/TAO/tao/orbconf.h
+++ b/TAO/tao/orbconf.h
@@ -225,10 +225,6 @@
#undef major
#endif /* major*/
-// TAO has problems encoding/decoding object references inside
-// structs.
-#define TAO_HAS_OBJECT_IN_STRUCT_MARSHAL_BUG
-
// For Win16, near/far pointers reflect same/other segment addressing.
// Of course, ACE doesn't support Win16, so why bother?
diff --git a/TAO/tao/varout.cpp b/TAO/tao/varout.cpp
new file mode 100644
index 00000000000..33340e2ec6b
--- /dev/null
+++ b/TAO/tao/varout.cpp
@@ -0,0 +1,55 @@
+/* -*- C++ -*- */
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// TAO
+//
+// = FILENAME
+// varout.cpp
+//
+// = DESCRIPTION
+// Templates for _var and _out types
+//
+// = AUTHOR
+//
+// Aniruddha Gokhale
+// Carlos O'Ryan
+// ============================================================================
+
+#if !defined (TAO_VAROUT_C)
+#define TAO_VAROUT_C
+
+#include "tao/varout.h"
+
+#if !defined (__ACE_INLINE__)
+#include "tao/varout.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID(tao, varout, "$Id$")
+
+template<class T> void
+TAO_Object_Field_T<T>::_downcast (CORBA_Object* base_ptr,
+ CORBA_Environment &env)
+{
+ CORBA::release (this->ptr_);
+ this->ptr_ = 0;
+ this->ptr_ = T::_narrow (base_ptr, env);
+ if (env.exception () != 0) return;
+}
+
+template<class T> CORBA_Object*
+TAO_Object_Field_T<T>::_upcast (void)
+{
+ return this->ptr_;
+}
+
+template<class T> void
+TAO_Object_Field_T<T>::_release (void)
+{
+ CORBA::release (this->ptr_);
+ this->ptr_ = 0;
+}
+
+#endif /* TAO_VAROUT_C */
diff --git a/TAO/tao/varout.h b/TAO/tao/varout.h
index 5c9d7e3c7f8..96ae1416ffc 100644
--- a/TAO/tao/varout.h
+++ b/TAO/tao/varout.h
@@ -1,7 +1,6 @@
/* -*- C++ -*- */
// $Id$
-
// ============================================================================
//
// = LIBRARY
@@ -21,6 +20,88 @@
#if !defined (TAO_VAROUT_H)
#define TAO_VAROUT_H
+class CORBA_Object;
+
+template <class T>
+class TAO_Object_Field_T : public TAO_Object_Field
+{
+ // = TITLE
+ // Parametric class to implement structure fields corresponding to
+ // object references.
+ //
+ // = DESCRIPTION
+ // When an object reference appears in a structure the marshaling
+ // and demarhsaling of the structure gets complicated:
+ // the interpreter can only marshal CORBA_Object_ptr when it
+ // dermarshal it creates on of those objects.
+ // The downcasting to the right type must be executed by classes
+ // with compile-time knowledge of the object type.
+ // The solution addopted in TAO is to create a special manager
+ // class for that field,
+public:
+ TAO_Object_Field_T (void);
+ // default constructor
+
+ TAO_Object_Field_T (T* object);
+ // constructor from a T*, assumes ownership of <object> i.e. it
+ // *will* release it.
+
+ TAO_Object_Field_T (const TAO_Object_Field_T<T> &);
+ // copy constructor
+
+ virtual ~TAO_Object_Field_T (void);
+ // destructor
+
+ TAO_Object_Field_T<T> &operator= (T* object);
+ // Assignment from a T*, it assumes ownership of <object>.
+
+ TAO_Object_Field_T<T> &operator= (const TAO_Object_Field_T<T> &);
+ // Assignment operator, in duplicates the underlying objects.
+
+ T* operator-> (void) const;
+ // smart pointer (const)
+
+ operator const T* &() const;
+ // cast operator
+
+ operator T* &();
+ // cast operator
+
+ // = operations for parameter passing modes
+
+ T* in (void) const;
+ // for in type parameter
+
+ T* &inout (void);
+ // for inout type parameter
+
+ T* &out (void);
+ // for out parameter
+
+ T* _retn (void);
+ // for return type
+
+ T* ptr (void) const;
+ // TAO extension for access to the underlying pointer.
+
+ virtual void _downcast (CORBA_Object* base_ptr,
+ CORBA_Environment& env);
+ virtual CORBA_Object* _upcast (void);
+ virtual void _release (void);
+ // Implement the TAO_Object_Field methods.
+
+private:
+ T* ptr_;
+};
+
+// ****************************************************************
+// The following classes are experimental, some of them do *not*
+// compile and produce errors in compilers that check templates before
+// instantiation time. In the future we may use them to implement
+// several classes generated by IDL compiler, possibly reducing the
+// complexity of the compiler.
+// ****************************************************************
+#if 0
template <class T>
class TAO_Fixed_var
// = TITLE
@@ -622,5 +703,18 @@ public:
private:
T_ptr &ptr_;
};
+#endif /* 0 */
+
+#if defined (__ACE_INLINE__)
+#include "tao/varout.i"
+#endif /* __ACE_INLINE__ */
+
+#if defined (ACE_TEMPLATES_REQUIRE_SOURCE)
+#include "tao/varout.cpp"
+#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */
+
+#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA)
+#pragma implementation ("varout.cpp")
+#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */
#endif /* TAO_VAROUT_H */
diff --git a/TAO/tao/varout.i b/TAO/tao/varout.i
new file mode 100644
index 00000000000..132628d1cf7
--- /dev/null
+++ b/TAO/tao/varout.i
@@ -0,0 +1,100 @@
+//
+// $Id$
+//
+
+template<class T> ACE_INLINE
+TAO_Object_Field_T<T>::TAO_Object_Field_T (void)
+ : ptr_ (0)
+{
+}
+
+template<class T> ACE_INLINE
+TAO_Object_Field_T<T>::TAO_Object_Field_T (T* object)
+ : ptr_ (object)
+{
+}
+
+template<class T> ACE_INLINE
+TAO_Object_Field_T<T>::TAO_Object_Field_T (const TAO_Object_Field_T<T>& rhs)
+ : ptr_ (T::_duplicate (rhs.ptr_))
+{
+}
+
+template<class T> ACE_INLINE
+TAO_Object_Field_T<T>::~TAO_Object_Field_T (void)
+{
+ CORBA::release (this->ptr_);
+}
+
+template<class T> ACE_INLINE TAO_Object_Field_T<T> &
+TAO_Object_Field_T<T>::operator= (T* object)
+{
+ CORBA::release (this->ptr_);
+ this->ptr_ = object;
+ return *this;
+}
+
+template<class T> ACE_INLINE TAO_Object_Field_T<T> &
+TAO_Object_Field_T<T>::operator= (const TAO_Object_Field_T<T> &rhs)
+{
+ if (this != &rhs)
+ {
+ CORBA::release (this->ptr_);
+ this->ptr_ = T::_duplicate (rhs.ptr_);
+ }
+ return *this;
+}
+
+template<class T> ACE_INLINE T*
+TAO_Object_Field_T<T>::ptr (void) const
+{
+ return this->ptr_;
+}
+
+template<class T> ACE_INLINE
+TAO_Object_Field_T<T>::operator const T* &() const
+{
+ return this->ptr_;
+}
+
+template<class T> ACE_INLINE
+TAO_Object_Field_T<T>::operator T* &()
+{
+ return this->ptr_;
+}
+
+template<class T> ACE_INLINE T*
+TAO_Object_Field_T<T>::operator-> (void) const
+{
+ return this->ptr_;
+}
+
+template<class T> ACE_INLINE T*
+TAO_Object_Field_T<T>::in (void) const
+{
+ return this->ptr_;
+}
+
+template<class T> ACE_INLINE T* &
+TAO_Object_Field_T<T>::inout (void)
+{
+ return this->ptr_;
+}
+
+template<class T> ACE_INLINE T* &
+TAO_Object_Field_T<T>::out (void)
+{
+ CORBA::release (this->ptr_);
+ this->ptr_ = 0;
+ return this->ptr_;
+}
+
+template<class T> ACE_INLINE T*
+TAO_Object_Field_T<T>::_retn (void)
+{
+ // yield ownership of managed obj reference
+ T* val = this->ptr_;
+ this->ptr_ = 0;
+ return val;
+}
+