[Groonga-commit] groonga/grnxx at 4707a8a [master] Add grnxx::Array<bool>.

アーカイブの一覧に戻る

susumu.yata null+****@clear*****
Wed May 29 12:49:14 JST 2013


susumu.yata	2013-05-29 12:49:14 +0900 (Wed, 29 May 2013)

  New Revision: 4707a8adb6aaacc3fee9b2095d8357d3b5b5114f
  https://github.com/groonga/grnxx/commit/4707a8adb6aaacc3fee9b2095d8357d3b5b5114f

  Message:
    Add grnxx::Array<bool>.

  Modified files:
    lib/grnxx/array.hpp

  Modified: lib/grnxx/array.hpp (+153 -0)
===================================================================
--- lib/grnxx/array.hpp    2013-05-29 11:45:43 +0900 (a23ebdb)
+++ lib/grnxx/array.hpp    2013-05-29 12:49:14 +0900 (6eaff94)
@@ -26,6 +26,7 @@
 
 #include "grnxx/array_impl.hpp"
 #include "grnxx/logger.hpp"
+#include "grnxx/traits.hpp"
 #include "grnxx/types.hpp"
 
 namespace grnxx {
@@ -155,6 +156,158 @@ class Array {
   }
 };
 
+// Bit array.
+template <uint64_t PAGE_SIZE_IN_BITS,
+          uint64_t TABLE_SIZE,
+          uint64_t SECONDARY_TABLE_SIZE>
+class Array<bool, PAGE_SIZE_IN_BITS, TABLE_SIZE, SECONDARY_TABLE_SIZE> {
+ public:
+  // Internal type to store bits.
+  using Unit = uint64_t;
+
+ private:
+  static constexpr uint64_t UNIT_SIZE = sizeof(Unit) * 8;
+  static constexpr uint64_t PAGE_SIZE = PAGE_SIZE_IN_BITS / UNIT_SIZE;
+
+  static_assert((PAGE_SIZE_IN_BITS % UNIT_SIZE) == 0,
+                "(PAGE_SIZE_IN_BITS % UNIT_SIZE) != 0");
+  using ArrayImpl = ArrayImpl<Unit, PAGE_SIZE, TABLE_SIZE,
+                              SECONDARY_TABLE_SIZE>;
+
+ public:
+  using Value = typename Traits<bool>::Type;
+  using ValueArg = typename Traits<bool>::ArgumentType;
+
+  ~Array() {}
+
+  // Create an array.
+  static Array *create(Storage *storage, uint32_t storage_node_id) {
+    std::unique_ptr<Array> array(create_instance());
+    if (!array) {
+      return nullptr;
+    }
+    if (!array->impl_.create(storage, storage_node_id)) {
+      return nullptr;
+    }
+    return array.release();
+  }
+
+  // Create an array with the default value.
+  static Array *create(Storage *storage, uint32_t storage_node_id,
+                       ValueArg default_value) {
+    std::unique_ptr<Array> array(create_instance());
+    if (!array) {
+      return nullptr;
+    }
+    if (!array->impl_.create(storage, storage_node_id,
+                             default_value ? ~Unit(0) : Unit(0))) {
+      return nullptr;
+    }
+    return array.release();
+  }
+
+  // Open an array.
+  static Array *open(Storage *storage, uint32_t storage_node_id) {
+    std::unique_ptr<Array> array(create_instance());
+    if (!array) {
+      return nullptr;
+    }
+    if (!array->impl_.open(storage, storage_node_id)) {
+      return nullptr;
+    }
+    return array.release();
+  }
+
+  // Unlink an array.
+  static bool unlink(Storage *storage, uint32_t storage_node_id) {
+    return ArrayImpl::unlink(storage, storage_node_id);
+  }
+
+  // Return the number of values in each unit.
+  static constexpr uint64_t unit_size() {
+    return UNIT_SIZE;
+  }
+  // Return the number of values in each page.
+  static constexpr uint64_t page_size() {
+    return PAGE_SIZE_IN_BITS;
+  }
+  // Return the number of pages in each table.
+  static constexpr uint64_t table_size() {
+    return TABLE_SIZE;
+  }
+  // Return the number of tables in each secondary table.
+  static constexpr uint64_t secondary_table_size() {
+    return SECONDARY_TABLE_SIZE;
+  }
+  // Return the number of values in Array.
+  static constexpr uint64_t size() {
+    return page_size() * table_size() * secondary_table_size();
+  }
+
+  // Return the storage node ID.
+  uint32_t storage_node_id() const {
+    return impl_.storage_node_id();
+  }
+
+  // Get a value and return true on success.
+  // The value is assigned to "*value" iff "value" != nullptr.
+  bool get(uint64_t value_id, Value *value) {
+    const uint64_t unit_id = value_id / UNIT_SIZE;
+    const Unit * const page = get_page(unit_id / PAGE_SIZE);
+    if (!page) {
+      return false;
+    }
+    if (value) {
+      *value = (page[unit_id % PAGE_SIZE] &
+                (Unit(1) << (value_id % UNIT_SIZE))) != 0;
+    }
+    return true;
+  }
+
+  // Set a value and return true on success.
+  // Note that if bits in the same byte are set at the same time, the result is
+  // undefined.
+  bool set(uint64_t value_id, ValueArg value) {
+    const uint64_t unit_id = value_id / UNIT_SIZE;
+    Unit * const page = get_page(unit_id / PAGE_SIZE);
+    if (!page) {
+      return false;
+    }
+    if (value) {
+      page[unit_id % PAGE_SIZE] |= Unit(1) << (value_id % UNIT_SIZE);
+    } else {
+      page[unit_id % PAGE_SIZE] &= ~(Unit(1) << (value_id % UNIT_SIZE));
+    }
+    return true;
+  }
+
+  // Get a unit and return its address on success.
+  Unit *get_unit(uint64_t unit_id) {
+    return impl_.get_pointer(unit_id);
+  }
+  // Get a page and return its starting address on success.
+  Unit *get_page(uint64_t page_id) {
+    return impl_.get_page(page_id);
+  }
+
+ private:
+  ArrayImpl impl_;
+
+  Array() : impl_() {}
+
+  static Array *create_instance() {
+    Array * const array = new (std::nothrow) Array;
+    if (!array) {
+      GRNXX_ERROR() << "new grnxx::Array failed: "
+                    << "value_size = " << sizeof(Value)
+                    << ", page_size = " << PAGE_SIZE
+                    << ", table_size = " << TABLE_SIZE
+                    << ", secondary_table_size = " << SECONDARY_TABLE_SIZE;
+    }
+    return array;
+  }
+};
+
 }  // namespace grnxx
 
 #endif  // GRNXX_ARRAY_HPP
-------------- next part --------------
HTML����������������������������...
ダウンロード 



More information about the Groonga-commit mailing list
アーカイブの一覧に戻る