]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Undo trunk r13270: "Refactor Vector and Stack to STL counterparts"
authorAlex Rousskov <rousskov@measurement-factory.com>
Mon, 17 Mar 2014 21:03:04 +0000 (15:03 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Mon, 17 Mar 2014 21:03:04 +0000 (15:03 -0600)
to avoid stability issues related to std::vector migration.

17 files changed:
include/MemPoolMalloc.h
include/Stack.h [new file with mode: 0644]
include/splay.h
lib/MemPoolMalloc.cc
src/DelayUser.h
src/Generic.h
src/HttpHeader.cc
src/Makefile.am
src/base/Makefile.am
src/base/Vector.cc [new file with mode: 0644]
src/base/Vector.h [new file with mode: 0644]
src/cbdata.cc
src/store.cc
src/tests/testVector.cc [new file with mode: 0644]
src/tests/testVector.h [new file with mode: 0644]
test-suite/Makefile.am
test-suite/StackTest.cc [new file with mode: 0644]

index 43064203ea09d92d5b740c8b1a7cd77792b12ce1..2999dd4620f8e9b274fb6d859271e8015700845a 100644 (file)
@@ -22,8 +22,6 @@
 
 #include "MemPool.h"
 
-#include <stack>
-
 /// \ingroup MemPoolsAPI
 class MemPoolMalloc : public MemImplementingAllocator
 {
@@ -44,7 +42,7 @@ protected:
     virtual void *allocate();
     virtual void deallocate(void *, bool aggressive);
 private:
-    std::stack<void *> freelist;
+    Stack<void *> freelist;
 };
 
 #endif /* _MEM_POOL_MALLOC_H_ */
diff --git a/include/Stack.h b/include/Stack.h
new file mode 100644 (file)
index 0000000..fe39f66
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * AUTHOR: Alex Rousskov
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#ifndef SQUID_STACK_H
+#define SQUID_STACK_H
+
+#include "base/Vector.h"
+
+/* RBC: 20030714 Composition might be better long-term, but for now,
+ * there's no reason to do so.
+ */
+
+template <class S = void *>
+
+class Stack : public Vector<S>
+{
+public:
+    using Vector<S>::count;
+    using Vector<S>::items;
+    typedef typename Vector<S>::value_type value_type;
+    typedef typename Vector<S>::pointer pointer;
+    value_type pop() {
+        if (!count)
+            return value_type();
+
+        value_type result = items[--count];
+
+        this->items[count] = value_type();
+
+        return result;
+    }
+
+    /* todo, fatal on empty Top call */
+    value_type top() const {
+        return count ? items[count - 1] : value_type();
+    }
+};
+
+#endif /* SQUID_STACK_H */
index daafdd19b6a7fe5b8fc81528e86b25c63d9cdc9c..ea4f2c3e036ac460f814aaccee6d6da84e04c9c5 100644 (file)
@@ -3,9 +3,7 @@
 
 #if defined(__cplusplus)
 
-#include "fatal.h"
-
-#include <stack>
+#include "Stack.h"
 
 template <class V>
 class SplayNode
@@ -378,7 +376,7 @@ private:
     void advance();
     void addLeftPath(SplayNode<V> *aNode);
     void init(SplayNode<V> *);
-    std::stack<SplayNode<V> *> toVisit;
+    Stack<SplayNode<V> *> toVisit;
 };
 
 template <class V>
@@ -391,12 +389,7 @@ template <class V>
 bool
 SplayConstIterator<V>::operator == (SplayConstIterator const &right) const
 {
-    if (toVisit.empty() && right.toVisit.empty())
-        return true;
-    if (!toVisit.empty() && !right.toVisit.empty())
-        return toVisit.top() == right.toVisit.top();
-    // only one of the two is empty
-    return false;
+    return toVisit.top() == right.toVisit.top();
 }
 
 template <class V>
@@ -428,21 +421,19 @@ template <class V>
 void
 SplayConstIterator<V>::advance()
 {
-    if (toVisit.empty())
+    if (toVisit.size() == 0)
         return;
 
     toVisit.pop();
 
-    if (toVisit.empty())
+    if (toVisit.size() == 0)
         return;
 
-    // not empty
-    SplayNode<V> *currentNode = toVisit.top();
-    toVisit.pop();
+    SplayNode<V> *currentNode = toVisit.pop();
 
     addLeftPath(currentNode->right);
 
-    toVisit.push(currentNode);
+    toVisit.push_back(currentNode);
 }
 
 template <class V>
@@ -453,7 +444,7 @@ SplayConstIterator<V>::addLeftPath(SplayNode<V> *aNode)
         return;
 
     do {
-        toVisit.push(aNode);
+        toVisit.push_back(aNode);
         aNode = aNode->left;
     } while (aNode != NULL);
 }
index f0fe52fe98aefd70d191b5a31ed6a245a7bae8a6..5a442f4e2060c568ad38b36f8891f7c90225d3ab 100644 (file)
@@ -46,11 +46,7 @@ extern time_t squid_curtime;
 void *
 MemPoolMalloc::allocate()
 {
-    void *obj = NULL;
-    if (!freelist.empty()) {
-        obj = freelist.top();
-        freelist.pop();
-    }
+    void *obj = freelist.pop();
     if (obj) {
         memMeterDec(meter.idle);
         ++saved_calls;
@@ -76,7 +72,7 @@ MemPoolMalloc::deallocate(void *obj, bool aggressive)
         if (doZero)
             memset(obj, 0, obj_size);
         memMeterInc(meter.idle);
-        freelist.push(obj);
+        freelist.push_back(obj);
     }
 }
 
@@ -132,9 +128,7 @@ MemPoolMalloc::idleTrigger(int shift) const
 void
 MemPoolMalloc::clean(time_t maxage)
 {
-    while (!freelist.empty()) {
-        void *obj = freelist.top();
-        freelist.pop();
+    while (void *obj = freelist.pop()) {
         memMeterDec(meter.idle);
         memMeterDec(meter.alloc);
         xfree(obj);
index 9bc88f411d9e5df0a91d0e0543c15cb70ea5f486..6ac274791c2dada93235aef87ebfdf81320e23d7 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "auth/Gadgets.h"
 #include "auth/User.h"
+#include "base/Vector.h"
 #include "CompositePoolNode.h"
 #include "DelayBucket.h"
 #include "DelayIdComposite.h"
index 1f7fbbf99befd517e5a5b99064c3bc9cdbd38d11..5e3329abd1dabbac4e4b632a9bfd0fa35bdde84a 100644 (file)
@@ -58,6 +58,18 @@ T& for_each(dlink_list const &collection, T& visitor)
     return visitor;
 }
 
+template <class S>
+class Stack;
+
+template <class E, class T>
+T& for_each(Stack<E> const &collection, T& visitor)
+{
+    for (size_t index = 0; index < collection.count; ++index)
+        visitor(*(typename T::argument_type const *)collection.items[index]);
+
+    return visitor;
+};
+
 /* RBC 20030718 - use this to provide instance expecting classes a pointer to a
  * singleton
  */
index 56eb4b32e61dcf039829cada933ee8a5b59a172e..26677530c6b94258aa7c35893fb2155a448495f0 100644 (file)
 
 #include <algorithm>
 
-/* XXX: the whole set of API managing the entries vector should be rethought
- *      after the parse4r-ng effort is complete.
- */
-
 /*
  * On naming conventions:
  *
@@ -441,6 +437,8 @@ HttpHeader::operator =(const HttpHeader &other)
 void
 HttpHeader::clean()
 {
+    HttpHeaderPos pos = HttpHeaderInitPos;
+    HttpHeaderEntry *e;
 
     assert(owner > hoNone && owner < hoEnd);
     debugs(55, 7, "cleaning hdr: " << this << " owner: " << owner);
@@ -466,19 +464,18 @@ HttpHeader::clean()
         HttpHeaderStats[owner].busyDestroyedCount += entries.size() > 0;
     } // if (owner <= hoReply)
 
-    for (std::vector<HttpHeaderEntry *>::iterator i = entries.begin(); i != entries.end(); ++i) {
-        HttpHeaderEntry *e = *i;
-        if (e == NULL)
-            continue;
+    while ((e = getEntry(&pos))) {
+        /* tmp hack to try to avoid coredumps */
+
         if (e->id < 0 || e->id >= HDR_ENUM_END) {
-            debugs(55, DBG_CRITICAL, "BUG: invalid entry (" << e->id << "). Ignored.");
+            debugs(55, DBG_CRITICAL, "HttpHeader::clean BUG: entry[" << pos << "] is invalid (" << e->id << "). Ignored.");
         } else {
             if (owner <= hoReply)
                 HttpHeaderStats[owner].fieldTypeDistr.count(e->id);
+            /* yes, this deletion leaves us in an inconsistent state */
             delete e;
         }
     }
-
     entries.clear();
     httpHeaderMaskInit(&mask, 0);
     len = 0;
index c0568c1ead3e3bdedeb7266b439a5a621d8a7f78..400f3153d52f6e9771343a0dc29d7a56e6905aee 100644 (file)
@@ -1077,7 +1077,8 @@ check_PROGRAMS+=\
        tests/testSBuf \
        tests/testSBufList \
        tests/testConfigParser \
-       tests/testStatHist
+       tests/testStatHist \
+       tests/testVector
 
 if HAVE_FS_ROCK
 check_PROGRAMS += tests/testRock
@@ -3825,6 +3826,21 @@ tests_testStatHist_LDADD = \
        $(COMPAT_LIB)
 tests_testStatHist_DEPENDENCIES = $(SQUID_CPPUNIT_LA)
 
+tests_testVector_SOURCES = \
+       tests/testVector.cc \
+       tests/testMain.cc \
+       tests/testVector.h
+nodist_tests_testVector_SOURCES = \
+       $(TESTSOURCES)
+tests_testVector_LDADD= \
+       $(SQUID_CPPUNIT_LIBS) \
+       $(COMPAT_LIB) \
+       $(XTRA_LIBS)
+tests_testVector_LDFLAGS = $(LIBADD_DL)
+tests_testVector_DEPENDENCIES = \
+       $(SQUID_CPPUNIT_LA)
+
+
 TESTS += testHeaders
 
 ## Special Universal .h dependency test script
index 3591294cf80886a98f9853c9fb5589c49f4372e9..80533ad4268b1dc1a7c3f2379ee03a4fd9586913 100644 (file)
@@ -23,7 +23,9 @@ libbase_la_SOURCES = \
        RunnersRegistry.h \
        Subscription.h \
        TextException.cc \
-       TextException.h
+       TextException.h \
+       Vector.cc \
+       Vector.h
 
 EXTRA_PROGRAMS = \
        testCharacterSet
diff --git a/src/base/Vector.cc b/src/base/Vector.cc
new file mode 100644 (file)
index 0000000..afc420a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * AUTHOR: Alex Rousskov
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+/*
+ * Array is an array of (void*) items with unlimited capacity
+ *
+ * Array grows when arrayAppend() is called and no space is left
+ * Currently, array does not have an interface for deleting an item because
+ *     we do not need such an interface yet.
+ */
+
+#include "squid.h"
+#include "base/Vector.h"
+
+#if HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#endif
diff --git a/src/base/Vector.h b/src/base/Vector.h
new file mode 100644 (file)
index 0000000..05d58f1
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * AUTHOR: Alex Rousskov
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+#ifndef SQUID_ARRAY_H
+#define SQUID_ARRAY_H
+
+/**
+ \todo remove this after replacing with STL
+ */
+
+#include "fatal.h"
+#include "util.h"
+
+/* users of this template also need assert() */
+#include "compat/assert.h"
+
+/* iterator support */
+#include <iterator>
+
+template <class C>
+class VectorIteratorBase
+{
+public:
+    typedef typename C::value_type value_type;
+    typedef std::forward_iterator_tag iterator_category;
+    typedef typename C::pointer pointer;
+    typedef typename C::reference reference;
+    typedef typename C::difference_type difference_type;
+
+    VectorIteratorBase();
+    VectorIteratorBase(C &);
+    VectorIteratorBase(size_t, C &);
+    VectorIteratorBase & operator =(VectorIteratorBase const &);
+    bool operator != (VectorIteratorBase const &rhs) const;
+    bool operator == (VectorIteratorBase const &rhs) const;
+    VectorIteratorBase & operator ++();
+    VectorIteratorBase operator ++(int);
+    typename C::value_type & operator *() const {
+        return theVector->items[pos];
+    }
+
+    typename C::value_type * operator -> () const {
+        return &theVector->items[pos];
+    }
+
+    ssize_t operator - (VectorIteratorBase const &rhs) const;
+    bool incrementable() const;
+
+private:
+    size_t pos;
+    C * theVector;
+};
+
+template<class E>
+class Vector
+{
+public:
+    typedef E value_type;
+    typedef E* pointer;
+    typedef E& reference;
+    typedef VectorIteratorBase<Vector<E> > iterator;
+    typedef VectorIteratorBase<Vector<E> const> const_iterator;
+    typedef ptrdiff_t difference_type;
+    friend class VectorIteratorBase<Vector<E> >;
+    friend class VectorIteratorBase<Vector<E> const>;
+    void *operator new (size_t);
+    void operator delete (void *);
+
+    Vector();
+    ~Vector();
+    Vector(Vector const &);
+    Vector &operator = (Vector const &);
+    void clear();
+    void reserve (size_t capacity);
+    void push_back (E);
+
+    void insert (E);
+    const E &front() const;
+    E &front();
+    E &back();
+    void pop_back();
+    E shift();         // aka pop_front
+    void prune(E);
+    void preAppend(int app_count);
+    inline bool empty() const;
+    inline size_t size() const;
+    iterator begin();
+    const_iterator begin () const;
+    iterator end();
+    const_iterator end () const;
+    E& at(unsigned i);
+    const E& at(unsigned i) const;
+    inline E& operator [] (unsigned i);
+    inline const E& operator [] (unsigned i) const;
+    E* data() const { return items; }
+
+protected:
+    size_t capacity;
+    size_t count;
+    E *items;
+};
+
+template<class E>
+void *
+Vector<E>::operator new(size_t size)
+{
+    return xmalloc(size);
+}
+
+template<class E>
+void
+Vector<E>::operator delete (void *address)
+{
+    xfree (address);
+}
+
+template<class E>
+Vector<E>::Vector() : capacity (0), count(0), items (NULL)
+{}
+
+template<class E>
+Vector<E>::~Vector()
+{
+    clear();
+}
+
+template<class E>
+void
+Vector<E>::clear()
+{
+    /* could also warn if some objects are left */
+    delete[] items;
+    items = NULL;
+    capacity = 0;
+    count = 0;
+}
+
+/* grows internal buffer to satisfy required minimal capacity */
+template<class E>
+void
+Vector<E>::reserve(size_t min_capacity)
+{
+    const int min_delta = 16;
+    int delta;
+
+    if (capacity >= min_capacity)
+        return;
+
+    delta = min_capacity;
+
+    /* make delta a multiple of min_delta */
+    delta += min_delta - 1;
+
+    delta /= min_delta;
+
+    delta *= min_delta;
+
+    /* actual grow */
+    if (delta < 0)
+        delta = min_capacity - capacity;
+
+    E*newitems = new E[capacity + delta];
+
+    for (size_t counter = 0; counter < size(); ++counter) {
+        newitems[counter] = items[counter];
+    }
+
+    capacity += delta;
+    delete[]items;
+    items = newitems;
+}
+
+template<class E>
+void
+Vector<E>::push_back(E obj)
+{
+    if (size() >= capacity)
+        reserve (size() + 1);
+
+    items[count++] = obj;
+}
+
+template<class E>
+void
+Vector<E>::insert(E obj)
+{
+    if (size() >= capacity)
+        reserve (size() + 1);
+
+    int i;
+
+    for (i = count; i > 0; i--)
+        items[i] = items[i - 1];
+
+    items[i] = obj;
+
+    count += 1;
+}
+
+template<class E>
+E
+Vector<E>::shift()
+{
+    assert (size());
+    value_type result = items[0];
+
+    for (unsigned int i = 1; i < count; i++)
+        items[i-1] = items[i];
+
+    count--;
+
+    /*reset the last (unused) element...*/
+    items[count] = value_type();
+
+    return result;
+}
+
+template<class E>
+void
+Vector<E>::pop_back()
+{
+    assert (size());
+    --count;
+    items[count] = value_type();
+}
+
+template<class E>
+E &
+Vector<E>::back()
+{
+    assert (size());
+    return items[size() - 1];
+}
+
+template<class E>
+const E &
+Vector<E>::front() const
+{
+    assert (size());
+    return items[0];
+}
+
+template<class E>
+E &
+Vector<E>::front()
+{
+    assert (size());
+    return items[0];
+}
+
+template<class E>
+void
+Vector<E>::prune(E item)
+{
+    unsigned int n = 0;
+    for (unsigned int i = 0; i < count; i++) {
+        if (items[i] != item) {
+            if (i != n)
+                items[n] = items[i];
+            n++;
+        }
+    }
+
+    count = n;
+}
+
+/* if you are going to append a known and large number of items, call this first */
+template<class E>
+void
+Vector<E>::preAppend(int app_count)
+{
+    if (size() + app_count > capacity)
+        reserve(size() + app_count);
+}
+
+template<class E>
+Vector<E>::Vector (Vector<E> const &rhs)
+{
+    items = NULL;
+    capacity = 0;
+    count = 0;
+    reserve (rhs.size());
+
+    for (size_t counter = 0; counter < rhs.size(); ++counter)
+        push_back (rhs.items[counter]);
+}
+
+template<class E>
+Vector<E> &
+Vector<E>::operator = (Vector<E> const &old)
+{
+    clear();
+    reserve (old.size());
+
+    for (size_t counter = 0; counter < old.size(); ++counter)
+        push_back (old.items[counter]);
+
+    return *this;
+}
+
+template<class E>
+bool
+Vector<E>::empty() const
+{
+    return size() == 0;
+}
+
+template<class E>
+size_t
+Vector<E>::size() const
+{
+    return count;
+}
+
+template<class E>
+typename Vector<E>::iterator
+Vector<E>::begin()
+{
+    return iterator (0, *this);
+}
+
+template<class E>
+typename Vector<E>::iterator
+Vector<E>::end()
+{
+    return iterator(size(), *this);
+}
+
+template<class E>
+typename Vector<E>::const_iterator
+Vector<E>::begin() const
+{
+    return const_iterator (0, *this);
+}
+
+template<class E>
+typename Vector<E>::const_iterator
+Vector<E>::end() const
+{
+    return const_iterator(size(), *this);
+}
+
+template<class E>
+E &
+Vector<E>::at(unsigned i)
+{
+    assert (size() > i);
+    return operator[](i);
+}
+
+template<class E>
+const E &
+Vector<E>::at(unsigned i) const
+{
+    assert (size() > i);
+    return operator[](i);
+}
+
+template<class E>
+E &
+Vector<E>::operator [] (unsigned i)
+{
+    return items[i];
+}
+
+template<class E>
+const E &
+Vector<E>::operator [] (unsigned i) const
+{
+    return items[i];
+}
+
+template<class C>
+VectorIteratorBase<C>::VectorIteratorBase() : pos(0), theVector(NULL)
+{}
+
+template<class C>
+VectorIteratorBase<C>::VectorIteratorBase(C &container) : pos(container.begin()), theVector(&container)
+{}
+
+template<class C>
+VectorIteratorBase<C>::VectorIteratorBase(size_t aPos, C &container) : pos(aPos), theVector(&container) {}
+
+template<class C>
+bool VectorIteratorBase<C>:: operator != (VectorIteratorBase<C> const &rhs) const
+{
+    assert (theVector);
+    return pos != rhs.pos;
+}
+
+template<class C>
+bool VectorIteratorBase<C>:: operator == (VectorIteratorBase<C> const &rhs) const
+{
+    assert (theVector);
+    return pos == rhs.pos;
+}
+
+template<class C>
+bool
+VectorIteratorBase<C>::incrementable() const
+{
+    assert (theVector);
+    return pos != theVector->size();
+}
+
+template<class C>
+VectorIteratorBase<C> & VectorIteratorBase<C>:: operator ++()
+{
+    assert (theVector);
+
+    if (!incrementable())
+        fatal ("domain error");
+
+    ++pos;
+
+    return *this;
+}
+
+template<class C>
+VectorIteratorBase<C> VectorIteratorBase<C>:: operator ++(int)
+{
+    VectorIteratorBase result(*this);
+    ++*this;
+    return result;
+}
+
+template<class C>
+VectorIteratorBase<C>&
+VectorIteratorBase<C>::operator =(VectorIteratorBase<C> const &old)
+{
+    pos = old.pos;
+    theVector = old.theVector;
+    return *this;
+}
+
+template<class C>
+ssize_t
+VectorIteratorBase<C>::operator - (VectorIteratorBase<C> const &rhs) const
+{
+    assert(theVector == rhs.theVector);
+    return pos - rhs.pos;
+}
+
+#endif /* SQUID_ARRAY_H */
index ae2827bf1d10c5bee52570c19c3d955d07c47c59..a0cf24acb361b6261d81be0e810fb949d8b6702e 100644 (file)
 #include "cbdata.h"
 #include "mgr/Registration.h"
 #include "Store.h"
+#if USE_CBDATA_DEBUG
+#include "Stack.h"
+#endif
 #include "Generic.h"
 
 #include <climits>
-#if USE_CBDATA_DEBUG
-#include <algorithm>
-#include <vector>
-#endif
 
 #if WITH_VALGRIND
 #define HASHED_CBDATA 1
@@ -123,7 +122,7 @@ public:
     dlink_node link;
     const char *file;
     int line;
-    std::vector<CBDataCall*> calls; // used as a stack with random access operator
+    Stack<CBDataCall*> calls;
 #endif
 
     /* cookie used while debugging */
@@ -208,11 +207,10 @@ cbdata_hash(const void *p, unsigned int mod)
 cbdata::~cbdata()
 {
 #if USE_CBDATA_DEBUG
+    CBDataCall *aCall;
 
-    while (!calls.empty()) {
-        delete calls.back();
-        calls.pop_back();
-    }
+    while ((aCall = calls.pop()))
+        delete aCall;
 
 #endif
 
@@ -316,7 +314,7 @@ cbdataInternalAlloc(cbdata_type type)
 
     c->file = file;
     c->line = line;
-    c->calls = std::vector<CBDataCall *> ();
+    c->calls = Stack<CBDataCall *> ();
     c->addHistory("Alloc", file, line);
     dlinkAdd(c, &c->link, &cbdataEntries);
     debugs(45, 3, "cbdataAlloc: " << p << " " << file << ":" << line);
@@ -614,8 +612,8 @@ CBDATA_CLASS_INIT(generic_cbdata);
 struct CBDataCallDumper : public unary_function<CBDataCall, void> {
     CBDataCallDumper (StoreEntry *anEntry):where(anEntry) {}
 
-    void operator()(CBDataCall const &x) {
-        storeAppendPrintf(where, "%s\t%s\t%d\n", x->label, x->file, x->line);
+    void operator()(CBDataCall const &x) {
+        storeAppendPrintf(where, "%s\t%s\t%d\n", x.label, x.file, x.line);
     }
 
     StoreEntry *where;
@@ -628,7 +626,7 @@ struct CBDataHistoryDumper : public CBDataDumper {
         CBDataDumper::operator()(x);
         storeAppendPrintf(where, "\n");
         storeAppendPrintf(where, "Action\tFile\tLine\n");
-        std::for_each (x.calls.begin(), x.calls.end(), callDumper);
+        for_each (x.calls,callDumper);
         storeAppendPrintf(where, "\n");
     }
 
index ebea92f716578ce21fc1579ac5e366ccaa01a691..b46504f8b4863a19ea14366e7f1368d681448fd5 100644 (file)
@@ -51,6 +51,7 @@
 #include "RequestFlags.h"
 #include "SquidConfig.h"
 #include "SquidTime.h"
+#include "Stack.h"
 #include "StatCounters.h"
 #include "stmem.h"
 #include "Store.h"
@@ -71,7 +72,6 @@
 #endif
 
 #include <climits>
-#include <stack>
 
 #define REBUILD_TIMESTAMP_DELTA_MAX 2
 
@@ -124,7 +124,7 @@ static EVH storeLateRelease;
 /*
  * local variables
  */
-static std::stack<StoreEntry*> LateReleaseStack;
+static Stack<StoreEntry*> LateReleaseStack;
 MemAllocator *StoreEntry::pool = NULL;
 
 StorePointer Store::CurrentRoot = NULL;
@@ -1252,7 +1252,7 @@ StoreEntry::release()
             // lock the entry until rebuilding is done
             lock("storeLateRelease");
             setReleaseFlag();
-            LateReleaseStack.push(this);
+            LateReleaseStack.push_back(this);
         } else {
             destroyStoreEntry(static_cast<hash_link *>(this));
             // "this" is no longer valid
@@ -1280,6 +1280,7 @@ static void
 storeLateRelease(void *unused)
 {
     StoreEntry *e;
+    int i;
     static int n = 0;
 
     if (StoreController::store_dirs_rebuilding) {
@@ -1287,14 +1288,13 @@ storeLateRelease(void *unused)
         return;
     }
 
-    // TODO: this works but looks unelegant.
-    for (int i = 0; i < 10; ++i) {
-        if (LateReleaseStack.empty()) {
+    for (i = 0; i < 10; ++i) {
+        e = LateReleaseStack.empty() ? NULL : LateReleaseStack.pop();
+
+        if (e == NULL) {
+            /* done! */
             debugs(20, DBG_IMPORTANT, "storeLateRelease: released " << n << " objects");
             return;
-        } else {
-            e = LateReleaseStack.top();
-            LateReleaseStack.pop();
         }
 
         e->unlock("storeLateRelease");
diff --git a/src/tests/testVector.cc b/src/tests/testVector.cc
new file mode 100644 (file)
index 0000000..7257007
--- /dev/null
@@ -0,0 +1,19 @@
+#define SQUID_UNIT_TEST 1
+#include "squid.h"
+#include "base/Vector.h"
+#include "tests/testVector.h"
+
+#include <cppunit/TestAssert.h>
+
+CPPUNIT_TEST_SUITE_REGISTRATION( testVector );
+
+void testVector::all()
+{
+    CPPUNIT_ASSERT_EQUAL(1 ,  1);
+    Vector<int> aArray;
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), aArray.size());
+    aArray.push_back(2);
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aArray.size());
+    CPPUNIT_ASSERT_EQUAL(2, aArray.back());
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), aArray.size());
+}
diff --git a/src/tests/testVector.h b/src/tests/testVector.h
new file mode 100644 (file)
index 0000000..f1606db
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef SQUID_SRC_TESTS_TESTVECTOR_H
+#define SQUID_SRC_TESTS_TESTVECTOR_H
+
+#include <cppunit/extensions/HelperMacros.h>
+
+/*
+ * A test case that is designed to produce
+ * example errors and failures
+ *
+ */
+
+class testVector : public CPPUNIT_NS::TestFixture
+{
+    CPPUNIT_TEST_SUITE( testVector );
+    CPPUNIT_TEST( all );
+    CPPUNIT_TEST_SUITE_END();
+
+public:
+
+protected:
+    void all();
+};
+
+#endif
index 6aeb5187d41a2d88b1cd6c2baaf064b026b055c8..010a8bb4fb56fcaebbaec965adfa93a89564af6c 100644 (file)
@@ -31,6 +31,7 @@ endif
 TESTS += debug \
        syntheticoperators \
        VirtualDeleteOperator \
+       StackTest \
        splay\
        MemPoolTest\
        mem_node_test\
@@ -45,6 +46,7 @@ check_PROGRAMS += debug \
                mem_node_test\
                mem_hdr_test \
                splay \
+               StackTest \
                syntheticoperators \
                VirtualDeleteOperator
 
@@ -87,6 +89,8 @@ MemPoolTest_SOURCES = MemPoolTest.cc
 
 splay_SOURCES = splay.cc
 
+StackTest_SOURCES = StackTest.cc $(DEBUG_SOURCE)
+
 syntheticoperators_SOURCES = syntheticoperators.cc $(DEBUG_SOURCE)
 
 VirtualDeleteOperator_SOURCES = VirtualDeleteOperator.cc $(DEBUG_SOURCE)
diff --git a/test-suite/StackTest.cc b/test-suite/StackTest.cc
new file mode 100644 (file)
index 0000000..377d899
--- /dev/null
@@ -0,0 +1,56 @@
+
+/*
+ * DEBUG: section 19    Store Memory Primitives
+ * AUTHOR: Robert Collins
+ *
+ * SQUID Web Proxy Cache          http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from
+ *  the Internet community; see the CONTRIBUTORS file for full
+ *  details.   Many organizations have provided support for Squid's
+ *  development; see the SPONSORS file for full details.  Squid is
+ *  Copyrighted (C) 2001 by the Regents of the University of
+ *  California; see the COPYRIGHT file for full details.  Squid
+ *  incorporates software developed and/or copyrighted by other
+ *  sources; see the CREDITS file for full details.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ * Copyright (c) 2003  Robert Collins <robertc@squid-cache.org>
+ */
+
+#include "squid.h"
+#include "Stack.h"
+
+int
+main(int argc, char **argv)
+{
+    Stack<int> aStack;
+    assert (aStack.size() == 0);
+    aStack.push_back(2);
+    assert (aStack.size() == 1);
+    assert (aStack.top() == 2);
+    assert (aStack.pop() == 2);
+    assert (aStack.size() == 0);
+    Stack<> oldStack;
+    assert (oldStack.size() == 0);
+    oldStack.push_back(&aStack);
+    assert (oldStack.size() == 1);
+    assert (oldStack.top() == &aStack);
+    assert (oldStack.pop() == &aStack);
+    assert (oldStack.size() == 0);
+    return 0;
+}