Line data Source code
1 : /* 2 : * Distributed under the OpenDDS License. 3 : * See: http://www.opendds.org/license.html 4 : */ 5 : 6 : #ifndef OPENDDS_DCPS_ZEROCOPYSEQ_T_H 7 : #define OPENDDS_DCPS_ZEROCOPYSEQ_T_H 8 : 9 : #include <ace/config-macros.h> 10 : #ifndef ACE_LACKS_PRAGMA_ONCE 11 : # pragma once 12 : #endif 13 : 14 : #include "ZeroCopySeqBase.h" 15 : #include "ZeroCopyAllocator_T.h" 16 : 17 : #include <ace/Vector_T.h> 18 : 19 : OPENDDS_BEGIN_VERSIONED_NAMESPACE_DECL 20 : 21 : namespace OpenDDS { 22 : namespace DCPS { 23 : 24 : class DataReaderImpl; 25 : class ReceivedDataElement; 26 : 27 : } // namespace DCPS 28 : } // namespace OpenDDS 29 : 30 : OPENDDS_END_VERSIONED_NAMESPACE_DECL 31 : 32 : 33 : TAO_BEGIN_VERSIONED_NAMESPACE_DECL 34 : 35 : //This must stay in namespace "TAO" until the tao_idl compiler is changed 36 : namespace TAO { 37 : namespace DCPS { 38 : 39 : /** 40 : * Provides [] operators returning sample references 41 : * but it is implemented as 42 : * an "array" of pointers to the samples so they can be 43 : * "loaned" to the application code. 44 : * 45 : * Design Goals: 46 : * - Provide enhanced performance known as "zero-copy" in the DDS spec 47 : * - Conform to the C++ CORBA mapping for sequences 48 : * - When necessary, certain uncommon sequence operations (resize, 49 : * get_buffer, replace) will cause copies. Performance impacts are 50 : * noted in comments on the individual methods. 51 : */ 52 : template <class Sample_T, size_t DEF_MAX = DCPS_ZERO_COPY_SEQ_DEFAULT_SIZE> 53 : class ZeroCopyDataSeq { 54 : public: 55 : 56 : typedef Sample_T value_type; 57 : 58 : /** 59 : * Construct a sequence of sample data values that supports 60 : * zero-copy reads. 61 : * 62 : * @param maximum Maximum number of samples to insert into the sequence. 63 : * If == 0 then use zero-copy reading. 64 : * Defaults to zero hence supporting zero-copy reads/takes. 65 : * 66 : * @param init_size Initial size of the underlying array of pointers. 67 : * 68 : * @param alloc The allocator used to allocate the array of pointers 69 : * to samples. If zero then use the default allocator. 70 : * 71 : * This constructor also serves as the "maximum" ctor and default ctor 72 : * in the CORBA spec. 73 : */ 74 : explicit ZeroCopyDataSeq(CORBA::ULong maximum = 0, 75 : CORBA::ULong init_size = DEF_MAX, ACE_Allocator* alloc = 0); 76 : 77 : ZeroCopyDataSeq(CORBA::ULong maximum, CORBA::ULong length, 78 : Sample_T* buffer, CORBA::Boolean release = false); 79 : 80 : ZeroCopyDataSeq(const ZeroCopyDataSeq& frm); 81 : 82 : ZeroCopyDataSeq& operator=(const ZeroCopyDataSeq& frm); 83 : 84 : void swap(ZeroCopyDataSeq& frm); 85 : 86 : ~ZeroCopyDataSeq(); 87 : 88 : CORBA::ULong maximum() const; 89 : 90 : /** Performance note: increasing the length of a zero-copy sequence past 91 : * its current length may cause a copy (the sequence will no longer be 92 : * zero-copy enabled). 93 : */ 94 : void length(CORBA::ULong length); 95 : CORBA::ULong length() const; 96 : 97 : const Sample_T& operator[](CORBA::ULong i) const; 98 : Sample_T& operator[](CORBA::ULong i); 99 : 100 : CORBA::Boolean release() const; 101 : 102 : void replace(CORBA::ULong max, CORBA::ULong length, Sample_T* buffer, 103 : CORBA::Boolean release = false); 104 : 105 : Sample_T* get_buffer(CORBA::Boolean orphan = false); 106 : const Sample_T* get_buffer() const; 107 : 108 : static Sample_T* allocbuf(CORBA::ULong nelems); 109 : static void freebuf(Sample_T* buffer); 110 : 111 : void increment_references(); 112 : 113 : ///Only used by the FooDataReaderImpl and tests 114 : class PrivateMemberAccess { 115 : public: 116 0 : explicit PrivateMemberAccess(ZeroCopyDataSeq& seq) 117 0 : : seq_(seq) {} 118 : 119 0 : CORBA::ULong max_slots() const { 120 0 : return seq_.max_slots(); 121 : } 122 : 123 0 : void internal_set_length(CORBA::ULong len) { 124 0 : seq_.internal_set_length(len); 125 0 : } 126 : 127 0 : void set_loaner(::OpenDDS::DCPS::DataReaderImpl* loaner) { 128 0 : seq_.set_loaner(loaner); 129 0 : } 130 : 131 0 : void assign_ptr(CORBA::ULong ii, OpenDDS::DCPS::ReceivedDataElement* item) { 132 0 : seq_.assign_ptr(ii, item); 133 0 : } 134 : 135 : OpenDDS::DCPS::ReceivedDataElement* get_ptr(CORBA::ULong ii) const { 136 : return seq_.get_ptr(ii); 137 : } 138 : 139 0 : void assign_sample(CORBA::ULong ii, const Sample_T& sample) { 140 0 : seq_.assign_sample(ii, sample); 141 0 : } 142 : 143 0 : void increment_references() { seq_.increment_references(); } 144 : 145 : private: 146 : ZeroCopyDataSeq& seq_; 147 : }; 148 : friend class PrivateMemberAccess; 149 : 150 : private: 151 : 152 : /** 153 : * In some versions of ACE, ACE_Vector doesn't have a working swap() 154 : * function, so we have to provide our own. 155 : * 156 : * This version also provides public access to the allocator_ member, 157 : * something the ACE_Vector doesn't do 158 : */ 159 : class ZeroCopyVector 160 : : public ACE_Vector<OpenDDS::DCPS::ReceivedDataElement*, DEF_MAX> { 161 : public: 162 : ZeroCopyVector(const size_t init_size = DEF_MAX, ACE_Allocator* alloc = 0); 163 : 164 : void swap(ZeroCopyVector&); 165 : 166 : typedef ACE_Vector<OpenDDS::DCPS::ReceivedDataElement*, DEF_MAX> BASE; 167 : using BASE::allocator_; 168 : using BASE::array_; 169 : }; 170 : 171 : /** 172 : * Current allocated number of sample slots. 173 : * 174 : * @note The DDS specification's use of maximum=0 to designate 175 : * zero-copy read request requires some 176 : * way of knowing the internally allocated slots 177 : * for sample pointers that is not "maximum". 178 : */ 179 : CORBA::ULong max_slots() const; 180 : 181 : void internal_set_length(CORBA::ULong len); 182 : 183 : void set_loaner(OpenDDS::DCPS::DataReaderImpl* loaner); 184 : 185 : void assign_ptr(CORBA::ULong ii, OpenDDS::DCPS::ReceivedDataElement* item); 186 : 187 : OpenDDS::DCPS::ReceivedDataElement* get_ptr(CORBA::ULong ii) const; 188 : 189 : void assign_sample(CORBA::ULong ii, const Sample_T& sample); 190 : 191 : bool is_zero_copy() const; 192 : 193 : void make_single_copy(CORBA::ULong maximum); 194 : 195 : /// The loaner that loaned its samples. 196 : OpenDDS::DCPS::DataReaderImpl* loaner_; 197 : 198 : /// the default allocator 199 : OpenDDS::DCPS::FirstTimeFastAllocator<OpenDDS::DCPS::ReceivedDataElement*, DEF_MAX> 200 : default_allocator_; 201 : 202 : typedef ZeroCopyVector Ptr_Seq_Type; 203 : 204 : /// array of pointers if the sequence is supporting zero-copy reads 205 : Ptr_Seq_Type ptrs_; 206 : static Sample_T default_; 207 : 208 : //single-copy (aka non-zero-copy) support 209 : CORBA::ULong sc_maximum_; 210 : CORBA::ULong sc_length_; 211 : mutable Sample_T* sc_buffer_; 212 : mutable CORBA::Boolean sc_release_; 213 : 214 : }; // class ZeroCopyDataSeq 215 : 216 : } // namespace DCPS 217 : } // namespace TAO 218 : 219 : TAO_END_VERSIONED_NAMESPACE_DECL 220 : 221 : #if defined (__ACE_INLINE__) 222 : #include "ZeroCopySeq_T.inl" 223 : #endif /* __ACE_INLINE__ */ 224 : 225 : #if defined (ACE_TEMPLATES_REQUIRE_SOURCE) 226 : #include "ZeroCopySeq_T.cpp" 227 : #endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ 228 : 229 : #if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) 230 : #pragma message ("ZeroCopySeq_T.cpp template inst") 231 : #pragma implementation ("ZeroCopySeq_T.cpp") 232 : #endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ 233 : 234 : #endif /* ZEROCOPYSEQ_H */