[Groonga-commit] groonga/grnxx at 891c250 [master] Add an implementation of grnxx::alpha::Array<bool>.

Back to archive index

susumu.yata null+****@clear*****
Tue Jul 16 13:22:32 JST 2013


susumu.yata	2013-07-16 13:22:32 +0900 (Tue, 16 Jul 2013)

  New Revision: 891c250ef849dec00490a99ad7d5b8ffc0da2b3c
  https://github.com/groonga/grnxx/commit/891c250ef849dec00490a99ad7d5b8ffc0da2b3c

  Message:
    Add an implementation of grnxx::alpha::Array<bool>.

  Modified files:
    lib/grnxx/array2.hpp
    lib/grnxx/array2_impl.hpp

  Modified: lib/grnxx/array2.hpp (+14 -15)
===================================================================
--- lib/grnxx/array2.hpp    2013-07-16 11:21:01 +0900 (b939a2b)
+++ lib/grnxx/array2.hpp    2013-07-16 13:22:32 +0900 (4254ef2)
@@ -38,19 +38,13 @@ struct ArrayErrorHandler {
 
 template <typename T, uint64_t PAGE_SIZE = 0, uint64_t TABLE_SIZE = 0>
 class Array {
-  // Test template parameters.
-  static_assert((PAGE_SIZE != 0) || (TABLE_SIZE == 0),
-                "TABLE_SIZE must be zero if PAGE_SIZE is zero");
-  static_assert((PAGE_SIZE & (PAGE_SIZE - 1)) == 0,
-                "PAGE_SIZE must be zero or a power of two");
-  static_assert((TABLE_SIZE & (TABLE_SIZE - 1)) == 0,
-                "TABLE_SIZE must be zero or a power of two");
-
   using Impl = ArrayImpl<T, PAGE_SIZE, TABLE_SIZE>;
 
  public:
-  using Value = typename Impl::Value;
+  using Value    = typename Impl::Value;
   using ValueArg = typename Impl::ValueArg;
+  using ValueRef = typename Impl::ValueRef;
+  using Unit     = typename Impl::Unit;
 
   ~Array() {}
 
@@ -90,17 +84,22 @@ class Array {
     return impl_.size();
   }
 
-  // Get a reference to a value.
-  Value &operator[](uint64_t value_id) {
-    return *impl_.get_value(value_id);
-  }
   // Get a value.
   Value get(uint64_t value_id) {
-    return *impl_.get_value(value_id);
+    return get_value(value_id);
   }
   // Set a value.
   void set(uint64_t value_id, ValueArg value) {
-    *impl_.get_value(value_id) = value;
+    get_value(value_id) = value;
+  }
+
+  // Get a reference to a value.
+  ValueRef get_value(uint64_t value_id) {
+    return impl_.get_value(value_id);
+  }
+  // Get a reference to a unit.
+  Unit &get_unit(uint64_t unit_id) {
+    return impl_.get_unit(unit_id);
   }
 
  private:

  Modified: lib/grnxx/array2_impl.hpp (+144 -12)
===================================================================
--- lib/grnxx/array2_impl.hpp    2013-07-16 11:21:01 +0900 (0850ef1)
+++ lib/grnxx/array2_impl.hpp    2013-07-16 13:22:32 +0900 (1d8804d)
@@ -67,10 +67,10 @@ class Array1D {
     return size_;
   }
 
-  // Return a pointer to a value.
+  // Return a reference to a value.
   template <typename T, uint64_t, uint64_t>
-  T *get_value(uint64_t value_id) {
-    return &static_cast<T *>(page_)[value_id];
+  T &get_value(uint64_t value_id) {
+    return static_cast<T *>(page_)[value_id];
   }
 
  private:
@@ -108,14 +108,14 @@ class Array2D {
     return size_;
   }
 
-  // Return a pointer to a value.
+  // Return a reference to a value.
   template <typename T, uint64_t PAGE_SIZE, uint64_t TABLE_SIZE>
-  T *get_value(uint64_t value_id) {
+  T &get_value(uint64_t value_id) {
     const uint64_t page_id = value_id / PAGE_SIZE;
     if (pages_[page_id] == invalid_page()) {
       reserve_page(page_id);
     }
-    return &static_cast<T *>(pages_[page_id])[value_id];
+    return static_cast<T *>(pages_[page_id])[value_id];
   }
 
  private:
@@ -170,15 +170,15 @@ class Array3D {
     return size_;
   }
 
-  // Return a pointer to a value.
+  // Return a reference to a value.
   template <typename T, uint64_t PAGE_SIZE, uint64_t TABLE_SIZE>
-  T *get_value(uint64_t value_id) {
+  T &get_value(uint64_t value_id) {
     const uint64_t table_id = value_id / (PAGE_SIZE * TABLE_SIZE);
     const uint64_t page_id = value_id / PAGE_SIZE;
     if (tables_[table_id][page_id] == invalid_page()) {
       reserve_page(page_id);
     }
-    return &static_cast<T *>(tables_[table_id][page_id])[value_id];
+    return static_cast<T *>(tables_[table_id][page_id])[value_id];
   }
 
   // Return a pointer to an invalid page.
@@ -240,11 +240,21 @@ struct ArrayPageFiller {
 
 template <typename T, uint64_t PAGE_SIZE, uint64_t TABLE_SIZE>
 class ArrayImpl {
+  // Test template parameters.
+  static_assert((PAGE_SIZE != 0) || (TABLE_SIZE == 0),
+                "TABLE_SIZE must be zero if PAGE_SIZE is zero");
+  static_assert((PAGE_SIZE & (PAGE_SIZE - 1)) == 0,
+                "PAGE_SIZE must be zero or a power of two");
+  static_assert((TABLE_SIZE & (TABLE_SIZE - 1)) == 0,
+                "TABLE_SIZE must be zero or a power of two");
+
   using Impl = typename ArrayImplSelector<PAGE_SIZE, TABLE_SIZE>::Type;
 
  public:
-  using Value = typename Traits<T>::Type;
+  using Value    = typename Traits<T>::Type;
   using ValueArg = typename Traits<T>::ArgumentType;
+  using ValueRef = Value &;
+  using Unit     = Value;
 
   ArrayImpl() : impl_() {}
   ~ArrayImpl() {}
@@ -284,10 +294,132 @@ class ArrayImpl {
     return impl_.size();
   }
 
-  // Return a pointer to a value.
-  Value *get_value(uint64_t value_id) {
+  // Return a reference to a value.
+  ValueRef get_value(uint64_t value_id) {
     return impl_. template get_value<Value, PAGE_SIZE, TABLE_SIZE>(value_id);
   }
+  // Return a reference to a unit.
+  Unit &get_unit(uint64_t unit_id) {
+    return get_value(unit_id);
+  }
+
+ private:
+  Impl impl_;
+};
+
+// A reference to a bit.
+class ArrayBitRef {
+ public:
+  using Unit = uint64_t;
+
+  // Create a reference to a bit.
+  ArrayBitRef(Unit &unit, Unit mask) : unit_(unit), mask_(mask) {}
+
+  // Get a bit.
+  operator bool() const {
+    return (unit_ & mask_) != 0;
+  }
+
+  // Set a bit.
+  ArrayBitRef &operator=(bool value) {
+    if (value) {
+      unit_ |= mask_;
+    } else {
+      unit_ &= ~mask_;
+    }
+    return *this;
+  }
+
+  // Copy a bit.
+  ArrayBitRef &operator=(const ArrayBitRef &rhs) {
+    return *this = bool(rhs);
+  }
+
+  // Compare bits.
+  bool operator==(bool rhs) const {
+    return bool(*this) == rhs;
+  }
+  bool operator!=(bool rhs) const {
+    return bool(*this) != rhs;
+  }
+
+ private:
+  Unit &unit_;
+  Unit mask_;
+};
+
+// An array of bits.
+template <uint64_t PAGE_SIZE_IN_BITS, uint64_t TABLE_SIZE>
+class ArrayImpl<bool, PAGE_SIZE_IN_BITS, TABLE_SIZE> {
+  static constexpr uint64_t UNIT_SIZE = sizeof(ArrayBitRef::Unit) * 8;
+  static constexpr uint64_t PAGE_SIZE = PAGE_SIZE_IN_BITS / UNIT_SIZE;
+
+  // Test template parameters.
+  static_assert((PAGE_SIZE_IN_BITS % UNIT_SIZE) == 0,
+                "(PAGE_SIZE_IN_BITS % UNIT_SIZE) != 0");
+  static_assert((PAGE_SIZE != 0) || (TABLE_SIZE == 0),
+                "TABLE_SIZE must be zero if PAGE_SIZE is zero");
+  static_assert((PAGE_SIZE & (PAGE_SIZE - 1)) == 0,
+                "PAGE_SIZE must be zero or a power of two");
+  static_assert((TABLE_SIZE & (TABLE_SIZE - 1)) == 0,
+                "TABLE_SIZE must be zero or a power of two");
+
+  using Impl = typename ArrayImplSelector<PAGE_SIZE, TABLE_SIZE>::Type;
+
+ public:
+  using Value    = typename Traits<bool>::Type;
+  using ValueArg = typename Traits<bool>::ArgumentType;
+  using ValueRef = ArrayBitRef;
+  using Unit     = ArrayBitRef::Unit;
+
+  ArrayImpl() : impl_() {}
+  ~ArrayImpl() {}
+
+  // Create an array.
+  void create(Storage *storage, uint32_t storage_node_id, uint64_t size) {
+    impl_.create(storage, storage_node_id,
+                 sizeof(Unit), PAGE_SIZE, TABLE_SIZE, size / UNIT_SIZE,
+                 nullptr, ArrayPageFiller<Unit>::fill_page);
+  }
+  // Create an array with the default value.
+  void create(Storage *storage, uint32_t storage_node_id, uint64_t size,
+              ValueArg default_value) {
+    const Unit default_unit = default_value ? ~(Unit)0 : (Unit)0;
+    impl_.create(storage, storage_node_id,
+                 sizeof(Unit), PAGE_SIZE, TABLE_SIZE, size / UNIT_SIZE,
+                 &default_unit, ArrayPageFiller<Unit>::fill_page);
+  }
+  // Open an array.
+  void open(Storage *storage, uint32_t storage_node_id) {
+    impl_.open(storage, storage_node_id,
+               sizeof(Unit), PAGE_SIZE, TABLE_SIZE,
+               ArrayPageFiller<Unit>::fill_page);
+  }
+
+  // Unlink an array.
+  static void unlink(Storage *storage, uint32_t storage_node_id) {
+    Impl::unlink(storage, storage_node_id,
+                 sizeof(Unit), PAGE_SIZE, TABLE_SIZE);
+  }
+
+  // Return the storage node ID.
+  uint32_t storage_node_id() const {
+    return impl_.storage_node_id();
+  }
+  // Return the number of values.
+  uint64_t size() const {
+    return impl_.size() * UNIT_SIZE;
+  }
+
+  // Return a reference to a value.
+  ValueRef get_value(uint64_t value_id) {
+    return ValueRef(get_unit(value_id / UNIT_SIZE),
+                    Unit(1) << (value_id % UNIT_SIZE));
+  }
+  // Return a reference to a unit.
+  Unit &get_unit(uint64_t unit_id) {
+    return impl_. template get_value<Unit, PAGE_SIZE, TABLE_SIZE>(unit_id);
+  }
 
  private:
   Impl impl_;
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index