Revert "Minor modernization of DynamicAny code"
[ACE_TAO.git] / TAO / tao / Valuetype / ValueBase.h
blob32eeaed2b3deeb17c7c6e62ec7979996c755a370
1 // -*- C++ -*-
3 //=============================================================================
4 /**
5 * @file ValueBase.h
7 * @author Torsten Kuepper <kuepper2@lfa.uni-wuppertal.de>
8 */
9 //=============================================================================
11 #ifndef TAO_VALUEBASE_H
12 #define TAO_VALUEBASE_H
14 #include /**/ "ace/pre.h"
16 #include "tao/Valuetype/valuetype_export.h"
17 #include "tao/orbconf.h"
19 #if !defined (ACE_LACKS_PRAGMA_ONCE)
20 # pragma once
21 #endif /* ACE_LACKS_PRAGMA_ONCE */
23 #include "tao/Valuetype/Value_CORBA_methods.h"
24 #include "tao/Valuetype/Value_VarOut_T.h"
26 #include "tao/Object_Argument_T.h"
27 #include "tao/Arg_Traits_T.h"
28 #include "tao/Any_Insert_Policy_T.h"
30 #include "ace/Basic_Types.h"
31 #include "ace/Synch_Traits.h"
32 #include "ace/Thread_Mutex.h"
33 #include <atomic>
34 #include "ace/Null_Mutex.h"
35 #include "ace/Vector_T.h"
37 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
39 #define DEFAULT_INDIRECTION_MAP_SIZE 10
40 #define VERIFY_MAP(CDR, MAPNAME, MAPCLASSNAME) \
41 if (strm.get_##MAPNAME ().is_nil ()) \
42 { \
43 CDR::MAPCLASSNAME##_Handle handle ( \
44 new CDR::RC_##MAPCLASSNAME (new CDR::MAPCLASSNAME (DEFAULT_INDIRECTION_MAP_SIZE)));\
45 strm.set_##MAPNAME (handle); \
46 } else do {} while (0)
48 ///////////////
50 #undef TAO_local_COPY_VALUE_IS_PURE
51 #if defined(TAO_VALUETYPE_COPYING_ANY_INSERTION_USES_COPY_VALUE) || !defined(TAO_VALUETYPE_COPY_VALUE_IS_NOT_PURE)
52 #define TAO_local_COPY_VALUE_IS_PURE =0
53 #else
54 #define TAO_local_COPY_VALUE_IS_PURE
55 #endif
57 class TAO_Valuetype_Export TAO_ChunkInfo
59 public:
60 TAO_ChunkInfo (CORBA::Boolean do_chunking = false,
61 CORBA::Long init_level = false);
63 /// Methods to support chunking.
64 /// Note: These methods are called for both chunking and non-chunking
65 /// valuetype. These methods checks the chunking_ flag. If it's
66 /// set to be false the methods return true rightaway.
68 /// Methods for marshalling a valuetype.
70 /// This is called in the _tao_marshal_state (). This method reserves
71 /// space for the chunk size of the next chunk and also increments the
72 /// nesting level. The reservasion actually occurs the first time that
73 /// the start_chunk is called if there are multiple continuous start_chunk()
74 /// calls without the close_chunk() called in between.
75 CORBA::Boolean start_chunk (TAO_OutputCDR &strm);
77 /// This is called in the _tao_marshal_state (). This method writes the
78 /// actual chunk size to the reserved chunk size space and writes an end
79 /// tag with the negation value of current nesting level. A start_chunk()
80 /// needs an end_chunk() to close the current chunk. It's also needed for
81 /// writing the outmost endtag to the stream.
82 CORBA::Boolean end_chunk (TAO_OutputCDR &strm);
84 /// Methods for unmarshalling a valuetype.
86 /// This is called in the _tao_unmarshal_state () to read the chunk
87 /// size or an end tag.
88 CORBA::Boolean handle_chunking (TAO_InputCDR &strm);
89 /// This is called in the _tao_unmarshal_state () to skip the rest
90 /// chunks until the outmost endtag (-1) if the value is truncated
91 /// to its truncatable parent.
92 CORBA::Boolean skip_chunks (TAO_InputCDR &strm);
93 /// This is called in end_chunk(). It writes the actual chunk size to the
94 /// reserved chunk size space.
95 CORBA::Boolean write_previous_chunk_size (TAO_OutputCDR &strm);
96 /// Reserve space for chunk size. The memory in the stream will be
97 /// overwritten after all the chunk data is written. This method
98 /// only allows the reservasion being made once if the reserved
99 /// space has not been overwritten.
100 CORBA::Boolean reserve_chunk_size (TAO_OutputCDR &strm);
102 /// A flag to indicate that this instance is actually involved in a chunked
103 /// or truncatable valuetype.
104 CORBA::Boolean chunking_;
106 /// The level of nesting valuetypes.
107 CORBA::Long value_nesting_level_;
108 /// The starting position of the size of current chunk.
109 char* chunk_size_pos_;
110 /// The length of CDR stream from the beginning to the current
111 /// chunk data starting position. Used to calculate the chunk size
112 /// across multiple chained ACE_Message_Blocks.
113 size_t length_to_chunk_octets_pos_;
114 /// The end position of current chunk.
115 char* chunk_octets_end_pos_;
118 namespace CORBA
120 class ValueFactoryBase;
121 typedef ValueFactoryBase *ValueFactory;
123 class ValueBase;
125 typedef TAO_Value_Var_T<ValueBase> ValueBase_var;
126 typedef TAO_Value_Out_T<ValueBase> ValueBase_out;
129 * @class ValueBase
131 * @brief Abstract baseclass for Valuetypes
133 * @see CORBA 2.3 - Section 20.17.5
135 class TAO_Valuetype_Export ValueBase
137 public:
138 friend class TAO_ChunkInfo;
140 typedef ValueBase* _ptr_type;
141 typedef ValueBase_var _var_type;
142 typedef ValueBase_out _out_type;
144 typedef ACE_Vector < ACE_CString > Repository_Id_List;
146 virtual CORBA::ValueBase* _copy_value () TAO_local_COPY_VALUE_IS_PURE;
148 // Reference counting.
149 virtual void _add_ref () = 0;
150 virtual void _remove_ref () = 0;
151 virtual CORBA::ULong _refcount_value () = 0;
153 // dynamic casting
154 static CORBA::ValueBase* _downcast (CORBA::ValueBase *);
156 /// TAO extension
158 /// Used in the implementation of CORBA::Any
159 static void _tao_any_destructor (void *);
160 virtual CORBA::TypeCode_ptr _tao_type () const = 0;
162 /// Return the repository id of this valuetype.
163 virtual const char * _tao_obv_repository_id () const = 0;
165 /// Give the list of the RepositoryIds in the valuetype "truncatable"
166 /// inheritance hierarchy. List the id of this valuetype as first
167 /// RepositoryID and go up the "truncatable" derivation hierarchy.
168 /// Note the truncatable repo ids only list the truncatable base types
169 /// to which this type is safe to truncate, not all its parents.
170 virtual void _tao_obv_truncatable_repo_ids (Repository_Id_List &) const = 0;
172 // TAO internal --------------------------
174 /// Marshal a valuetype (see operator<< in tao_idl generated file
175 /// how it is called)
176 static CORBA::Boolean _tao_marshal (TAO_OutputCDR &strm,
177 const ValueBase *_this,
178 ptrdiff_t formal_type_id = 0);
180 /// Unmarshal a valuetype, if formal type is a pointer to
181 /// ValueBase
182 static CORBA::Boolean _tao_unmarshal (TAO_InputCDR &strm,
183 ValueBase *&new_object);
185 // static CORBA::Boolean
186 // T::_tao_unmarshal (TAO_InputCDR &, ValueBase *&_this)
187 // is typespecific for valuetype T and generated from tao_idl
188 // Use this for unmarshaling.
190 /// Both used internally and are called from T::_tao_unmarshal ()
191 static CORBA::Boolean _tao_unmarshal_pre (TAO_InputCDR &strm,
192 CORBA::ValueBase *&valuetype,
193 const char *const repo_id,
194 CORBA::Boolean &is_null_object,
195 CORBA::Boolean &is_indirected);
197 static CORBA::Boolean _tao_unmarshal_header (
198 TAO_InputCDR &strm,
199 const char *const fallback_repo_id,
200 Repository_Id_List &ids,
201 CORBA::Boolean &is_null_object,
202 CORBA::Boolean &is_indirected,
203 CORBA::Boolean &is_chunked);
205 CORBA::Boolean _tao_unmarshal_post (TAO_InputCDR &strm);
207 /// Check repository id for value box type against what is
208 /// in the CDR stream.
209 static CORBA::Boolean _tao_validate_box_type (
210 TAO_InputCDR &strm,
211 TAO_InputCDR &indirected_strm,
212 const char * const repo_id_expected,
213 CORBA::Boolean & null_object,
214 CORBA::Boolean & is_indirected);
215 #if defined (GEN_OSTREAM_OPS)
216 /// Used by optionally generated ostream operators for valuetypes
217 /// to output the state of the actual type for debugging.
218 static std::ostream& _tao_stream (std::ostream &strm, const ValueBase *value);
219 virtual std::ostream& _tao_stream_v (std::ostream &strm) const;
220 #endif /* GEN_OSTREAM_OPS */
222 public: // otherwise these cannot be called from a static function
223 /// During marshal jump to the most derived part
224 virtual CORBA::Boolean _tao_marshal_v (TAO_OutputCDR &) const = 0;
226 /// Called after obtaining the fresh object from create_for_unmarshal ()
227 virtual CORBA::Boolean _tao_unmarshal_v (TAO_InputCDR &) = 0;
229 /// Notify the truncated parent valuetype to skip the rest of the chunks
230 /// when unmarshalling a value from its derived valuetype.
231 /// This is called when the factory for the most derived valuetype (in
232 /// the repository id list) does not exist and a truncated parent factory
233 /// is registered.
234 virtual void truncation_hook ();
236 protected:
237 ValueBase ();
238 ValueBase (const ValueBase&);
239 virtual ~ValueBase () = default;
241 /// This flag is set to be true when the valuetype defined
242 /// in the idl has the truncatable parent.
243 CORBA::Boolean is_truncatable_;
245 /// This flag is set to be true when marshalling uses chunking.
246 /// According to spec, the truncatable valuetype should use chunking
247 /// and it can be used for marshalling large valuetype. In current
248 /// implementation, we just use chunking for the truncatable valuetype.
249 CORBA::Boolean chunking_;
251 /// Compare the supplied formal type identifier with our actual type.
252 /// This is used during marshaling of valuetypes to detect when it is
253 /// appropriate to not explicitly marshal the typecode for the value.
254 virtual CORBA::Boolean _tao_match_formal_type (ptrdiff_t ) const = 0;
256 private:
257 static void _tao_unmarshal_find_factory (
258 TAO_InputCDR &strm,
259 void *start_of_valuetype,
260 CORBA::ValueBase *&valuetype,
261 Repository_Id_List &ids,
262 CORBA::Boolean &is_chunked);
264 static CORBA::Boolean _tao_unmarshal_value_indirection_pre (TAO_InputCDR &strm,
265 TAO_InputCDR &indirected_strm);
267 static CORBA::Boolean _tao_unmarshal_value_indirection (TAO_InputCDR &strm,
268 CORBA::ValueBase *&value);
270 static CORBA::Boolean _tao_unmarshal_repo_id_indirection (TAO_InputCDR &strm,
271 ACE_CString& repo_id);
273 static CORBA::Boolean _tao_unmarshal_codebase_url_indirection (TAO_InputCDR &strm,
274 ACE_CString& codebase_url);
275 public:
276 static CORBA::Boolean _tao_write_repository_id (TAO_OutputCDR &strm,
277 ACE_CString& id);
279 /// Write some special values such as null value or indirection value.
280 static CORBA::Boolean _tao_write_special_value(TAO_OutputCDR &strm,
281 const CORBA::ValueBase * value);
282 private:
283 /// Write whole value.
284 static CORBA::Boolean _tao_write_value(TAO_OutputCDR &strm,
285 const CORBA::ValueBase * value,
286 ptrdiff_t formal_type_id);
288 /// Write the header of the value which includes the valuetag, number of
289 /// repository ids and list of repository ids.
290 CORBA::Boolean _tao_write_value_header(TAO_OutputCDR &strm,
291 ptrdiff_t formal_type_id) const;
293 /// Read a single repository id from the CDR input stream,
294 /// accounting for indirection.
295 static CORBA::Boolean _tao_read_repository_id (TAO_InputCDR& strm,
296 ACE_CString& id);
298 /// Read a list of repository ids from the CDR input stream,
299 /// accounting for indirection
300 static CORBA::Boolean _tao_read_repository_id_list (TAO_InputCDR& strm,
301 Repository_Id_List& ids);
303 /// Read a codebase url from the CDR input stream,
304 /// accounting for indirection.
305 static CORBA::Boolean _tao_read_codebase_url (TAO_InputCDR& strm,
306 ACE_CString& codebase_url);
307 private:
308 ValueBase & operator= (const ValueBase &);
309 }; // ValueBase
311 /// Valuetype-related type codes.
312 extern TAO_Valuetype_Export TypeCode_ptr const _tc_ValueBase;
313 extern TAO_Valuetype_Export TypeCode_ptr const _tc_EventBase;
316 * @class DefaultValueRefCountBase
318 * @brief Default mix-in for reference count of a valuetype.
320 * Default mix-in for reference count of a valuetype.
322 class TAO_Valuetype_Export DefaultValueRefCountBase
323 : public virtual ValueBase
325 public:
326 virtual void _add_ref ();
327 virtual void _remove_ref ();
328 virtual CORBA::ULong _refcount_value ();
330 /// The _tao variants are inline for fast access from T_var
331 /// (if valuetype T is compiled with optimization for that.) %! (todo)
332 void _tao_add_ref ();
333 void _tao_remove_ref ();
334 CORBA::ULong _tao_refcount_value () const;
336 protected:
337 DefaultValueRefCountBase ();
338 DefaultValueRefCountBase (const DefaultValueRefCountBase&);
339 virtual ~DefaultValueRefCountBase ();
341 private:
342 void operator= (const DefaultValueRefCountBase &);
344 private: // data
345 /// Reference counter.
346 std::atomic<uint32_t> refcount_;
347 }; // DefaultValueRefCountBase
349 // which lock has the lowest memory overhead ?
350 // %! todo refcountbase w/o locking (now memory overhead)
351 // $! todo: debug aids for refcounts
353 } // End CORBA namespace
355 # if defined (__ACE_INLINE__)
356 # define TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION inline
357 # else
358 # define TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION extern TAO_Valuetype_Export
359 # endif
362 * @namespace TAO_OBV_GIOP_Flags
364 * @brief TAO_OBV_GIOP_Flags
366 * @see CORBA 3.0.3 -- Section 15.3.4
368 namespace TAO_OBV_GIOP_Flags
370 const CORBA::Long Value_tag_base = 0x7fffff00L;
371 const CORBA::Long Value_tag_sigbits = 0x7fffff00L;
372 const CORBA::Long Codebase_url = 1;
373 const CORBA::Long Type_info_sigbits = 0x00000006L;
374 const CORBA::Long Type_info_none = 0;
375 const CORBA::Long Type_info_single = 2;
376 const CORBA::Long Type_info_list = 6;
377 const CORBA::Long Chunking_tag_sigbits = 0x00000008L;
378 const CORBA::Long Indirection_tag = 0xFFFFFFFF;
379 const CORBA::Long Null_tag = 0x00000000L;
381 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean is_null_ref (CORBA::Long tag);
382 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean is_value_tag (CORBA::Long tag);
383 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean has_codebase_url (CORBA::Long tag);
384 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean has_no_type_info (CORBA::Long tag);
385 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean has_single_type_info (CORBA::Long tag);
386 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean has_list_type_info (CORBA::Long tag);
387 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean is_chunked (CORBA::Long tag);
388 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean is_indirection_tag (CORBA::Long tag);
389 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean is_indirection (CORBA::Long tag);
390 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean is_block_size (CORBA::Long tag);
391 TAO_OBV_GIOP_FLAGS_INLINE_FUNCTION CORBA::Boolean is_end_tag (CORBA::Long tag);
394 TAO_Valuetype_Export CORBA::Boolean
395 operator<< (TAO_OutputCDR&, const CORBA::ValueBase *);
397 TAO_Valuetype_Export CORBA::Boolean
398 operator>> (TAO_InputCDR&, CORBA::ValueBase *&);
400 #if defined (GEN_OSTREAM_OPS)
402 /// Outputs the state for debugging.
403 TAO_Valuetype_Export std::ostream&
404 operator<< (std::ostream&, CORBA::ValueBase *);
406 #endif /* GEN_OSTREAM_OPS */
408 /// Used in generated code if CORBA::ValueBase is an argument or return type.
409 namespace TAO
411 template<>
412 class TAO_Valuetype_Export Arg_Traits<CORBA::ValueBase>
413 : public Object_Arg_Traits_T<CORBA::ValueBase *,
414 CORBA::ValueBase_var,
415 CORBA::ValueBase_out,
416 TAO::Value_Traits<CORBA::ValueBase>,
417 TAO::Any_Insert_Policy_Stream>
421 template<>
422 struct TAO_Valuetype_Export Value_Traits<CORBA::ValueBase>
424 static void add_ref (CORBA::ValueBase *);
425 static void remove_ref (CORBA::ValueBase *);
427 // For INOUT value type arguments, so they can use the same set
428 // of arg classes as interfaces.
429 static void release (CORBA::ValueBase *);
433 #undef TAO_local_COPY_VALUE_IS_PURE
434 TAO_END_VERSIONED_NAMESPACE_DECL
436 #if defined (__ACE_INLINE__)
437 # include "tao/Valuetype/ValueBase.inl"
438 #endif /* __ACE_INLINE__*/
440 #include /**/ "ace/post.h"
442 #endif /* TAO_VALUEBASE_H */