You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datasketches.apache.org by al...@apache.org on 2019/07/25 19:51:09 UTC

[incubator-datasketches-cpp] branch kll_no_default_construction updated: always use given allocator

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

alsay pushed a commit to branch kll_no_default_construction
in repository https://gitbox.apache.org/repos/asf/incubator-datasketches-cpp.git


The following commit(s) were added to refs/heads/kll_no_default_construction by this push:
     new b801445  always use given allocator
b801445 is described below

commit b80144519fafdfe281773a284e0fc091f4043006
Author: AlexanderSaydakov <Al...@users.noreply.github.com>
AuthorDate: Thu Jul 25 12:51:00 2019 -0700

    always use given allocator
---
 kll/include/kll_sketch.hpp | 63 +++++++++++++++++++++++++---------------------
 1 file changed, 35 insertions(+), 28 deletions(-)

diff --git a/kll/include/kll_sketch.hpp b/kll/include/kll_sketch.hpp
index 13fd1e5..61e403b 100644
--- a/kll/include/kll_sketch.hpp
+++ b/kll/include/kll_sketch.hpp
@@ -171,10 +171,10 @@ class kll_sketch {
     T get_min_value() const;
     T get_max_value() const;
     T get_quantile(double fraction) const;
-    std::unique_ptr<T[]> get_quantiles(const double* fractions, uint32_t size) const;
+    std::unique_ptr<T[], std::function<void(T*)>> get_quantiles(const double* fractions, uint32_t size) const;
     double get_rank(const T& value) const;
-    std::unique_ptr<double[]> get_PMF(const T* split_points, uint32_t size) const;
-    std::unique_ptr<double[]> get_CDF(const T* split_points, uint32_t size) const;
+    std::unique_ptr<double[], std::function<void(double*)>> get_PMF(const T* split_points, uint32_t size) const;
+    std::unique_ptr<double[], std::function<void(double*)>> get_CDF(const T* split_points, uint32_t size) const;
     double get_normalized_rank_error(bool pmf) const;
 
     // implementation for fixed-size arithmetic types (integral and floating point)
@@ -290,8 +290,8 @@ class kll_sketch {
     uint8_t find_level_to_compact() const;
     void add_empty_top_level_to_completely_full_sketch();
     void sort_level_zero();
-    std::unique_ptr<kll_quantile_calculator<T, C, A>> get_quantile_calculator();
-    std::unique_ptr<double[]> get_PMF_or_CDF(const T* split_points, uint32_t size, bool is_CDF) const;
+    std::unique_ptr<kll_quantile_calculator<T, C, A>, std::function<void(kll_quantile_calculator<T, C, A>*)>> get_quantile_calculator();
+    std::unique_ptr<double[], std::function<void(double*)>> get_PMF_or_CDF(const T* split_points, uint32_t size, bool is_CDF) const;
     void increment_buckets_unsorted_level(uint32_t from_index, uint32_t to_index, uint64_t weight,
         const T* split_points, uint32_t size, double* buckets) const;
     void increment_buckets_sorted_level(uint32_t from_index, uint32_t to_index, uint64_t weight,
@@ -512,23 +512,29 @@ T kll_sketch<T, C, S, A>::get_quantile(double fraction) const {
 }
 
 template<typename T, typename C, typename S, typename A>
-std::unique_ptr<T[]> kll_sketch<T, C, S, A>::get_quantiles(const double* fractions, uint32_t size) const {
-  if (is_empty()) { return nullptr; }
-  std::unique_ptr<kll_quantile_calculator<T, C, A>> quantile_calculator;
-  std::unique_ptr<T[]> quantiles(new T[size]);
+std::unique_ptr<T[], std::function<void(T*)>> kll_sketch<T, C, S, A>::get_quantiles(const double* fractions, uint32_t size) const {
+  if (is_empty()) return std::unique_ptr<T[], std::function<void(T*)>>();
+  std::unique_ptr<kll_quantile_calculator<T, C, A>, std::function<void(kll_quantile_calculator<T, C, A>*)>> quantile_calculator;
+  std::unique_ptr<T[], std::function<void(T*)>> quantiles(
+    A().allocate(size),
+    [size](T* ptr){
+      for (uint32_t i = 0; i < size; i++) ptr[i].~T();
+      A().deallocate(ptr, size);
+    }
+  );
   for (uint32_t i = 0; i < size; i++) {
     const double fraction = fractions[i];
     if ((fraction < 0.0) or (fraction > 1.0)) {
       throw std::invalid_argument("Fraction cannot be less than zero or greater than 1.0");
     }
-    if      (fraction == 0.0) quantiles[i] = *min_value_;
-    else if (fraction == 1.0) quantiles[i] = *max_value_;
+    if      (fraction == 0.0) new (&quantiles[i]) T(*min_value_);
+    else if (fraction == 1.0) new (&quantiles[i]) T(*max_value_);
     else {
       if (!quantile_calculator) {
         // has side effect of sorting level zero if needed
         quantile_calculator = const_cast<kll_sketch*>(this)->get_quantile_calculator();
       }
-      quantiles[i] = quantile_calculator->get_quantile(fraction);
+      new (&quantiles[i]) T(quantile_calculator->get_quantile(fraction));
     }
   }
   return std::move(quantiles);
@@ -557,12 +563,12 @@ double kll_sketch<T, C, S, A>::get_rank(const T& value) const {
 }
 
 template<typename T, typename C, typename S, typename A>
-std::unique_ptr<double[]> kll_sketch<T, C, S, A>::get_PMF(const T* split_points, uint32_t size) const {
+std::unique_ptr<double[], std::function<void(double*)>> kll_sketch<T, C, S, A>::get_PMF(const T* split_points, uint32_t size) const {
   return get_PMF_or_CDF(split_points, size, false);
 }
 
 template<typename T, typename C, typename S, typename A>
-std::unique_ptr<double[]> kll_sketch<T, C, S, A>::get_CDF(const T* split_points, uint32_t size) const {
+std::unique_ptr<double[], std::function<void(double*)>> kll_sketch<T, C, S, A>::get_CDF(const T* split_points, uint32_t size) const {
   return get_PMF_or_CDF(split_points, size, true);
 }
 
@@ -608,10 +614,9 @@ std::pair<void_ptr_with_deleter, const size_t> kll_sketch<T, C, S, A>::serialize
   const bool is_single_item = n_ == 1;
   const size_t size = header_size_bytes + get_serialized_size_bytes();
   typedef typename A::template rebind<char>::other AllocChar;
-  AllocChar allocator;
   void_ptr_with_deleter data_ptr(
-    static_cast<void*>(allocator.allocate(size)),
-    [size](void* ptr) { AllocChar allocator; allocator.deallocate(static_cast<char*>(ptr), size); }
+    static_cast<void*>(AllocChar().allocate(size)),
+    [size](void* ptr) { AllocChar().deallocate(static_cast<char*>(ptr), size); }
   );
   char* ptr = static_cast<char*>(data_ptr.get()) + header_size_bytes;
   const uint8_t preamble_ints(is_empty() or is_single_item ? PREAMBLE_INTS_SHORT : PREAMBLE_INTS_FULL);
@@ -901,10 +906,7 @@ void kll_sketch<T, C, S, A>::add_empty_top_level_to_completely_full_sketch() {
 
   // move (and shift) the current data into the new buffer
   T* new_buf = A().allocate(new_total_cap);
-  for (uint32_t i = 0; i < cur_total_cap; i++) {
-    new (&new_buf[i + delta_cap]) T(std::move(items_[i]));
-    items_[i].~T();
-  }
+  kll_helper::move_construct<T>(items_, 0, cur_total_cap, new_buf, delta_cap, true);
   A().deallocate(items_, items_size_);
   items_ = new_buf;
   items_size_ = new_total_cap;
@@ -929,18 +931,24 @@ void kll_sketch<T, C, S, A>::sort_level_zero() {
 }
 
 template<typename T, typename C, typename S, typename A>
-std::unique_ptr<kll_quantile_calculator<T, C, A>> kll_sketch<T, C, S, A>::get_quantile_calculator() {
+std::unique_ptr<kll_quantile_calculator<T, C, A>, std::function<void(kll_quantile_calculator<T, C, A>*)>> kll_sketch<T, C, S, A>::get_quantile_calculator() {
   sort_level_zero();
-  std::unique_ptr<kll_quantile_calculator<T, C, A>> quantile_calculator(new kll_quantile_calculator<T, C, A>(items_, levels_, num_levels_, n_));
+  typedef typename std::allocator_traits<A>::template rebind_alloc<kll_quantile_calculator<T, C, A>> AllocCalc;
+  std::unique_ptr<kll_quantile_calculator<T, C, A>, std::function<void(kll_quantile_calculator<T, C, A>*)>> quantile_calculator(
+    new (AllocCalc().allocate(1)) kll_quantile_calculator<T, C, A>(items_, levels_, num_levels_, n_),
+    [](kll_quantile_calculator<T, C, A>* ptr){ ptr->~kll_quantile_calculator<T, C, A>(); AllocCalc().deallocate(ptr, 1); }
+  );
   return std::move(quantile_calculator);
 }
 
 template<typename T, typename C, typename S, typename A>
-std::unique_ptr<double[]> kll_sketch<T, C, S, A>::get_PMF_or_CDF(const T* split_points, uint32_t size, bool is_CDF) const {
+std::unique_ptr<double[], std::function<void(double*)>> kll_sketch<T, C, S, A>::get_PMF_or_CDF(const T* split_points, uint32_t size, bool is_CDF) const {
   if (is_empty()) return nullptr;
   kll_helper::validate_values<T, C>(split_points, size);
-  std::unique_ptr<double[]> buckets(new double[size + 1]);
-  std::fill(&buckets.get()[0], &buckets.get()[size + 1], 0);
+  typedef typename std::allocator_traits<A>::template rebind_alloc<double> AllocD;
+  const size_t array_size = size + 1;
+  std::unique_ptr<double[], std::function<void(double*)>> buckets(AllocD().allocate(size + 1), [array_size](double* ptr){ AllocD().deallocate(ptr, array_size); });
+  std::fill(&buckets.get()[0], &buckets.get()[array_size], 0);
   uint8_t level(0);
   uint64_t weight(1);
   while (level < num_levels_) {
@@ -1009,7 +1017,7 @@ void kll_sketch<T, C, S, A>::increment_buckets_sorted_level(uint32_t from_index,
 template<typename T, typename C, typename S, typename A>
 void kll_sketch<T, C, S, A>::merge_higher_levels(const kll_sketch& other, uint64_t final_n) {
   const uint32_t tmp_num_items = get_num_retained() + other.get_num_retained_above_level_zero();
-  auto tmp_items_deleter = [tmp_num_items](T* ptr) { A().deallocate(ptr, tmp_num_items); };
+  auto tmp_items_deleter = [tmp_num_items](T* ptr) { A().deallocate(ptr, tmp_num_items); }; // no destructor needed
   const std::unique_ptr<T, decltype(tmp_items_deleter)> workbuf(A().allocate(tmp_num_items), tmp_items_deleter);
   const uint8_t ub = kll_helper::ub_on_num_levels(final_n);
   const size_t work_levels_size = ub + 2; // ub+1 does not work
@@ -1029,7 +1037,6 @@ void kll_sketch<T, C, S, A>::merge_higher_levels(const kll_sketch& other, uint64
 
   // now we need to transfer the results back into "this" sketch
   if (result.final_capacity != items_size_) {
-    for (unsigned i = 0; i < items_size_; i++) A().destroy(&items_[i]);
     A().deallocate(items_, items_size_);
     items_size_ = result.final_capacity;
     items_ = A().allocate(items_size_);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datasketches.apache.org
For additional commands, e-mail: commits-help@datasketches.apache.org