Line data Source code
1 : /*
2 : *
3 : *
4 : * Distributed under the OpenDDS License.
5 : * See: http://www.opendds.org/license.html
6 : */
7 :
8 : #include "ReceivedDataElementList.h"
9 :
10 : #include <ace/Truncate.h>
11 :
12 : #include <utility>
13 : #include <algorithm>
14 :
15 : TAO_BEGIN_VERSIONED_NAMESPACE_DECL
16 :
17 : namespace TAO {
18 : namespace DCPS {
19 :
20 : //ZeroCopyVector implementation
21 :
22 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
23 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::ZeroCopyVector::ZeroCopyVector(
24 : const size_t init_size,
25 : ACE_Allocator* alloc)
26 0 : : ACE_Vector<OpenDDS::DCPS::ReceivedDataElement*, DEF_MAX> (init_size, alloc)
27 : {
28 0 : }
29 :
30 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
31 : void
32 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::ZeroCopyVector::swap(ZeroCopyVector& rhs)
33 : {
34 : // Later versions of ACE do have a working ACE_Vector<T,MAX>::swap so we must
35 : // delegate up to ACE_Array<T> to get consistent swap behavior.
36 0 : ACE_Array<OpenDDS::DCPS::ReceivedDataElement*>::swap(rhs);
37 0 : std::swap(this->length_, rhs.length_);
38 0 : std::swap(this->curr_max_size_, rhs.curr_max_size_);
39 0 : }
40 :
41 : //ZeroCopyDataSeq implementation
42 :
43 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
44 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::ZeroCopyDataSeq(
45 : CORBA::ULong maximum /* = 0 */,
46 : CORBA::ULong init_size /* = DEF_MAX */,
47 : ACE_Allocator* alloc /* = 0 */)
48 0 : : loaner_(0)
49 0 : , ptrs_((maximum == 0) ? init_size : 0
50 : , alloc ? alloc : &default_allocator_)
51 0 : , sc_maximum_(maximum)
52 0 : , sc_length_(0)
53 0 : , sc_buffer_(sc_maximum_ ? allocbuf(sc_maximum_) : 0)
54 0 : , sc_release_(sc_maximum_)
55 : {
56 0 : }
57 :
58 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
59 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::ZeroCopyDataSeq(
60 : CORBA::ULong maximum,
61 : CORBA::ULong length,
62 : Sample_T* buffer,
63 : CORBA::Boolean release /* = false */)
64 : : loaner_(0)
65 : , ptrs_(0)
66 : , sc_maximum_(maximum)
67 : , sc_length_(length)
68 : , sc_buffer_(buffer)
69 : , sc_release_(release)
70 : {
71 : }
72 :
73 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
74 : ZeroCopyDataSeq<Sample_T, DEF_MAX>&
75 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::operator=(
76 : const ZeroCopyDataSeq& frm)
77 : {
78 : if (this != &frm) {
79 : ZeroCopyDataSeq<Sample_T, DEF_MAX> temp(frm);
80 : swap(temp);
81 : }
82 :
83 : return *this;
84 : }
85 :
86 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
87 : void
88 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::swap(ZeroCopyDataSeq& frm)
89 : {
90 0 : bool thisUsedDefAlloc = ptrs_.allocator_ == &default_allocator_;
91 0 : bool thisUsedLocalBuffer = ptrs_.array_ == default_allocator_.pool();
92 0 : bool frmUsedDefAlloc = frm.ptrs_.allocator_ == &frm.default_allocator_;
93 0 : bool frmUsedLocalBuffer = frm.ptrs_.array_ == frm.default_allocator_.pool();
94 :
95 0 : std::swap(loaner_, frm.loaner_);
96 0 : std::swap(default_allocator_, frm.default_allocator_);
97 0 : ptrs_.swap(frm.ptrs_);
98 0 : std::swap(sc_maximum_, frm.sc_maximum_);
99 0 : std::swap(sc_length_, frm.sc_length_);
100 0 : std::swap(sc_buffer_, frm.sc_buffer_);
101 0 : std::swap(sc_release_, frm.sc_release_);
102 :
103 0 : if (thisUsedDefAlloc) frm.ptrs_.allocator_ = &frm.default_allocator_;
104 :
105 0 : if (thisUsedLocalBuffer) frm.ptrs_.array_ = frm.default_allocator_.pool();
106 :
107 0 : if (frmUsedDefAlloc) ptrs_.allocator_ = &default_allocator_;
108 :
109 0 : if (frmUsedLocalBuffer) ptrs_.array_ = default_allocator_.pool();
110 0 : }
111 :
112 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
113 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::~ZeroCopyDataSeq()
114 : {
115 0 : if (!this->release())
116 : {
117 0 : this->length(0);
118 : }
119 :
120 0 : if (sc_release_ && sc_buffer_) freebuf(sc_buffer_);
121 0 : }
122 :
123 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
124 : bool
125 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::is_zero_copy() const
126 : {
127 0 : return sc_maximum_ == 0;
128 : }
129 :
130 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
131 : CORBA::ULong
132 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::maximum() const
133 : {
134 0 : return sc_maximum_;
135 : }
136 :
137 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
138 : CORBA::ULong
139 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::max_slots() const
140 : {
141 0 : return is_zero_copy() ? static_cast<CORBA::ULong>(ptrs_.max_size())
142 0 : : sc_maximum_;
143 : }
144 :
145 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
146 : CORBA::ULong
147 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::length() const
148 : {
149 0 : return is_zero_copy() ? static_cast<CORBA::ULong>(ptrs_.size()) : sc_length_;
150 : }
151 :
152 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
153 : const Sample_T&
154 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::operator[](CORBA::ULong i) const
155 : {
156 : if (is_zero_copy()) {
157 : if (ptrs_[i]->registered_data_) {
158 : return *static_cast<const Sample_T*>(ptrs_[i]->registered_data_);
159 : }
160 : return default_;
161 :
162 : } else {
163 : return sc_buffer_[i];
164 : }
165 : }
166 :
167 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
168 : Sample_T&
169 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::operator[](CORBA::ULong i)
170 : {
171 0 : if (is_zero_copy()) {
172 0 : if (ptrs_[i]->registered_data_) {
173 0 : return *static_cast<Sample_T*>(ptrs_[i]->registered_data_);
174 : }
175 0 : return default_;
176 :
177 : } else {
178 0 : return sc_buffer_[i];
179 : }
180 : }
181 :
182 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
183 : CORBA::Boolean
184 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::release() const
185 : {
186 0 : return sc_release_; //will always be false in zero-copy mode
187 : }
188 :
189 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
190 : void
191 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::replace(
192 : CORBA::ULong maximum,
193 : CORBA::ULong length,
194 : Sample_T* buffer,
195 : CORBA::Boolean release /* = false */)
196 : {
197 : ZeroCopyDataSeq<Sample_T, DEF_MAX> newOne(maximum, length, buffer, release);
198 : swap(newOne);
199 : }
200 :
201 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
202 : void
203 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::make_single_copy(CORBA::ULong maximum)
204 : {
205 0 : CORBA::ULong currentSize(static_cast<CORBA::ULong>(ptrs_.size()));
206 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX> sc((std::max)(maximum, currentSize));
207 0 : sc.length(currentSize);
208 :
209 0 : for (CORBA::ULong i(0); i < ptrs_.size(); ++i) {
210 0 : sc[i] = (*this)[i];
211 : }
212 :
213 0 : swap(sc);
214 0 : }
215 :
216 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
217 : const Sample_T*
218 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::get_buffer() const
219 : {
220 : //If we're currently zero-copy we must become single copy in order to return
221 : //a contiguous buffer. The only way to do this and meet the CORBA/C++ spec
222 : //interface is to cast-away the constness.
223 : if (is_zero_copy())
224 : const_cast<ZeroCopyDataSeq*>(this)->make_single_copy(max_slots());
225 :
226 : if (!sc_buffer_) {
227 : sc_buffer_ = allocbuf(sc_maximum_);
228 : sc_release_ = true;
229 : }
230 :
231 : return sc_buffer_;
232 : }
233 :
234 : /*static*/
235 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
236 : Sample_T*
237 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::allocbuf(CORBA::ULong nelems)
238 : {
239 0 : return new Sample_T[nelems];
240 : }
241 :
242 : /*static*/
243 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
244 : void
245 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::freebuf(Sample_T* buffer)
246 : {
247 0 : delete[] buffer;
248 0 : }
249 :
250 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
251 : void
252 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::internal_set_length(CORBA::ULong len)
253 : {
254 0 : if (!is_zero_copy() || len < ptrs_.size()) {
255 0 : length(len);
256 :
257 0 : } else if (len > ptrs_.size()) {
258 : //We need the vector to grow efficiently (not reallocate on each call)...
259 0 : ptrs_.resize((std::max)(len, CORBA::ULong(ptrs_.size()) * 2), 0);
260 : //...but maintain the invariant that the size of ptrs_ is our length
261 0 : ptrs_.resize(len, 0);
262 : }
263 0 : }
264 :
265 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
266 : void
267 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::set_loaner(
268 : OpenDDS::DCPS::DataReaderImpl* loaner)
269 : {
270 0 : loaner_ = loaner;
271 0 : }
272 :
273 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
274 : void
275 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::assign_ptr(
276 : CORBA::ULong ii,
277 : OpenDDS::DCPS::ReceivedDataElement* item)
278 : {
279 0 : OPENDDS_ASSERT(is_zero_copy());
280 0 : if (ptrs_[ii]) {
281 0 : --ptrs_[ii]->zero_copy_cnt_;
282 0 : ptrs_[ii]->dec_ref();
283 : }
284 :
285 0 : item->inc_ref();
286 0 : ++item->zero_copy_cnt_;
287 0 : ptrs_[ii] = item;
288 0 : }
289 :
290 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
291 : OpenDDS::DCPS::ReceivedDataElement*
292 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::get_ptr(CORBA::ULong ii) const
293 : {
294 : OPENDDS_ASSERT(is_zero_copy());
295 : return ptrs_[ii];
296 : }
297 :
298 : template <class Sample_T, size_t DEF_MAX> ACE_INLINE
299 : void
300 0 : ZeroCopyDataSeq<Sample_T, DEF_MAX>::assign_sample(
301 : CORBA::ULong ii, const Sample_T& sample)
302 : {
303 0 : OPENDDS_ASSERT(!is_zero_copy());
304 0 : sc_buffer_[ii] = sample;
305 0 : }
306 :
307 : } // namespace DCPS
308 : } // namespace TAO
309 :
310 : TAO_END_VERSIONED_NAMESPACE_DECL
|