Line data Source code
1 : /* 2 : * 3 : * 4 : * Distributed under the OpenDDS License. 5 : * See: http://www.opendds.org/license.html 6 : */ 7 : 8 : #ifndef OPENDDS_DCPS_ZEROCOPYSEQ_T_CPP 9 : #define OPENDDS_DCPS_ZEROCOPYSEQ_T_CPP 10 : 11 : #if !defined (ACE_LACKS_PRAGMA_ONCE) 12 : # pragma once 13 : #endif /* ACE_LACKS_PRAGMA_ONCE */ 14 : 15 : #include "ZeroCopySeq_T.h" 16 : 17 : #if !defined (__ACE_INLINE__) 18 : #include "ZeroCopySeq_T.inl" 19 : #endif /* __//ACE_INLINE__ */ 20 : 21 : TAO_BEGIN_VERSIONED_NAMESPACE_DECL 22 : 23 : namespace TAO { 24 : namespace DCPS { 25 : 26 : template <class Sample_T, size_t DEF_MAX> 27 : Sample_T ZeroCopyDataSeq<Sample_T, DEF_MAX>::default_; 28 : 29 : template <class Sample_T, size_t DEF_MAX> 30 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::ZeroCopyDataSeq( 31 : const ZeroCopyDataSeq& frm) 32 : : loaner_(frm.loaner_) 33 : , ptrs_(frm.ptrs_.size(), 34 : (frm.ptrs_.allocator_ == 35 : static_cast<const ACE_Allocator*>(&frm.default_allocator_)) 36 : ? &default_allocator_ 37 : : const_cast<ACE_Allocator*>(frm.ptrs_.allocator_)) 38 : //The constructor of ptrs_ requires a non-const ptr to ACE_Alloc. 39 : , sc_maximum_(frm.sc_maximum_) 40 : , sc_length_(0) //initialized below 41 : , sc_buffer_(frm.sc_maximum_ ? allocbuf(frm.sc_maximum_) : 0) 42 : , sc_release_(frm.sc_maximum_) 43 : { 44 : if (frm.is_zero_copy()) { 45 : ptrs_ = frm.ptrs_; 46 : 47 : //ptrs_ doesn't manage the ref count for its elements 48 : for (size_t ii = 0; ii < frm.ptrs_.size(); ++ii) { 49 : ptrs_[ii]->inc_ref(); 50 : ++ptrs_[ii]->zero_copy_cnt_; 51 : } 52 : 53 : } else { 54 : for (CORBA::ULong i = 0; i < frm.sc_length_; ++i) { 55 : sc_buffer_[i] = frm.sc_buffer_[i]; 56 : ++sc_length_; 57 : } 58 : } 59 : } 60 : 61 : #if defined (_MSC_VER) 62 : #pragma warning (disable:4996) //std::copy OK here 63 : #endif 64 : template <class Sample_T, size_t DEF_MAX> 65 : void 66 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::length(CORBA::ULong length) 67 : { 68 : using std::fill; 69 : using std::max; 70 : using std::copy; 71 : 72 0 : if (length == this->length()) { 73 0 : return; 74 : } 75 : 76 0 : if (is_zero_copy()) { 77 0 : if (length < ptrs_.size()) { 78 0 : if (!loaner_) { 79 0 : make_single_copy(length); 80 0 : this->length(length); 81 0 : return; 82 : } 83 : 84 0 : for (size_t i(length); i < ptrs_.size(); ++i) { 85 0 : --ptrs_[i]->zero_copy_cnt_; 86 0 : ptrs_[i]->dec_ref(); 87 : } 88 : 89 0 : ptrs_.resize(length, 0); 90 : // At this point, there is no longer a loan 91 0 : this->set_loaner(0); 92 : 93 : } else { 94 : //There's no way we can expand the size (logical) of the zero-copy 95 : //array and have the user do any meaningful operations on the new 96 : //elements. The fact that they're pointers to ReceivedDataElement 97 : //is hidden from the user. Thus we need to make the sequence 98 : //single-copy at this point. 99 0 : make_single_copy(length); 100 0 : sc_length_ = length; 101 : } 102 : 103 : } else { 104 0 : if (length < sc_length_) { //shrink 105 0 : sc_length_ = length; 106 : 107 0 : } else if (length <= sc_maximum_) { //grow within buffer 108 0 : fill(&sc_buffer_[sc_length_], &sc_buffer_[length], Sample_T()); 109 0 : sc_length_ = length; 110 : 111 : } else { //grow to larger buffer 112 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX> grow(max(length, sc_maximum_*2)); 113 0 : grow.sc_length_ = length; 114 0 : copy(sc_buffer_, &sc_buffer_[sc_length_], grow.sc_buffer_); 115 0 : fill(&grow.sc_buffer_[sc_length_], &grow.sc_buffer_[length], 116 0 : Sample_T()); 117 0 : swap(grow); 118 0 : } 119 : } 120 : } 121 : #if defined (_MSC_VER) 122 : #pragma warning (default:4996) 123 : #endif 124 : 125 : template <class Sample_T, size_t DEF_MAX> 126 : Sample_T* 127 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::get_buffer( 128 : CORBA::Boolean orphan /* = false */) 129 : { 130 : //Case 1: I can't give away what's not mine 131 : // (includes zero-copy since sc_release_ is always false for zero-copy 132 : if (orphan && !sc_release_) return 0; 133 : 134 : // (preparation for cases 2-3) 135 : if (is_zero_copy()) make_single_copy(max_slots()); 136 : 137 : if (!sc_buffer_) { 138 : sc_buffer_ = allocbuf(sc_maximum_); 139 : 140 : if (!orphan) sc_release_ = true; 141 : } 142 : 143 : //Case 2: Keeping the buffer but letting client use it too 144 : if (!orphan) return sc_buffer_; 145 : 146 : //Case 3: Orphaning the buffer to the client, leaves "this" in the 147 : // default-constructed state (which in our case is ZC-enabled) 148 : ZeroCopyDataSeq<Sample_T, DEF_MAX> yours; 149 : swap(yours); 150 : yours.sc_release_ = false; //don't freebuf in dtor 151 : return yours.sc_buffer_; 152 : } 153 : 154 : #if defined (_MSC_VER) 155 : #pragma warning (default:4996) 156 : #endif 157 : 158 : template <class Sample_T, size_t DEF_MAX> 159 0 : void ZeroCopyDataSeq<Sample_T, DEF_MAX>::increment_references() 160 : { 161 0 : if (is_zero_copy()) { 162 0 : for (size_t ii = 0; ii < ptrs_.size(); ++ii) { 163 0 : ptrs_[ii]->inc_ref(); 164 : } 165 : } 166 0 : } 167 : 168 : } // namespace DCPS 169 : } // namespace OpenDDS 170 : 171 : TAO_END_VERSIONED_NAMESPACE_DECL 172 : 173 : #endif /* OPENDDS_DCPS_ZEROCOPYSEQ_CPP */