]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common: replace BitVector::NoInitAllocator with wrapper struct 45031/head
authorCasey Bodley <cbodley@redhat.com>
Tue, 15 Feb 2022 23:27:10 +0000 (18:27 -0500)
committerCasey Bodley <cbodley@redhat.com>
Wed, 16 Feb 2022 13:26:44 +0000 (08:26 -0500)
in c++20, the deprecated `struct std::allocator<T>::rebind` template was
removed, so `BitVector` no longer compiles. without a `rebind` to
inherit, `std::allocator_traits<NoInitAllocator>::rebind_alloc<U>` was
looking for `NoInitAllocator<U>`, but it isn't a template class

further investigation found that in c++17, `vector<__u32, NoInitAllocator>`
was rebinding this `NoInitAllocator` to `std::allocator<__u32>` and
preventing the no-init optimization from taking effect

instead of messing with the allocator to avoid zero-initialization, wrap
each __u32 in a struct whose constructor does not initialize the value

Fixes: https://tracker.ceph.com/issues/54279
Signed-off-by: Casey Bodley <cbodley@redhat.com>
src/common/bit_vector.hpp

index 10ee6c3ed6ccda73c7feba999aaba6318517f239..9ce3e8b1ebb2320754b76c84c4619d157373e49d 100644 (file)
@@ -223,23 +223,18 @@ public:
 
   static void generate_test_instances(std::list<BitVector *> &o);
 private:
-  struct NoInitAllocator : public std::allocator<__u32> {
-    NoInitAllocator() {}
-    NoInitAllocator(const std::allocator<__u32>& alloc)
-      : std::allocator<__u32>(alloc) {
-    }
-
-    template <class U, class... Args>
-    void construct(U* p, Args&&... args) const {
-    }
-  };
-
   bufferlist m_data;
   uint64_t m_size;
   bool m_crc_enabled;
 
   mutable __u32 m_header_crc;
-  mutable std::vector<__u32, NoInitAllocator> m_data_crcs;
+
+  // inhibit value-initialization when used in std::vector
+  struct u32_struct {
+    u32_struct() {}
+    __u32 val;
+  };
+  mutable std::vector<u32_struct> m_data_crcs;
 
   void resize(uint64_t elements, bool zero);
 
@@ -351,7 +346,7 @@ void BitVector<_b>::encode_data(bufferlist& bl, uint64_t data_byte_offset,
 
     bufferlist bit;
     bit.substr_of(m_data, data_byte_offset, len);
-    m_data_crcs[data_byte_offset / BLOCK_SIZE] = bit.crc32c(0);
+    m_data_crcs[data_byte_offset / BLOCK_SIZE].val = bit.crc32c(0);
 
     bl.claim_append(bit);
     data_byte_offset += BLOCK_SIZE;
@@ -385,7 +380,7 @@ void BitVector<_b>::decode_data(bufferlist::const_iterator& it,
     bufferlist bit;
     bit.append(ptr);
     if (m_crc_enabled &&
-       m_data_crcs[data_byte_offset / BLOCK_SIZE] != bit.crc32c(0)) {
+       m_data_crcs[data_byte_offset / BLOCK_SIZE].val != bit.crc32c(0)) {
       throw buffer::malformed_input("invalid data block CRC");
     }
     data.append(bit);
@@ -499,7 +494,7 @@ void BitVector<_b>::encode_data_crcs(bufferlist& bl, uint64_t offset,
   compute_index(offset + length - 1, &index, &shift);
   uint64_t end_crc_index = index / BLOCK_SIZE;
   while (crc_index <= end_crc_index) {
-    __u32 crc = m_data_crcs[crc_index++];
+    __u32 crc = m_data_crcs[crc_index++].val;
     ceph::encode(crc, bl);
   }
 }
@@ -520,7 +515,7 @@ void BitVector<_b>::decode_data_crcs(bufferlist::const_iterator& it,
   while (remaining > 0) {
     __u32 crc;
     ceph::decode(crc, it);
-    m_data_crcs[crc_index++] = crc;
+    m_data_crcs[crc_index++].val = crc;
     --remaining;
   }
 }