ZeroCopySeq_T.inl

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #include "dds/DCPS/ReceivedDataElementList.h"
00009 #include "ace/Truncate.h"
00010 
00011 #include <utility>
00012 #include <algorithm>
00013 
00014 TAO_BEGIN_VERSIONED_NAMESPACE_DECL
00015 
00016 namespace TAO {
00017 namespace DCPS {
00018 
00019 //ZeroCopyVector implementation
00020 
00021 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00022 ZeroCopyDataSeq<Sample_T, DEF_MAX>::ZeroCopyVector::ZeroCopyVector(
00023   const size_t init_size,
00024   ACE_Allocator* alloc)
00025   : ACE_Vector<OpenDDS::DCPS::ReceivedDataElement*, DEF_MAX> (init_size, alloc)
00026 {
00027 }
00028 
00029 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00030 void
00031 ZeroCopyDataSeq<Sample_T, DEF_MAX>::ZeroCopyVector::swap(ZeroCopyVector& rhs)
00032 {
00033   // Later versions of ACE do have a working ACE_Vector<T,MAX>::swap so we must
00034   // delegate up to ACE_Array<T> to get consistent swap behavior.
00035   ACE_Array<OpenDDS::DCPS::ReceivedDataElement*>::swap(rhs);
00036   std::swap(this->length_, rhs.length_);
00037   std::swap(this->curr_max_size_, rhs.curr_max_size_);
00038 }
00039 
00040 //ZeroCopyDataSeq implementation
00041 
00042 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00043 ZeroCopyDataSeq<Sample_T, DEF_MAX>::ZeroCopyDataSeq(
00044   CORBA::ULong maximum /* = 0 */,
00045   CORBA::ULong init_size /* = DEF_MAX */,
00046   ACE_Allocator* alloc /* = 0 */)
00047   : loaner_(0)
00048   , ptrs_((maximum == 0) ? init_size : 0
00049             , alloc ? alloc : &default_allocator_)
00050   , sc_maximum_(maximum)
00051   , sc_length_(0)
00052   , sc_buffer_(sc_maximum_ ? allocbuf(sc_maximum_) : 0)
00053   , sc_release_(sc_maximum_)
00054 {
00055 }
00056 
00057 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00058 ZeroCopyDataSeq<Sample_T, DEF_MAX>::ZeroCopyDataSeq(
00059   CORBA::ULong maximum,
00060   CORBA::ULong length,
00061   Sample_T* buffer,
00062   CORBA::Boolean release /* = false */)
00063   : loaner_(0)
00064   , ptrs_(0)
00065   , sc_maximum_(maximum)
00066   , sc_length_(length)
00067   , sc_buffer_(buffer)
00068   , sc_release_(release)
00069 {
00070 }
00071 
00072 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00073 ZeroCopyDataSeq<Sample_T, DEF_MAX>&
00074 ZeroCopyDataSeq<Sample_T, DEF_MAX>::operator=(
00075   const ZeroCopyDataSeq& frm)
00076 {
00077   if (this != &frm) {
00078     ZeroCopyDataSeq<Sample_T, DEF_MAX> temp(frm);
00079     swap(temp);
00080   }
00081 
00082   return *this;
00083 }
00084 
00085 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00086 void
00087 ZeroCopyDataSeq<Sample_T, DEF_MAX>::swap(ZeroCopyDataSeq& frm)
00088 {
00089   bool thisUsedDefAlloc = ptrs_.allocator_ == &default_allocator_;
00090   bool thisUsedLocalBuffer = ptrs_.array_ == default_allocator_.pool();
00091   bool frmUsedDefAlloc = frm.ptrs_.allocator_ == &frm.default_allocator_;
00092   bool frmUsedLocalBuffer = frm.ptrs_.array_ == frm.default_allocator_.pool();
00093 
00094   std::swap(loaner_, frm.loaner_);
00095   std::swap(default_allocator_, frm.default_allocator_);
00096   ptrs_.swap(frm.ptrs_);
00097   std::swap(sc_maximum_, frm.sc_maximum_);
00098   std::swap(sc_length_, frm.sc_length_);
00099   std::swap(sc_buffer_, frm.sc_buffer_);
00100   std::swap(sc_release_, frm.sc_release_);
00101 
00102   if (thisUsedDefAlloc) frm.ptrs_.allocator_ = &frm.default_allocator_;
00103 
00104   if (thisUsedLocalBuffer) frm.ptrs_.array_ = frm.default_allocator_.pool();
00105 
00106   if (frmUsedDefAlloc) ptrs_.allocator_ = &default_allocator_;
00107 
00108   if (frmUsedLocalBuffer) ptrs_.array_ = default_allocator_.pool();
00109 }
00110 
00111 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00112 ZeroCopyDataSeq<Sample_T, DEF_MAX>::~ZeroCopyDataSeq()
00113 {
00114   if (!this->release())
00115   {
00116     this->length(0);
00117   }
00118 
00119   if (sc_release_ && sc_buffer_) freebuf(sc_buffer_);
00120 }
00121 
00122 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00123 bool
00124 ZeroCopyDataSeq<Sample_T, DEF_MAX>::is_zero_copy() const
00125 {
00126   return sc_maximum_ == 0;
00127 }
00128 
00129 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00130 CORBA::ULong
00131 ZeroCopyDataSeq<Sample_T, DEF_MAX>::maximum() const
00132 {
00133   return sc_maximum_;
00134 }
00135 
00136 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00137 CORBA::ULong
00138 ZeroCopyDataSeq<Sample_T, DEF_MAX>::max_slots() const
00139 {
00140   return is_zero_copy() ? static_cast<CORBA::ULong>(ptrs_.max_size())
00141     : sc_maximum_;
00142 }
00143 
00144 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00145 CORBA::ULong
00146 ZeroCopyDataSeq<Sample_T, DEF_MAX>::length() const
00147 {
00148   return is_zero_copy() ? static_cast<CORBA::ULong>(ptrs_.size()) : sc_length_;
00149 }
00150 
00151 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00152 const Sample_T&
00153 ZeroCopyDataSeq<Sample_T, DEF_MAX>::operator[](CORBA::ULong i) const
00154 {
00155   if (is_zero_copy()) {
00156     if (ptrs_[i]->registered_data_) {
00157       return *static_cast<const Sample_T*>(ptrs_[i]->registered_data_);
00158     }
00159     return default_;
00160 
00161   } else {
00162     return sc_buffer_[i];
00163   }
00164 }
00165 
00166 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00167 Sample_T&
00168 ZeroCopyDataSeq<Sample_T, DEF_MAX>::operator[](CORBA::ULong i)
00169 {
00170   if (is_zero_copy()) {
00171     if (ptrs_[i]->registered_data_) {
00172       return *static_cast<Sample_T*>(ptrs_[i]->registered_data_);
00173     }
00174     return default_;
00175 
00176   } else {
00177     return sc_buffer_[i];
00178   }
00179 }
00180 
00181 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00182 CORBA::Boolean
00183 ZeroCopyDataSeq<Sample_T, DEF_MAX>::release() const
00184 {
00185   return sc_release_; //will always be false in zero-copy mode
00186 }
00187 
00188 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00189 void
00190 ZeroCopyDataSeq<Sample_T, DEF_MAX>::replace(
00191   CORBA::ULong maximum,
00192   CORBA::ULong length,
00193   Sample_T* buffer,
00194   CORBA::Boolean release /* = false */)
00195 {
00196   ZeroCopyDataSeq<Sample_T, DEF_MAX> newOne(maximum, length, buffer, release);
00197   swap(newOne);
00198 }
00199 
00200 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00201 void
00202 ZeroCopyDataSeq<Sample_T, DEF_MAX>::make_single_copy(CORBA::ULong maximum)
00203 {
00204   CORBA::ULong currentSize(static_cast<CORBA::ULong>(ptrs_.size()));
00205   ZeroCopyDataSeq<Sample_T, DEF_MAX> sc((std::max)(maximum, currentSize));
00206   sc.length(currentSize);
00207 
00208   for (CORBA::ULong i(0); i < ptrs_.size(); ++i) {
00209     sc[i] = (*this)[i];
00210   }
00211 
00212   swap(sc);
00213 }
00214 
00215 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00216 const Sample_T*
00217 ZeroCopyDataSeq<Sample_T, DEF_MAX>::get_buffer() const
00218 {
00219   //If we're currently zero-copy we must become single copy in order to return
00220   //a contiguous buffer.  The only way to do this and meet the CORBA/C++ spec
00221   //interface is to cast-away the constness.
00222   if (is_zero_copy())
00223     const_cast<ZeroCopyDataSeq*>(this)->make_single_copy(max_slots());
00224 
00225   if (!sc_buffer_) {
00226     sc_buffer_ = allocbuf(sc_maximum_);
00227     sc_release_ = true;
00228   }
00229 
00230   return sc_buffer_;
00231 }
00232 
00233 /*static*/
00234 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00235 Sample_T*
00236 ZeroCopyDataSeq<Sample_T, DEF_MAX>::allocbuf(CORBA::ULong nelems)
00237 {
00238   return new Sample_T[nelems];
00239 }
00240 
00241 /*static*/
00242 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00243 void
00244 ZeroCopyDataSeq<Sample_T, DEF_MAX>::freebuf(Sample_T* buffer)
00245 {
00246   delete[] buffer;
00247 }
00248 
00249 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00250 void
00251 ZeroCopyDataSeq<Sample_T, DEF_MAX>::internal_set_length(CORBA::ULong len)
00252 {
00253   if (!is_zero_copy() || len < ptrs_.size()) {
00254     length(len);
00255 
00256   } else if (len > ptrs_.size()) {
00257     //We need the vector to grow efficiently (not reallocate on each call)...
00258     ptrs_.resize((std::max)(len, CORBA::ULong(ptrs_.size()) * 2), 0);
00259     //...but maintain the invariant that the size of ptrs_ is our length
00260     ptrs_.resize(len, 0);
00261   }
00262 }
00263 
00264 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00265 void
00266 ZeroCopyDataSeq<Sample_T, DEF_MAX>::set_loaner(
00267   OpenDDS::DCPS::DataReaderImpl* loaner)
00268 {
00269   loaner_ = loaner;
00270 }
00271 
00272 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00273 void
00274 ZeroCopyDataSeq<Sample_T, DEF_MAX>::assign_ptr(
00275   CORBA::ULong ii,
00276   OpenDDS::DCPS::ReceivedDataElement* item)
00277 {
00278   ACE_ASSERT(is_zero_copy());
00279   if (ptrs_[ii])
00280     ptrs_[ii]->dec_ref();
00281 
00282   item->inc_ref();
00283   ++item->zero_copy_cnt_;
00284   ptrs_[ii] = item;
00285 }
00286 
00287 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00288 OpenDDS::DCPS::ReceivedDataElement*
00289 ZeroCopyDataSeq<Sample_T, DEF_MAX>::get_ptr(CORBA::ULong ii) const
00290 {
00291   ACE_ASSERT(is_zero_copy());
00292   return ptrs_[ii];
00293 }
00294 
00295 template <class Sample_T, size_t DEF_MAX> ACE_INLINE
00296 void
00297 ZeroCopyDataSeq<Sample_T, DEF_MAX>::assign_sample(
00298   CORBA::ULong ii, const Sample_T& sample)
00299 {
00300   ACE_ASSERT(!is_zero_copy());
00301   sc_buffer_[ii] = sample;
00302 }
00303 
00304 } // namespace DCPS
00305 } // namespace TAO
00306 
00307 TAO_END_VERSIONED_NAMESPACE_DECL
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1