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

wwbmmm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brpc.git


The following commit(s) were added to refs/heads/master by this push:
     new c727dd77 Use ManualConstructor(AlignedMemory) instead of 
std::aligned_storage which has been deprecated in C++23 (#2719)
c727dd77 is described below

commit c727dd77a26aed921b8d7b5fdcb83c22d6f62a02
Author: Bright Chen <chenguangmin...@foxmail.com>
AuthorDate: Thu Sep 26 10:43:19 2024 +0800

    Use ManualConstructor(AlignedMemory) instead of std::aligned_storage which 
has been deprecated in C++23 (#2719)
---
 src/butil/compiler_specific.h         | 17 +++++++
 src/butil/containers/flat_map.h       | 23 +++++----
 src/butil/containers/mpsc_queue.h     | 10 ++--
 src/butil/memory/aligned_memory.h     | 46 +++++++++++-------
 src/butil/memory/manual_constructor.h |  5 ++
 src/butil/object_pool_inl.h           | 17 ++++---
 src/butil/resource_pool_inl.h         | 91 ++++++++++++++++++-----------------
 7 files changed, 128 insertions(+), 81 deletions(-)

diff --git a/src/butil/compiler_specific.h b/src/butil/compiler_specific.h
index d05da9dc..9eb4283e 100644
--- a/src/butil/compiler_specific.h
+++ b/src/butil/compiler_specific.h
@@ -124,6 +124,23 @@
 // Use like:
 //   class ALIGNAS(16) MyClass { ... }
 //   ALIGNAS(16) int array[4];
+//
+// In most places you can use the C++11 keyword "alignas", which is preferred.
+//
+// But compilers have trouble mixing __attribute__((...)) syntax with
+// alignas(...) syntax.
+//
+// Doesn't work in clang or gcc:
+//   struct alignas(16) __attribute__((packed)) S { char c; };
+// Works in clang but not gcc:
+//   struct __attribute__((packed)) alignas(16) S2 { char c; };
+// Works in clang and gcc:
+//   struct alignas(16) S3 { char c; } __attribute__((packed));
+//
+// There are also some attributes that must be specified *before* a class
+// definition: visibility (used for exporting functions/classes) is one of
+// these attributes. This means that it is not possible to use alignas() with a
+// class that is marked as exported.
 #if defined(COMPILER_MSVC)
 # define ALIGNAS(byte_alignment) __declspec(align(byte_alignment))
 #elif defined(COMPILER_GCC)
diff --git a/src/butil/containers/flat_map.h b/src/butil/containers/flat_map.h
index 40c44c59..955753d2 100644
--- a/src/butil/containers/flat_map.h
+++ b/src/butil/containers/flat_map.h
@@ -105,6 +105,7 @@
 #include "butil/bit_array.h"                       // bit_array_*
 #include "butil/strings/string_piece.h"            // StringPiece
 #include "butil/memory/scope_guard.h"
+#include "butil/memory/manual_constructor.h"
 
 namespace butil {
 
@@ -265,24 +266,26 @@ public:
     BucketInfo bucket_info() const;
 
     struct Bucket {
-        explicit Bucket(const _K& k) : next(NULL)
-        { new (&element_spaces) Element(k); }
-        Bucket(const Bucket& other) : next(NULL)
-        { new (&element_spaces) Element(other.element()); }
+        explicit Bucket(const _K& k) : next(NULL) {
+            element_.Init(k);
+        }
+        Bucket(const Bucket& other) : next(NULL) {
+            element_.Init(other.element());
+        }
+
         bool is_valid() const { return next != (const Bucket*)-1UL; }
         void set_invalid() { next = (Bucket*)-1UL; }
         // NOTE: Only be called when is_valid() is true.
         Element& element() {
-            void* spaces = &element_spaces; // Suppress strict-aliasing
-            return *reinterpret_cast<Element*>(spaces);
+            return *element_;
         }
         const Element& element() const {
-            const void* spaces = &element_spaces;
-            return *reinterpret_cast<const Element*>(spaces);
+            return *element_;
         }
         Bucket *next;
-        typename std::aligned_storage<sizeof(Element), alignof(Element)>::type
-            element_spaces;
+
+    private:
+        ManualConstructor<Element> element_;
     };
 
     allocator_type& get_allocator() { return _pool.get_allocator(); }
diff --git a/src/butil/containers/mpsc_queue.h 
b/src/butil/containers/mpsc_queue.h
index 6db50f28..6ba09db3 100644
--- a/src/butil/containers/mpsc_queue.h
+++ b/src/butil/containers/mpsc_queue.h
@@ -24,6 +24,7 @@
 
 #include "butil/object_pool.h"
 #include "butil/type_traits.h"
+#include "butil/memory/manual_constructor.h"
 
 namespace butil {
 
@@ -32,8 +33,7 @@ struct BAIDU_CACHELINE_ALIGNMENT MPSCQueueNode {
     static MPSCQueueNode* const UNCONNECTED;
 
     MPSCQueueNode* next{NULL};
-    char data_mem[sizeof(T)]{};
-
+    ManualConstructor<T> data_mem;
 };
 
 template <typename T>
@@ -95,7 +95,7 @@ template <typename T, typename Alloc>
 void MPSCQueue<T, Alloc>::Enqueue(typename add_const_reference<T>::type data) {
     auto node = (MPSCQueueNode<T>*)_alloc.Alloc();
     node->next = MPSCQueueNode<T>::UNCONNECTED;
-    new ((void*)&node->data_mem) T(data);
+    node->data_mem.Init(data);
     EnqueueImpl(node);
 }
 
@@ -103,7 +103,7 @@ template <typename T, typename Alloc>
 void MPSCQueue<T, Alloc>::Enqueue(T&& data) {
     auto node = (MPSCQueueNode<T>*)_alloc.Alloc();
     node->next = MPSCQueueNode<T>::UNCONNECTED;
-    new ((void*)&node->data_mem) T(std::forward<T>(data));
+    node->data_mem.Init(data);
     EnqueueImpl(node);
 }
 
@@ -136,7 +136,7 @@ bool MPSCQueue<T, Alloc>::DequeueImpl(T* data) {
     }
 
     if (data) {
-        auto mem = (T* const)node->data_mem;
+        auto mem = (T* const)node->data_mem.get();
         *data = std::move(*mem);
     }
     MPSCQueueNode<T>* old_node = node;
diff --git a/src/butil/memory/aligned_memory.h 
b/src/butil/memory/aligned_memory.h
index f589ff9c..c6aaaeef 100644
--- a/src/butil/memory/aligned_memory.h
+++ b/src/butil/memory/aligned_memory.h
@@ -51,24 +51,36 @@ namespace butil {
 template <size_t Size, size_t ByteAlignment>
 struct AlignedMemory {};
 
-#define BUTIL_DECL_ALIGNED_MEMORY(byte_alignment) \
-    template <size_t Size> \
-    class AlignedMemory<Size, byte_alignment> { \
-     public: \
-      ALIGNAS(byte_alignment) uint8_t data_[Size]; \
-      void* void_data() { return static_cast<void*>(data_); } \
-      const void* void_data() const { \
-        return static_cast<const void*>(data_); \
-      } \
-      template<typename Type> \
+// std::aligned_storage has been deprecated in C++23,
+// because aligned_* are harmful to codebases and should not be used.
+// For details, see 
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1413r3.pdf
+#if (__cplusplus >= 201103L)
+// In most places, use the C++11 keyword "alignas", which is preferred.
+#define DECL_ALIGNED_BUFFER(buffer_name, byte_alignment, size) \
+    alignas(byte_alignment) uint8_t buffer_name[size]
+#else
+#define DECL_ALIGNED_BUFFER(buffer_name, byte_alignment, size) \
+    ALIGNAS(byte_alignment) uint8_t buffer_name[size]
+#endif
+
+#define BUTIL_DECL_ALIGNED_MEMORY(byte_alignment)                 \
+    template <size_t Size>                                        \
+    class AlignedMemory<Size, byte_alignment> {                   \
+     public:                                                      \
+      DECL_ALIGNED_BUFFER(data_, byte_alignment, Size);           \
+      void* void_data() { return static_cast<void*>(data_); }     \
+      const void* void_data() const {                             \
+        return static_cast<const void*>(data_);                   \
+      }                                                           \
+      template<typename Type>                                     \
       Type* data_as() { return static_cast<Type*>(void_data()); } \
-      template<typename Type> \
-      const Type* data_as() const { \
-        return static_cast<const Type*>(void_data()); \
-      } \
-     private: \
-      void* operator new(size_t); \
-      void operator delete(void*); \
+      template<typename Type>                                     \
+      const Type* data_as() const {                               \
+        return static_cast<const Type*>(void_data());             \
+      }                                                           \
+     private:                                                     \
+      void* operator new(size_t);                                 \
+      void operator delete(void*);                                \
     }
 
 // Specialization for all alignments is required because MSVC (as of VS 2008)
diff --git a/src/butil/memory/manual_constructor.h 
b/src/butil/memory/manual_constructor.h
index 5d06b949..266f6cca 100644
--- a/src/butil/memory/manual_constructor.h
+++ b/src/butil/memory/manual_constructor.h
@@ -56,6 +56,11 @@ class ManualConstructor {
   inline Type& operator*() { return *get(); }
   inline const Type& operator*() const { return *get(); }
 
+  template<typename Ctor>
+  inline void InitBy(Ctor ctor) {
+    ctor(space_.void_data());
+  }
+
   // You can pass up to eight constructor arguments as arguments of Init().
   inline void Init() {
     new(space_.void_data()) Type;
diff --git a/src/butil/object_pool_inl.h b/src/butil/object_pool_inl.h
index 6f10e03a..71b9b890 100644
--- a/src/butil/object_pool_inl.h
+++ b/src/butil/object_pool_inl.h
@@ -29,6 +29,7 @@
 #include "butil/macros.h"                 // BAIDU_CACHELINE_ALIGNMENT
 #include "butil/scoped_lock.h"            // BAIDU_SCOPED_LOCK
 #include "butil/thread_local.h"           // BAIDU_THREAD_LOCAL
+#include "butil/memory/manual_constructor.h"
 #include <vector>
 
 #ifdef BUTIL_OBJECT_POOL_NEED_FREE_ITEM_NUM
@@ -97,7 +98,7 @@ public:
     // items in the Block are only used by the thread.
     // To support cache-aligned objects, align Block.items by cacheline.
     struct BAIDU_CACHELINE_ALIGNMENT Block {
-        char items[sizeof(T) * BLOCK_NITEM];
+        ManualConstructor<T> items[BLOCK_NITEM];
         size_t nitem;
 
         Block() : nitem(0) {}
@@ -145,7 +146,7 @@ public:
         // which may include parenthesis because when T is POD, "new T()"
         // and "new T" are different: former one sets all fields to 0 which
         // we don't want.
-#define BAIDU_OBJECT_POOL_GET(CTOR_ARGS)                                \
+#define BAIDU_OBJECT_POOL_GET(...)                                      \
         /* Fetch local free ptr */                                      \
         if (_cur_free.nfree) {                                          \
             BAIDU_OBJECT_POOL_FREE_ITEM_NUM_SUB1;                       \
@@ -158,9 +159,13 @@ public:
             BAIDU_OBJECT_POOL_FREE_ITEM_NUM_SUB1;                       \
             return _cur_free.ptrs[--_cur_free.nfree];                   \
         }                                                               \
+        T* obj = NULL;                                                  \
+        auto ctor = [&](void* mem) {                                    \
+            obj = new (mem) T(__VA_ARGS__);                             \
+        };                                                              \
         /* Fetch memory from local block */                             \
         if (_cur_block && _cur_block->nitem < BLOCK_NITEM) {            \
-            T* obj = new ((T*)_cur_block->items + _cur_block->nitem) T 
CTOR_ARGS; \
+            (_cur_block->items + _cur_block->nitem)->InitBy(ctor);      \
             if (!ObjectPoolValidator<T>::validate(obj)) {               \
                 obj->~T();                                              \
                 return NULL;                                            \
@@ -171,7 +176,7 @@ public:
         /* Fetch a Block from global */                                 \
         _cur_block = add_block(&_cur_block_index);                      \
         if (_cur_block != NULL) {                                       \
-            T* obj = new ((T*)_cur_block->items + _cur_block->nitem) T 
CTOR_ARGS; \
+            (_cur_block->items + _cur_block->nitem)->InitBy(ctor);      \
             if (!ObjectPoolValidator<T>::validate(obj)) {               \
                 obj->~T();                                              \
                 return NULL;                                            \
@@ -188,12 +193,12 @@ public:
 
         template <typename A1>
         inline T* get(const A1& a1) {
-            BAIDU_OBJECT_POOL_GET((a1));
+            BAIDU_OBJECT_POOL_GET(a1);
         }
 
         template <typename A1, typename A2>
         inline T* get(const A1& a1, const A2& a2) {
-            BAIDU_OBJECT_POOL_GET((a1, a2));
+            BAIDU_OBJECT_POOL_GET(a1, a2);
         }
 
 #undef BAIDU_OBJECT_POOL_GET
diff --git a/src/butil/resource_pool_inl.h b/src/butil/resource_pool_inl.h
index 4ebe4ad1..2ca858ad 100644
--- a/src/butil/resource_pool_inl.h
+++ b/src/butil/resource_pool_inl.h
@@ -29,6 +29,7 @@
 #include "butil/macros.h"                 // BAIDU_CACHELINE_ALIGNMENT
 #include "butil/scoped_lock.h"            // BAIDU_SCOPED_LOCK
 #include "butil/thread_local.h"           // thread_atexit
+#include "butil/memory/manual_constructor.h"
 #include <vector>
 
 #ifdef BUTIL_RESOURCE_POOL_NEED_FREE_ITEM_NUM
@@ -113,7 +114,7 @@ public:
     // items in the Block are only used by the thread.
     // To support cache-aligned objects, align Block.items by cacheline.
     struct BAIDU_CACHELINE_ALIGNMENT Block {
-        char items[sizeof(T) * BLOCK_NITEM];
+        ManualConstructor<T> items[BLOCK_NITEM];
         size_t nitem;
 
         Block() : nitem(0) {}
@@ -162,48 +163,52 @@ public:
         // which may include parenthesis because when T is POD, "new T()"
         // and "new T" are different: former one sets all fields to 0 which
         // we don't want.
-#define BAIDU_RESOURCE_POOL_GET(CTOR_ARGS)                              \
-        /* Fetch local free id */                                       \
-        if (_cur_free.nfree) {                                          \
+#define BAIDU_RESOURCE_POOL_GET(...)                                        \
+        /* Fetch local free id */                                           \
+        if (_cur_free.nfree) {                                              \
             const ResourceId<T> free_id = _cur_free.ids[--_cur_free.nfree]; \
-            *id = free_id;                                              \
-            BAIDU_RESOURCE_POOL_FREE_ITEM_NUM_SUB1;                   \
-            return unsafe_address_resource(free_id);                    \
-        }                                                               \
-        /* Fetch a FreeChunk from global.                               \
-           TODO: Popping from _free needs to copy a FreeChunk which is  \
-           costly, but hardly impacts amortized performance. */         \
-        if (_pool->pop_free_chunk(_cur_free)) {                         \
-            --_cur_free.nfree;                                          \
-            const ResourceId<T> free_id =  _cur_free.ids[_cur_free.nfree]; \
-            *id = free_id;                                              \
-            BAIDU_RESOURCE_POOL_FREE_ITEM_NUM_SUB1;                   \
-            return unsafe_address_resource(free_id);                    \
-        }                                                               \
-        /* Fetch memory from local block */                             \
-        if (_cur_block && _cur_block->nitem < BLOCK_NITEM) {            \
+            *id = free_id;                                                  \
+            BAIDU_RESOURCE_POOL_FREE_ITEM_NUM_SUB1;                         \
+            return unsafe_address_resource(free_id);                        \
+        }                                                                   \
+        /* Fetch a FreeChunk from global.                                   \
+           TODO: Popping from _free needs to copy a FreeChunk which is      \
+           costly, but hardly impacts amortized performance. */             \
+        if (_pool->pop_free_chunk(_cur_free)) {                             \
+            --_cur_free.nfree;                                              \
+            const ResourceId<T> free_id =  _cur_free.ids[_cur_free.nfree];  \
+            *id = free_id;                                                  \
+            BAIDU_RESOURCE_POOL_FREE_ITEM_NUM_SUB1;                         \
+            return unsafe_address_resource(free_id);                        \
+        }                                                                   \
+        T* p = NULL;                                                        \
+        auto ctor = [&](void* mem) {                                        \
+            p = new (mem) T(__VA_ARGS__);                                   \
+        };                                                                  \
+        /* Fetch memory from local block */                                 \
+        if (_cur_block && _cur_block->nitem < BLOCK_NITEM) {                \
             id->value = _cur_block_index * BLOCK_NITEM + _cur_block->nitem; \
-            T* p = new ((T*)_cur_block->items + _cur_block->nitem) T 
CTOR_ARGS; \
-            if (!ResourcePoolValidator<T>::validate(p)) {               \
-                p->~T();                                                \
-                return NULL;                                            \
-            }                                                           \
-            ++_cur_block->nitem;                                        \
-            return p;                                                   \
-        }                                                               \
-        /* Fetch a Block from global */                                 \
-        _cur_block = add_block(&_cur_block_index);                      \
-        if (_cur_block != NULL) {                                       \
+            (_cur_block->items + _cur_block->nitem)->InitBy(ctor);          \
+            if (!ResourcePoolValidator<T>::validate(p)) {                   \
+                p->~T();                                                    \
+                return NULL;                                                \
+            }                                                               \
+            ++_cur_block->nitem;                                            \
+            return p;                                                       \
+        }                                                                   \
+        /* Fetch a Block from global */                                     \
+        _cur_block = add_block(&_cur_block_index);                          \
+        if (_cur_block != NULL) {                                           \
             id->value = _cur_block_index * BLOCK_NITEM + _cur_block->nitem; \
-            T* p = new ((T*)_cur_block->items + _cur_block->nitem) T 
CTOR_ARGS; \
-            if (!ResourcePoolValidator<T>::validate(p)) {               \
-                p->~T();                                                \
-                return NULL;                                            \
-            }                                                           \
-            ++_cur_block->nitem;                                        \
-            return p;                                                   \
-        }                                                               \
-        return NULL;                                                    \
+            (_cur_block->items + _cur_block->nitem)->InitBy(ctor);          \
+            if (!ResourcePoolValidator<T>::validate(p)) {                   \
+                p->~T();                                                    \
+                return NULL;                                                \
+            }                                                               \
+            ++_cur_block->nitem;                                            \
+            return p;                                                       \
+        }                                                                   \
+        return NULL;                                                        \
  
 
         inline T* get(ResourceId<T>* id) {
@@ -212,12 +217,12 @@ public:
 
         template <typename A1>
         inline T* get(ResourceId<T>* id, const A1& a1) {
-            BAIDU_RESOURCE_POOL_GET((a1));
+            BAIDU_RESOURCE_POOL_GET(a1);
         }
 
         template <typename A1, typename A2>
         inline T* get(ResourceId<T>* id, const A1& a1, const A2& a2) {
-            BAIDU_RESOURCE_POOL_GET((a1, a2));
+            BAIDU_RESOURCE_POOL_GET(a1, a2);
         }
 
 #undef BAIDU_RESOURCE_POOL_GET
@@ -384,7 +389,7 @@ private:
 
     // Create a Block and append it to right-most BlockGroup.
     static Block* add_block(size_t* index) {
-        Block* const new_block = new(std::nothrow) Block;
+        Block* const new_block = new (std::nothrow) Block;
         if (NULL == new_block) {
             return NULL;
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@brpc.apache.org
For additional commands, e-mail: dev-h...@brpc.apache.org

Reply via email to