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

Generated on Fri Feb 12 20:05:29 2016 for OpenDDS by  doxygen 1.4.7