]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Reverted trunk r12255 changes. Provided a portable flexible arrays replacement.
authorAlex Rousskov <rousskov@measurement-factory.com>
Tue, 16 Oct 2012 00:26:06 +0000 (18:26 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Tue, 16 Oct 2012 00:26:06 +0000 (18:26 -0600)
Trunk r12255 made Clang compiler happy by removing flexible nonPod[] arrays.
Unfortunately, it also moved shared memory items into local memory (in some
cases uninitialized).

This change provides a Clang-friendly flexible array replacement while keeping
items in the shared memory (and using placement-new initialization). The code
may have become even less readable, but hopefully more portable.

N.B. Flexible arrays were introdiced in C99 standard, after C++ was
standardized in 1998. They are not yet in any revised C++ standard, but most
C++ compilers support them, at least for PODs.

src/ipc/Makefile.am
src/ipc/Queue.cc
src/ipc/Queue.h
src/ipc/StoreMap.cc
src/ipc/StoreMap.h
src/ipc/mem/FlexibleArray.h [new file with mode: 0644]
src/ipc/mem/PageStack.cc
src/ipc/mem/PageStack.h

index 9e2f7dcfda5a5c3e0aa8fe477d9fd60877390d47..3a08d6ea465c09260dd00793edba435d26b0cb2c 100644 (file)
@@ -46,6 +46,7 @@ libipc_la_SOURCES = \
        Request.h \
        Response.h \
        \
+       mem/FlexibleArray.h \
        mem/Page.cc \
        mem/Page.h \
        mem/PagePool.cc \
index e8bab93f7bbb673f6d3eee9ec7ad927899e14a85..0a47af19571c9c9dfa271e58fb8437856de4167b 100644 (file)
@@ -45,15 +45,10 @@ Ipc::QueueReader::QueueReader(): popBlocked(1), popSignal(0),
 
 /* QueueReaders */
 
-Ipc::QueueReaders::QueueReaders(const int aCapacity): theCapacity(aCapacity)
+Ipc::QueueReaders::QueueReaders(const int aCapacity): theCapacity(aCapacity),
+    theReaders(theCapacity)
 {
     Must(theCapacity > 0);
-    theReaders=new QueueReader[theCapacity];
-}
-
-Ipc::QueueReaders::~QueueReaders()
-{
-    delete[] theReaders;
 }
 
 size_t
index a800d51eb8ec873e8b30d114f12b71e35177c84f..8311a13a3550598fe6195e8cc93d2986de5fcf17 100644 (file)
@@ -8,6 +8,7 @@
 #include "Debug.h"
 #include "base/InstanceId.h"
 #include "ipc/AtomicWord.h"
+#include "ipc/mem/FlexibleArray.h"
 #include "ipc/mem/Pointer.h"
 #include "util.h"
 
@@ -62,16 +63,11 @@ class QueueReaders
 {
 public:
     QueueReaders(const int aCapacity);
-    ~QueueReaders();
     size_t sharedMemorySize() const;
     static size_t SharedMemorySize(const int capacity);
 
     const int theCapacity; /// number of readers
-    QueueReader *theReaders; /// readers
-private:
-    QueueReaders(); //not implemented
-    QueueReaders& operator =(const QueueReaders&); //not implemented
-    QueueReaders(const QueueReaders&); //not implemented
+    Ipc::Mem::FlexibleArray<QueueReader> theReaders; /// readers
 };
 
 /**
index c339a31cc26def8490e4388e720ebb8681dd763d..613dce632e4afe1bbbf212c42aec7d6e0e93efcf 100644 (file)
@@ -255,14 +255,14 @@ void
 Ipc::StoreMap::freeLocked(Slot &s, bool keepLocked)
 {
     if (s.state == Slot::Readable && cleaner)
-        cleaner->cleanReadable(&s - shared->slots);
+        cleaner->cleanReadable(&s - shared->slots.raw());
 
     s.waitingToBeFreed = false;
     s.state = Slot::Empty;
     if (!keepLocked)
         s.lock.unlockExclusive();
     --shared->count;
-    debugs(54, 5, HERE << " freed slot at " << (&s - shared->slots) <<
+    debugs(54, 5, HERE << " freed slot at " << (&s - shared->slots.raw()) <<
            " in map [" << path << ']');
 }
 
@@ -304,14 +304,8 @@ Ipc::StoreMapSlot::set(const StoreEntry &from)
 /* Ipc::StoreMap::Shared */
 
 Ipc::StoreMap::Shared::Shared(const int aLimit, const size_t anExtrasSize):
-        limit(aLimit), extrasSize(anExtrasSize), count(0)
+        limit(aLimit), extrasSize(anExtrasSize), count(0), slots(aLimit)
 {
-    slots=new Slot[limit];
-}
-
-Ipc::StoreMap::Shared::~Shared()
-{
-    delete[] slots;
 }
 
 size_t
index 42afbf46da350678cd09927162fac656b0c76aa9..444073a3595de9abfd68a810c206693a37d57163 100644 (file)
@@ -2,6 +2,7 @@
 #define SQUID_IPC_STORE_MAP_H
 
 #include "ipc/ReadWriteLock.h"
+#include "ipc/mem/FlexibleArray.h"
 #include "ipc/mem/Pointer.h"
 #include "typedefs.h"
 
@@ -62,16 +63,11 @@ public:
         Shared(const int aLimit, const size_t anExtrasSize);
         size_t sharedMemorySize() const;
         static size_t SharedMemorySize(const int limit, const size_t anExtrasSize);
-        ~Shared();
 
         const int limit; ///< maximum number of map slots
         const size_t extrasSize; ///< size of slot extra data
         Atomic::Word count; ///< current number of map slots
-        Slot *slots; ///< slots storage
-    private:
-        Shared(); //disabled
-        Shared &operator=(const Shared&); //disabled
-        Shared(const Shared&); //disabled
+        Ipc::Mem::FlexibleArray<Slot> slots; ///< slots storage
     };
 
 public:
diff --git a/src/ipc/mem/FlexibleArray.h b/src/ipc/mem/FlexibleArray.h
new file mode 100644 (file)
index 0000000..0af9971
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ */
+
+#ifndef SQUID_IPC_MEM_FLEXIBLE_ARRAY_H
+#define SQUID_IPC_MEM_FLEXIBLE_ARRAY_H
+
+// sometimes required for placement-new operator to be declared
+#include <new> 
+
+namespace Ipc
+{
+
+namespace Mem
+{
+
+/// A "flexible array" of Items inside some shared memory space.
+/// A portable equivalent of a "Item items[];" data member.
+/// Some compilers such as Clang can only handle flexible arrays of PODs,
+/// and the current C++ standard does not allow flexible arrays at all.
+template <class Item>
+class FlexibleArray
+{
+public:
+    explicit FlexibleArray(const int capacity) {
+        if (capacity > 1) // the first item is initialized automatically
+            new (items+1) Item[capacity-1];
+    }
+
+    Item &operator [](const int idx) { return items[idx]; }
+    const Item &operator [](const int idx) const { return items[idx]; }
+
+    //const Item *operator ()() const { return items; }
+    //Item *operator ()() { return items; }
+
+    Item *raw() { return items; }
+
+private:
+    Item items[1]; // ensures proper alignment of array elements
+};
+
+} // namespace Mem
+
+} // namespace Ipc
+
+#endif /* SQUID_IPC_MEM_FLEXIBLE_ARRAY_H */
index 4f3a6e18ebad310cc42b379d0c1e071f0d5b21f2..135283e30e5b47bdbd2fce82c6004bca58f6181c 100644 (file)
@@ -15,19 +15,14 @@ const Ipc::Mem::PageStack::Value Writable = 0;
 Ipc::Mem::PageStack::PageStack(const uint32_t aPoolId, const unsigned int aCapacity, const size_t aPageSize):
         thePoolId(aPoolId), theCapacity(aCapacity), thePageSize(aPageSize),
         theSize(theCapacity),
-        theLastReadable(prev(theSize)), theFirstWritable(next(theLastReadable))
+        theLastReadable(prev(theSize)), theFirstWritable(next(theLastReadable)),
+        theItems(aCapacity)
 {
-    theItems=new Item[theSize];
     // initially, all pages are free
     for (Offset i = 0; i < theSize; ++i)
         theItems[i] = i + 1; // skip page number zero to keep numbers positive
 }
 
-Ipc::Mem::PageStack::~PageStack()
-{
-    delete[] theItems;
-}
-
 /*
  * TODO: We currently rely on the theLastReadable hint during each
  * loop iteration. We could also use hint just for the start position:
index ccedbdac0c4450894c87c8e7693e57a6f9cd78e2..b58cf60b024e7357d907a158de5a75e66b6bcf04 100644 (file)
@@ -5,6 +5,7 @@
 #define SQUID_IPC_MEM_PAGE_STACK_H
 
 #include "ipc/AtomicWord.h"
+#include "ipc/mem/FlexibleArray.h"
 
 namespace Ipc
 {
@@ -23,7 +24,6 @@ public:
     typedef uint32_t Value; ///< stack item type (a free page number)
 
     PageStack(const uint32_t aPoolId, const unsigned int aCapacity, const size_t aPageSize);
-    ~PageStack();
 
     unsigned int capacity() const { return theCapacity; }
     size_t pageSize() const { return thePageSize; }
@@ -66,7 +66,7 @@ private:
     Atomic::WordT<Offset> theFirstWritable;
 
     typedef Atomic::WordT<Value> Item;
-    Item *theItems; ///< page number storage
+    Ipc::Mem::FlexibleArray<Item> theItems; ///< page number storage
 };
 
 } // namespace Mem