This is an automated email from the ASF dual-hosted git repository.

bneradt pushed a commit to branch stuff-1
in repository https://gitbox.apache.org/repos/asf/trafficserver-libswoc.git

commit 38e8c208ddf46a93655be1e2a188a2df83a695df
Author: Alan M. Carroll <[email protected]>
AuthorDate: Fri May 20 16:38:24 2022 -0500

    fix.
---
 code/include/swoc/Vectray.h | 65 +++++++++++++++++++++++++++++++++++++++++++--
 doc/code/Vectray.en.rst     | 14 +++++-----
 2 files changed, 71 insertions(+), 8 deletions(-)

diff --git a/code/include/swoc/Vectray.h b/code/include/swoc/Vectray.h
index a446880..42f7a37 100644
--- a/code/include/swoc/Vectray.h
+++ b/code/include/swoc/Vectray.h
@@ -1,3 +1,11 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright Apache Software Foundation 2019
+/** @file
+
+    Container that acts like a vector but has static storage to avoid memory 
allocation for
+    some specified number of elements.
+*/
+
 #pragma once
 
 #include <array>
@@ -32,13 +40,17 @@ class Vectray {
 
 public: // STL compliance types.
   using value_type = T;
+  using reference = std::remove_reference<T>&;
+  using const_reference = std::remove_reference<T> const&;
+  using pointer = std::remove_reference<T>*;
+  using const_pointer = std::remove_reference<T> const*;
   using allocator_type = A;
   using size_type = typename vector_type::size_type;
   using difference_type = typename vector_type::difference_type;
   using iterator = typename swoc::MemSpan<T>::iterator;
   using const_iterator = typename swoc::MemSpan<const T>::iterator;
+  // Need to add reverse iterators - @c reverse_iterator and @c 
const_reverse_iterator
 
-protected:
   /// Internal (fixed) storage.
   struct FixedStore {
     std::array<std::byte, sizeof(T) * N> _raw; ///< Raw memory for element 
storage.
@@ -57,6 +69,12 @@ protected:
 
     /// @return A span containing the valid elements.
     MemSpan<T> span();
+
+    /// @return A pointer to the data.
+    T * data();
+
+    /// @return A pointer to the data.
+    T const * data() const;
   };
 
   using DynamicStore = vector_type; ///< Dynamic (heap) storage.
@@ -90,6 +108,15 @@ public:
   /// @return The number of elements in the container.
   size_type size() const;
 
+  /// @return A pointer to the data.
+  T * data();
+
+  /// @return A pointer to the data.
+  T const * data() const;
+
+  /// @return @c true if no valid elements, @c false if at least one valid 
element.
+  bool empty() const;
+
   /// Implicitly convert to a @c MemSpan.
   operator span () { return this->items(); }
   /// Implicitly convert to a @c MemSpan.
@@ -237,6 +264,16 @@ MemSpan<T> Vectray<T, N, A>::FixedStore::span() {
   return MemSpan(_raw).template rebind<T>();
 }
 
+template<typename T, size_t N, class A>
+T * Vectray<T, N, A>::FixedStore::data() {
+  return reinterpret_cast<T*>(_raw.data());
+}
+
+template<typename T, size_t N, class A>
+T const * Vectray<T, N, A>::FixedStore::data() const {
+  return reinterpret_cast<T*>(_raw.data());
+}
+
 template<typename T, size_t N, typename A>
 T& Vectray<T,N,A>::operator[](size_type idx) {
   return this->items()[idx];
@@ -310,11 +347,19 @@ auto Vectray<T, N, A>::pop_back() -> self_type & {
 template<typename T, size_t N, typename A>
 auto Vectray<T,N,A>::size() const -> size_type {
   return std::visit(swoc::meta::vary{
-      [](FixedStore const& fs) { return fs._count; }
+        [](FixedStore const& fs) { return fs._count; }
       , [](DynamicStore const& ds) { return ds.size(); }
   }, _store);
 }
 
+template<typename T, size_t N, typename A>
+bool Vectray<T,N,A>::empty() const {
+  return std::visit(swoc::meta::vary{
+           [](FixedStore const& fs) { return fs._count > 0; }
+         , [](DynamicStore const& ds) { return ds.empty(); }
+         }, _store);
+}
+
 // --- iterators
 template<typename T, size_t N, typename A>
 auto  Vectray<T,N,A>::begin() const -> const_iterator { return 
this->items().begin(); }
@@ -349,6 +394,22 @@ auto Vectray<T, N, A>::items() const -> const_span {
   }, _store);
 }
 
+template<typename T, size_t N, class A>
+T * Vectray<T, N, A>::data() {
+  return std::visit(swoc::meta::vary{
+                      [](FixedStore const& fs) { fs.data(); }
+                      , [](DynamicStore const& ds) { return ds.data(); }
+                    }, _store);
+}
+
+template<typename T, size_t N, class A>
+T const * Vectray<T, N, A>::data() const {
+  return std::visit(swoc::meta::vary{
+                      [](FixedStore const& fs) { fs.data(); }
+                      , [](DynamicStore const& ds) { return ds.data(); }
+                    }, _store);
+}
+
 template<typename T, size_t N, class A>
 auto Vectray<T, N, A>::items() -> span {
   return std::visit(swoc::meta::vary{
diff --git a/doc/code/Vectray.en.rst b/doc/code/Vectray.en.rst
index 04f8f38..68e6908 100644
--- a/doc/code/Vectray.en.rst
+++ b/doc/code/Vectray.en.rst
@@ -24,11 +24,11 @@ Synopsis
 |V| is a class intended to replace :code:`std::vector` in situations where 
performance is critical.
 An instance of |V| contains a static array of size :arg:`N` which is used in 
preference to allocating
 memory. If the number of instances is generally less than :arg:`N` then no 
memory allocation /
-deallocation is done and the performance is as fast as a :code:`std::array`. 
Unlike an array if
+deallocation is done and the performance is as fast as a :code:`std::array`. 
Unlike an array, if
 the required memory exceeds the static limits the internal storage is changed 
to a :code:`std::vector`
-without data loss.
+without data loss. Another key difference is the number of valid elements in 
the container can vary.
 
-Performance gain from using this class depends on
+Performance gain from using this class depends upon
 
 *  The static limit :arg:`N` being relatively small to minimize fixed costs.
 *  Required storage usually fits within the static limits.
@@ -41,11 +41,13 @@ for a parameter) and only rarely longer. |V| can then 
significantly reduce memor
 cost.
 
 The second common use case is for stack buffers of moderate size, such as 
logging buffers. Generally
-these are selected to be large to enough to cover almost cases, except for the 
occasional truncation.
+these are selected to be large to enough to cover most cases, except for the 
occasional truncation.
 In this case |V| preserves the performance of the common case while providing 
an escape in the
 rare circumstance of exceeding the buffer size.
 
-As always, performance tuning is an art, not a science. Do not simply assume 
|V| is a better choice.
+As always, performance tuning is an art, not a science. Do not simply assume 
|V| is a better choice
+and use it to replace `std::vector` or `std::array` in general. Use where it 
looks helpful and do
+measurements to verify.
 
 Usage
 *****
@@ -60,5 +62,5 @@ The static elements are not default constructed, but are 
constructed as needed.
 Allocator
 =========
 
-Generally this should be defaulted, but is provided so a polymorphic memory 
resource based
+Generally this should be defaulted, but is exposed so a polymorphic memory 
resource based
 allocator can be used when needed.

Reply via email to