SafetyProfileSequence.h

Go to the documentation of this file.
00001 #ifndef dds_DCPS_SafetyProfileSequence_h
00002 #define dds_DCPS_SafetyProfileSequence_h
00003 
00004 #include "dds/DCPS/SafetyProfilePool.h"
00005 #include "dds/DCPS/Serializer.h"
00006 #include "dds/DCPS/PoolAllocationBase.h"
00007 
00008 #include <tao/Array_VarOut_T.h> // Array_Traits
00009 #include <tao/String_Manager_T.h>
00010 
00011 #include <algorithm>
00012 #include <memory>
00013 #include <utility>
00014 #include <cstddef>
00015 #include <cstring>
00016 
00017 namespace OpenDDS {
00018 namespace SafetyProfile {
00019 
00020   template <typename T>
00021   struct StringTraits { };
00022 
00023   template <>
00024   struct StringTraits<CORBA::Char>
00025   {
00026     static CORBA::Char* alloc(CORBA::ULong len) { return CORBA::string_alloc(len); }
00027     static CORBA::Char* empty() { return dup(""); }
00028     static CORBA::Char* dup(const CORBA::Char* s) { return CORBA::string_dup(s); }
00029     static void free(CORBA::Char* s) { if (s) CORBA::string_free(s); }
00030 
00031     static int cmp(const CORBA::Char* lhs, const CORBA::Char* rhs)
00032     {
00033       return std::strcmp(lhs, rhs);
00034     }
00035   };
00036 
00037   typedef CORBA::ULong seq_size_type;
00038   typedef CORBA::Boolean seq_flag_type;
00039 
00040   template <seq_size_type N>
00041   struct Bounded {
00042     static const seq_size_type Bounds = N;
00043   };
00044 
00045   struct Unbounded {
00046     static const seq_size_type Bounds = INT_MAX;
00047   };
00048 
00049   template <typename T, typename Sequence, typename Bounds>
00050   struct AllocPolicy;
00051 
00052   template <typename T, typename Sequence, seq_size_type N>
00053   struct AllocPolicy<T, Sequence, Bounded<N> > {
00054     static T* allocbuf();
00055     seq_size_type maximum() const { return N; }
00056     seq_size_type max_size() const { return N; }
00057     void replace(seq_size_type length, T* data, seq_flag_type release = false)
00058     {
00059       static_cast<Sequence&>(*this).replace_i(N, length, data, release);
00060     }
00061   protected:
00062     explicit AllocPolicy(seq_size_type = N) {}
00063     T* allocate(seq_size_type = N) const { return allocbuf(); }
00064     void swap(AllocPolicy&) throw() {}
00065   };
00066 
00067   template <typename T, typename Sequence>
00068   struct AllocPolicy<T, Sequence, Unbounded> {
00069     static T* allocbuf(seq_size_type n);
00070     seq_size_type maximum() const { return maximum_; }
00071     seq_size_type max_size() const { return Unbounded::Bounds; }
00072     void replace(seq_size_type maximum, seq_size_type length,
00073                  T* data, seq_flag_type release = false)
00074     {
00075       static_cast<Sequence&>(*this).replace_i(maximum, length, data, release);
00076     }
00077   protected:
00078     explicit AllocPolicy(seq_size_type n = 0) : maximum_(n) {}
00079     T* allocate(seq_size_type request = 0) const
00080     {
00081       return allocbuf(request ? request : maximum_);
00082     }
00083     void swap(AllocPolicy& rhs) throw() { std::swap(maximum_, rhs.maximum_); }
00084     seq_size_type maximum_;
00085   };
00086 
00087   /// Element Policy for sequence elements that are IDL "fixed-length" types.
00088   /// These types don't need initialization or destruction of elements in their
00089   /// allocbuf()/freebuf() functions.
00090   /// @tparam T element type of the sequence
00091   template <typename T>
00092   struct DefaultEltPolicy {
00093     typedef T& Element;
00094     typedef const T& ConstElement;
00095     typedef T ConstRawElement;
00096     static const seq_size_type extra = 0;
00097     static T& make_element(T& elt, seq_flag_type) { return elt; }
00098     static void construct(T*, seq_size_type, seq_flag_type) {}
00099     static void copy_n(const T* input, seq_size_type n, T* output);
00100     static void move_n(T* in, seq_size_type n, T* out) { copy_n(in, n, out); }
00101     static void reset_n(T*, seq_size_type) {}
00102     static T* destroy(T* buffer, seq_size_type) { return buffer; }
00103   };
00104 
00105   /// Element Policy for sequence elements that are IDL "variable-length" types
00106   /// except for strings and arrays, which are handled separately.
00107   /// @tparam T element type of the sequence
00108   template <typename T>
00109   struct VariEltPolicy {
00110     typedef T& Element;
00111     typedef const T& ConstElement;
00112     typedef T ConstRawElement;
00113     static const seq_size_type extra = 1;
00114     static T& make_element(T& elt, seq_flag_type) { return elt; }
00115     static void construct(T* buffer, seq_size_type n, seq_flag_type cookie);
00116     static void copy_n(const T* input, seq_size_type n, T* output);
00117     static void move_n(T* in, seq_size_type n, T* out);
00118     static void reset_n(T* buffer, seq_size_type n);
00119     static T* destroy(T* buffer, seq_size_type n);
00120   };
00121 
00122   /// Element Policy for sequences of strings.
00123   /// @tparam CharT FACE::Char or FACE::WChar
00124   template <typename CharT>
00125   struct StringEltPolicy {
00126 
00127     /// Indexing a non-const string sequence yields an object of this class.
00128     /// This allows string memory management duing assignment.
00129     struct Element {
00130       Element(CharT*& element, seq_flag_type release)
00131         : element_(element), release_(release) {}
00132 
00133       Element(const Element& elt)
00134         : element_(elt.element_), release_(elt.release_) {}
00135 
00136       Element& operator=(const CharT* rhs)
00137       {
00138         ::TAO::String_var<CharT> tmp(rhs);
00139         return move_from(tmp);
00140       }
00141 
00142       Element& operator=(CharT* rhs)
00143       {
00144         ::TAO::String_var<CharT> tmp(rhs);
00145         return move_from(tmp);
00146       }
00147 
00148       Element& operator=(const ::TAO::String_var<CharT>& rhs)
00149       {
00150         ::TAO::String_var<CharT> tmp(rhs);
00151         return move_from(tmp);
00152       }
00153 
00154       Element& operator=(const ::TAO::String_Manager_T<CharT>& rhs)
00155       {
00156         ::TAO::String_var<CharT> tmp(rhs);
00157         return move_from(tmp);
00158       }
00159 
00160       operator const CharT*() const { return element_; }
00161       const CharT* in() const { return element_; }
00162       CharT*& inout() { return element_; }
00163 
00164       ::TAO::String_out<CharT> out() const
00165       {
00166         if (release_) StringTraits<CharT>::free(element_);
00167         return element_;
00168       }
00169 
00170       CharT* _retn()
00171       {
00172         CharT* const tmp = element_;
00173         element_ = StringTraits<CharT>::empty();
00174         return tmp;
00175       }
00176 
00177     private:
00178       Element& move_from(::TAO::String_var<CharT>& rhs)
00179       {
00180         if (release_) StringTraits<CharT>::free(element_);
00181         element_ = rhs._retn();
00182         return *this;
00183       }
00184 
00185       CharT*& element_;
00186       seq_flag_type release_;
00187 
00188       inline friend bool operator>>(DCPS::Serializer& ser, Element elt)
00189       {
00190         ser.read_string(elt.out(), StringTraits<CharT>::alloc,
00191           StringTraits<CharT>::free);
00192         return ser.good_bit();
00193       }
00194     };
00195 
00196     static Element make_element(CharT*& elt, seq_flag_type release)
00197     {
00198       return Element(elt, release);
00199     }
00200 
00201     typedef const CharT* ConstElement;
00202     typedef const CharT* ConstRawElement;
00203     static const seq_size_type extra = 1;
00204     static void construct(CharT** buf, seq_size_type n, seq_flag_type cookie);
00205     static void copy_n(const CharT* const* in, seq_size_type n, CharT** out);
00206     static void move_n(CharT** in, seq_size_type n, CharT** out);
00207     static void reset_n(CharT**, seq_size_type);
00208     static CharT** destroy(CharT** buffer, seq_size_type n);
00209   };
00210 
00211   /// Element Policy for sequences of arrays.
00212   /// Currently arrays of fixed-length and variable-length elements are both
00213   /// handled the same way, but optimizing the fixed-length element types could
00214   /// be done here (they don't need construction, destruction, or cookies).
00215   /// @tparam Forany the array's *_forany type generated by the IDL compiler
00216   template <typename Forany, typename T = typename Forany::_array_type>
00217   struct ArrayEltPolicy {
00218     typedef T& Element;
00219     typedef const T& ConstElement;
00220     typedef const T ConstRawElement;
00221     static const seq_size_type extra =
00222       (sizeof(seq_size_type) - 1) / sizeof(T) + 1;
00223     static T& make_element(T& elt, seq_flag_type) { return elt; }
00224     static void construct(T* buffer, seq_size_type n, seq_flag_type use_cookie);
00225     static void copy_n(const T* input, seq_size_type n, T* output);
00226     static void move_n(T* in, seq_size_type n, T* out) { copy_n(in, n, out); }
00227     static void reset_n(T* buffer, seq_size_type n);
00228     static T* destroy(T* buffer, seq_size_type n);
00229   };
00230 
00231   /// Generic base class for all IDL-defined sequences accepted by opendds_idl.
00232   /// Derived classes (generated by opendds_idl) need to provide the following
00233   /// methods to be compliant with the IDL-to-C++ specification:
00234   /// If bounded:
00235   /// - Constructors: default, copy, 3-arg
00236   /// If unbounded:
00237   /// - Constructors: default, copy, 1-arg (maximum), 4-arg
00238   /// Both bounded and unbounded:
00239   /// - Copy assignment
00240   /// - non-member swap(), while not in spec this is useful for copy assignment
00241   /// @tparam T element type of the sequence
00242   /// @tparam Bounds either Bounded<N> or Unbounded
00243   /// @tparam Elts element handling policy
00244   template <typename T, typename Bounds, typename Elts = DefaultEltPolicy<T> >
00245   class Sequence
00246     : public AllocPolicy<T, Sequence<T, Bounds, Elts>, Bounds>
00247     , public ::OpenDDS::DCPS::PoolAllocationBase {
00248   public:
00249     typedef seq_size_type size_type;  // from std C++ Container concept
00250     typedef seq_size_type _size_type; // from IDL-to-C++ specification
00251     typedef Elts ElementPolicy;
00252 
00253   protected:
00254     explicit Sequence(size_type maximum = 0, size_type length = 0,
00255                       T* data = 0, seq_flag_type release = false);
00256     Sequence(const Sequence& seq);
00257     ~Sequence();
00258     Sequence& operator=(const Sequence& seq);
00259 
00260     void swap(Sequence& rhs) throw();
00261   public:
00262     using AllocPolicy<T, Sequence, Bounds>::maximum;
00263     void length(size_type len);
00264     size_type length() const { return length_; }
00265 
00266     typedef typename Elts::Element Element;
00267     typedef typename Elts::ConstElement ConstElement;
00268     typedef typename Elts::ConstRawElement ConstRawElement;
00269 
00270     typedef ConstElement const_subscript_type; // sequence _var compatibility
00271     typedef Element subscript_type; // sequence _var compatibility
00272 
00273     ConstElement operator[](size_type idx) const;
00274     Element operator[](size_type idx);
00275 
00276     seq_flag_type release() const { return release_; }
00277 
00278     T* get_buffer(seq_flag_type orphan = false);
00279     const ConstRawElement* get_buffer() const;
00280 
00281     // allocbuf() inherited from AllocPolicy
00282     static void freebuf(T* data);
00283 
00284 
00285     // The public members below provide C++ standard library container
00286     // compatibility for convenience.
00287     // Iterators are always T* so be careful with string sequences,
00288     // the caller needs to use FACE::string_free() and FACE::string_alloc()
00289     // or FACE::string_dup() to replace a string in the sequence.
00290     // These are the same semantics as get_buffer(bool) in the IDL-to-C++
00291     // mapping.
00292 
00293     typedef T value_type;
00294     typedef T& reference;
00295     typedef const T& const_reference;
00296     typedef T* iterator;
00297     typedef const T* const_iterator;
00298     typedef std::ptrdiff_t difference_type;
00299 
00300     const T* begin() const { return buffer_; }
00301     T* begin() { return buffer_; }
00302 
00303     const T* end() const { return buffer_ + length_; }
00304     T* end() { return buffer_ + length_; }
00305 
00306     bool operator==(const Sequence& rhs) const;
00307     bool operator!=(const Sequence& rhs) const;
00308 
00309     size_type size() const { return length_; }
00310     // max_size() inherited from AllocPolicy
00311     bool empty() const { return !length_; }
00312 
00313 #ifndef __SUNPRO_CC
00314   private:
00315     friend struct AllocPolicy<T, Sequence, Bounds>;
00316 #endif
00317     void replace_i(size_type maximum, size_type length,
00318                    T* data, seq_flag_type release);
00319 
00320   private:
00321     using AllocPolicy<T, Sequence, Bounds>::allocate;
00322     void lazy_alloc() const;
00323 
00324     size_type length_;
00325     mutable seq_flag_type release_;
00326     mutable T* buffer_;
00327   };
00328 
00329 
00330   // Allocation Policies:
00331 
00332   template <typename T, typename Sequence, seq_size_type N>
00333   inline T* AllocPolicy<T, Sequence, Bounded<N> >::allocbuf()
00334   {
00335     void* const raw =
00336       ACE_Allocator::instance()->malloc(N * sizeof(T));
00337     T* const mem = static_cast<T*>(raw);
00338     Sequence::ElementPolicy::construct(mem, N, false);
00339     return mem;
00340   }
00341 
00342   template <typename T, typename Sequence>
00343   inline T* AllocPolicy<T, Sequence, Unbounded>::allocbuf(seq_size_type n)
00344   {
00345     const size_t bytes = (n + Sequence::ElementPolicy::extra) * sizeof(T);
00346     void* const raw = ACE_Allocator::instance()->malloc(bytes);
00347     T* const mem = static_cast<T*>(raw);
00348     Sequence::ElementPolicy::construct(mem, n, true);
00349     return mem + Sequence::ElementPolicy::extra;
00350   }
00351 
00352 
00353   // Default Element Policy:
00354 
00355   template <typename T>
00356   inline void DefaultEltPolicy<T>::copy_n(const T* in, seq_size_type n, T* out)
00357   {
00358     std::memcpy(out, in, n * sizeof(T));
00359   }
00360 
00361 
00362   // String Element Policy:
00363 
00364   template <typename CharT>
00365   inline void StringEltPolicy<CharT>::construct(CharT** buffer, seq_size_type n,
00366                                                 seq_flag_type use_cookie)
00367   {
00368     for (seq_size_type i = use_cookie; i < n + use_cookie; ++i) {
00369       buffer[i] = StringTraits<CharT>::empty();
00370     }
00371     if (use_cookie) {
00372       *reinterpret_cast<seq_size_type*>(buffer) = n;
00373     }
00374   }
00375 
00376   template <typename CharT>
00377   inline void StringEltPolicy<CharT>::copy_n(const CharT* const* in,
00378                                              seq_size_type n, CharT** out)
00379   {
00380     for (seq_size_type i = 0; i < n; ++i) {
00381       StringTraits<CharT>::free(out[i]);
00382       out[i] = StringTraits<CharT>::dup(in[i]);
00383     }
00384   }
00385 
00386   template <typename CharT>
00387   inline void StringEltPolicy<CharT>::move_n(CharT** in, seq_size_type n,
00388                                              CharT** out)
00389   {
00390     for (seq_size_type i = 0; i < n; ++i) {
00391       std::swap(in[i], out[i]);
00392     }
00393   }
00394 
00395   template <typename CharT>
00396   inline void StringEltPolicy<CharT>::reset_n(CharT** buffer, seq_size_type n)
00397   {
00398     for (seq_size_type i = 0; i < n; ++i) {
00399       StringTraits<CharT>::free(buffer[i]);
00400       buffer[i] = StringTraits<CharT>::empty();
00401     }
00402   }
00403 
00404   template <typename CharT>
00405   inline CharT** StringEltPolicy<CharT>::destroy(CharT** buffer,
00406                                                  seq_size_type n_or_int_max)
00407   {
00408     seq_size_type n = n_or_int_max;
00409     CharT** allocated = buffer;
00410 
00411     if (n_or_int_max == INT_MAX) {
00412       allocated = buffer - 1;
00413       n = *reinterpret_cast<seq_size_type*>(allocated);
00414     }
00415 
00416     for (seq_size_type i = 0; i < n; ++i) {
00417       StringTraits<CharT>::free(buffer[i]);
00418     }
00419 
00420     return allocated;
00421   }
00422 
00423 
00424   // Variable-length Element Policy:
00425 
00426   template <typename T>
00427   inline void VariEltPolicy<T>::construct(T* buffer, seq_size_type n,
00428                                           seq_flag_type use_cookie)
00429   {
00430     std::uninitialized_fill_n(buffer + use_cookie, n, T());
00431     if (use_cookie) {
00432       *reinterpret_cast<seq_size_type*>(buffer) = n;
00433     }
00434   }
00435 
00436   template <typename T>
00437   inline void VariEltPolicy<T>::copy_n(const T* in, seq_size_type n, T* out)
00438   {
00439     std::copy(in, in + n, out);
00440   }
00441 
00442   template <typename T>
00443   inline void VariEltPolicy<T>::move_n(T* in, seq_size_type n, T* out)
00444   {
00445     std::swap_ranges(in, in + n, out);
00446   }
00447 
00448   template <typename T>
00449   inline void VariEltPolicy<T>::reset_n(T* buffer, seq_size_type n)
00450   {
00451     std::fill_n(buffer, n, T());
00452   }
00453 
00454   template <typename T>
00455   inline T* VariEltPolicy<T>::destroy(T* buffer, seq_size_type n_or_int_max)
00456   {
00457     seq_size_type n = n_or_int_max;
00458     T* allocated = buffer;
00459 
00460     if (n_or_int_max == INT_MAX) {
00461       allocated = buffer - 1;
00462       n = *reinterpret_cast<seq_size_type*>(allocated);
00463     }
00464 
00465     for (seq_size_type i = 0; i < n; ++i) {
00466       buffer[i].~T();
00467     }
00468 
00469     return allocated;
00470   }
00471 
00472 
00473   // Array Element Policy:
00474 
00475   template <typename Forany, typename T>
00476   inline void ArrayEltPolicy<Forany, T>::construct(T* buffer,
00477                                                    seq_size_type n,
00478                                                    seq_flag_type use_cookie)
00479   {
00480     const seq_size_type start = use_cookie ? extra : 0;
00481     for (seq_size_type i = start; i < n + start; ++i) {
00482       TAO::Array_Traits<Forany>::construct(buffer[i]);
00483     }
00484     if (use_cookie) {
00485       *reinterpret_cast<seq_size_type*>(buffer) = n;
00486     }
00487   }
00488 
00489   template <typename Forany, typename T>
00490   inline void ArrayEltPolicy<Forany, T>::copy_n(const T* in, seq_size_type n,
00491                                                 T* out)
00492   {
00493     for (seq_size_type i = 0; i < n; ++i) {
00494       TAO::Array_Traits<Forany>::copy(out[i], in[i]);
00495     }
00496   }
00497 
00498   template <typename Forany, typename T>
00499   inline void ArrayEltPolicy<Forany, T>::reset_n(T* buffer, seq_size_type n)
00500   {
00501     for (seq_size_type i = 0; i < n; ++i) {
00502       TAO::Array_Traits<Forany>::zero(buffer[i]);
00503     }
00504   }
00505 
00506   template <typename Forany, typename T>
00507   inline T* ArrayEltPolicy<Forany, T>::destroy(T* buffer, seq_size_type n)
00508   {
00509     seq_size_type num = n;
00510     T* alloc = buffer;
00511 
00512     if (n == INT_MAX) {
00513       alloc = buffer - extra;
00514       num = *reinterpret_cast<seq_size_type*>(alloc);
00515     }
00516 
00517     for (seq_size_type i = 0; i < num; ++i) {
00518       TAO::Array_Traits<Forany>::destroy(buffer[i]);
00519     }
00520 
00521     return alloc;
00522   }
00523 
00524 
00525   // Members of the Sequence template itself:
00526 
00527   template <typename T, typename Bounds, typename Elts>
00528   inline Sequence<T, Bounds, Elts>::Sequence(size_type maximum,
00529                                              size_type length,
00530                                              T* data, seq_flag_type release)
00531     : AllocPolicy<T, Sequence, Bounds>(maximum)
00532     , length_(length)
00533     , release_(release)
00534     , buffer_(data)
00535   {
00536   }
00537 
00538   template <typename T, typename Bounds, typename Elts>
00539   inline Sequence<T, Bounds, Elts>::Sequence(const Sequence& seq)
00540     : AllocPolicy<T, Sequence, Bounds>(seq.maximum())
00541     , length_(seq.length_)
00542     , release_(true)
00543     , buffer_((seq.maximum() && seq.buffer_) ? allocate() : 0)
00544   {
00545     if (buffer_) {
00546       Elts::copy_n(seq.buffer_, length_, buffer_);
00547     }
00548   }
00549 
00550   template <typename T, typename Bounds, typename Elts>
00551   inline Sequence<T, Bounds, Elts>::~Sequence()
00552   {
00553     if (release_) {
00554       freebuf(buffer_);
00555     }
00556   }
00557 
00558   template <typename T, typename Bounds, typename Elts>
00559   inline Sequence<T, Bounds, Elts>&
00560   Sequence<T, Bounds, Elts>::operator=(const Sequence& seq)
00561   {
00562     Sequence cpy(seq);
00563     swap(cpy);
00564     return *this;
00565   }
00566 
00567   template <typename T, typename Bounds, typename Elts>
00568   inline void Sequence<T, Bounds, Elts>::swap(Sequence& rhs) throw()
00569   {
00570     AllocPolicy<T, Sequence, Bounds>::swap(rhs);
00571     std::swap(length_, rhs.length_);
00572     std::swap(release_, rhs.release_);
00573     std::swap(buffer_, rhs.buffer_);
00574   }
00575 
00576   template <typename T, typename Bounds, typename Elts>
00577   inline void Sequence<T, Bounds, Elts>::replace_i(size_type maximum,
00578                                                    size_type length, T* data,
00579                                                    seq_flag_type release)
00580   {
00581     Sequence tmp(maximum, length, data, release);
00582     swap(tmp);
00583   }
00584 
00585   template <typename T, typename Bounds, typename Elts>
00586   inline void Sequence<T, Bounds, Elts>::lazy_alloc() const
00587   {
00588     if (!buffer_) {
00589       buffer_ = allocate();
00590       release_ = true;
00591     }
00592   }
00593 
00594   template <typename T, typename Bounds, typename Elts>
00595   inline void Sequence<T, Bounds, Elts>::length(size_type len)
00596   {
00597     if (len <= maximum()) {
00598       if (len && !buffer_) {
00599         lazy_alloc();
00600       }
00601       else if (release_ && len < length_) {
00602         Elts::reset_n(buffer_ + len, length_ - len);
00603       }
00604       length_ = len;
00605       return;
00606     }
00607 
00608     Sequence tmp(len, len, allocate(len), true);
00609     Elts::move_n(buffer_, length_, tmp.buffer_);
00610     swap(tmp);
00611   }
00612 
00613   template <typename T, typename Bounds, typename Elts>
00614   inline typename Sequence<T, Bounds, Elts>::ConstElement
00615   Sequence<T, Bounds, Elts>::operator[](size_type idx) const
00616   {
00617     return buffer_[idx];
00618   }
00619 
00620   template <typename T, typename Bounds, typename Elts>
00621   inline typename Sequence<T, Bounds, Elts>::Element
00622   Sequence<T, Bounds, Elts>::operator[](size_type idx)
00623   {
00624     return Elts::make_element(buffer_[idx], release_);
00625   }
00626 
00627   template <typename T, typename Bounds, typename Elts>
00628   inline T* Sequence<T, Bounds, Elts>::get_buffer(seq_flag_type orphan)
00629   {
00630     if (orphan && !release_) {
00631       return 0;
00632     }
00633 
00634     lazy_alloc();
00635 
00636     if (orphan) {
00637       Sequence tmp;
00638       swap(tmp);
00639       tmp.release_ = false;
00640       return tmp.buffer_;
00641     }
00642 
00643     return buffer_;
00644   }
00645 
00646   template <typename T, typename Bounds, typename Elts>
00647   inline const typename Sequence<T, Bounds, Elts>::ConstRawElement*
00648   Sequence<T, Bounds, Elts>::get_buffer() const
00649   {
00650     lazy_alloc();
00651     return buffer_;
00652   }
00653 
00654   template <typename T, typename Bounds, typename Elts>
00655   inline void Sequence<T, Bounds, Elts>::freebuf(T* data)
00656   {
00657     if (!data) return;
00658     T* const allocated = Elts::destroy(data, Bounds::Bounds);
00659     ACE_Allocator::instance()->free(allocated);
00660   }
00661 
00662   template <typename T, typename Bounds, typename Elts>
00663   inline bool Sequence<T, Bounds, Elts>::operator==(const Sequence& rhs) const
00664   {
00665     const size_type sz = size();
00666     if (sz != rhs.size()) {
00667       return false;
00668     }
00669     for (size_type i = 0; i < sz; ++i) {
00670       if (!((*this)[i] == rhs[i])) {
00671         return false;
00672       }
00673     }
00674     return true;
00675   }
00676 
00677   template <typename T, typename Bounds, typename Elts>
00678   inline bool Sequence<T, Bounds, Elts>::operator!=(const Sequence& rhs) const
00679   {
00680     return !(*this == rhs);
00681   }
00682 }
00683 }
00684 
00685 #endif /* dds_DCPS_SafetyProfileSequence_h */

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