Compare commits

..

6 Commits

Author SHA1 Message Date
Beman Dawes
2c478e1884 Release 1.49.0
[SVN r77094]
2012-02-22 22:08:43 +00:00
Jan Gaspar
ed237fa058 circular_buffer: fixed when BOOST_NO_STDC_NAMESPACE defined
[SVN r66704]
2010-11-23 19:45:36 +00:00
Jan Gaspar
2bd298dec7 circular_buffer: applied patch to remove workaround for DEC C++ compiler - now all compilers will use this->invalidate_iterators_except
[SVN r61570]
2010-04-26 09:40:08 +00:00
Jan Gaspar
65810242ee circular_buffer: updated documentation
[SVN r60691]
2010-03-18 12:39:52 +00:00
Jan Gaspar
0282b8ee74 circular_buffer: constant complexity of clear method and destructor; added erase_begin and erase_end methods
[SVN r58681]
2010-01-04 15:54:37 +00:00
Troy D. Straszheim
cde2abac0c rm cmake from the release branch before it goes out broken. Policy dictates that you never commit to release, you commit to trunk and merge to release.
[SVN r56941]
2009-10-17 01:10:45 +00:00
9 changed files with 603 additions and 86 deletions

View File

@@ -1,29 +0,0 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
#----------------------------------------------------------------------------
# This file was automatically generated from the original CMakeLists.txt file
# Add a variable to hold the headers for the library
set (lib_headers
circular_buffer.hpp
circular_buffer_fwd.hpp
circular_buffer
)
# Add a library target to the build system
boost_library_project(
circular_buffer
# SRCDIRS
TESTDIRS test
HEADERS ${lib_headers}
# DOCDIRS
DESCRIPTION "STL compliant container also known as ring or cyclic buffer."
MODULARIZED
AUTHORS "Jan Gaspar <jano_gaspar -at- yahoo.com>"
# MAINTAINERS
)

View File

@@ -65,6 +65,9 @@
<dt>
<a href="#debug">Debug Support</a>
</dt>
<dt>
<a href="#interprocess">Compatibility with Interprocess library</a>
</dt>
<dt>
<a href="#examples">More Examples</a>
</dt>
@@ -338,6 +341,8 @@ public:
iterator <a href="#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase</a>(iterator pos);
iterator <a href=
"#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase</a>(iterator first, iterator last);
void <a href="#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin</a>(size_type n);
void <a href="#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end</a>(size_type n);
void <a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear</a>();
};
@@ -592,7 +597,18 @@ template &lt;class T, class Alloc&gt;
</p>
<p>
The debug support is enabled only in the debug mode (when the <code>NDEBUG</code> is not defined). It can also be
explicitly disabled by defining <code>BOOST_CB_DISABLE_DEBUG</code> macro.
explicitly disabled (only for <code>circular_buffer</code>) by defining <code>BOOST_CB_DISABLE_DEBUG</code>
macro.
</p>
<h2>
<a name="intreprocess" id="interprocess">Compatibility with Interprocess library</a>
</h2>
<p>
The <code>circular_buffer</code> is compatible with the <a href="../../../doc/html/interprocess.html">Boost
Interprocess</a> library used for interprocess communication. Considering that the <code>circular_buffer</code>'s
debug support relies on 'raw' pointers - which is not permited by the Interprocess library - the code has to
compiled with <code>-DBOOST_CB_DISABLE_DEBUG</code> or <code>-DNDEBUG</code> (which disables the
<a href="#debug">Debug Support</a>). Not doing that will cause the compilation to fail.
</p>
<h2>
<a name="examples" id="examples">More Examples</a>
@@ -1607,7 +1623,7 @@ template &lt;class T, class Alloc&gt;
<b>Complexity:</b>
</dt>
<dd>
Linear (in the size of the <code>circular_buffer</code>).
Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
</dd>
</dl>
<dl>
@@ -6110,7 +6126,10 @@ template &lt;class T, class Alloc&gt;
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
@@ -6222,7 +6241,10 @@ template &lt;class T, class Alloc&gt;
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
@@ -6335,7 +6357,10 @@ template &lt;class T, class Alloc&gt;
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
@@ -6460,6 +6485,219 @@ template &lt;class T, class Alloc&gt;
<code><a href="#classboost_1_1circular__buffer_1a96415389509a18bd7d7b5d8e4dda9bd">erase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
</tr>
<tr>
<td>
<a id="classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd" name=
"classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd"></a><code><b>void erase_begin(<a href=
"#classboost_1_1circular__buffer_19ba12c0142a21a7d960877c22fa3ea00">size_type</a> n);</b></code><br>
<br>
Remove first <code>n</code> elements (with constant complexity for scalar types).
<dl>
<dt>
<b>Precondition:</b>
</dt>
<dd>
<code>n &lt;= <a href=
"#classboost_1_1circular__buffer_15fa0edd153e2591dd6bf070eb663ee32">size()</a></code>
</dd>
</dl>
<dl>
<dt>
<b>Effect:</b>
</dt>
<dd>
The <code>n</code> elements at the beginning of the <code>circular_buffer</code> will be removed.
</dd>
</dl>
<dl>
<dt>
<b>Parameter(s):</b>
</dt>
<dd>
<dl compact>
<dt>
<code>n</code>
</dt>
<dd>
The number of elements to be removed.
</dd>
</dl>
</dd>
</dl>
<dl>
<dt>
<b>Throws:</b>
</dt>
<dd>
Whatever <code>T::operator = (const T&amp;)</code> throws. (Does not throw anything in case of
scalars.)
</dd>
</dl>
<dl>
<dt>
<b>Exception Safety:</b>
</dt>
<dd>
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw
in case of scalars.)
</dd>
</dl>
<dl>
<dt>
<b>Iterator Invalidation:</b>
</dt>
<dd>
Invalidates iterators pointing to the first <code>n</code> erased elements.
</dd>
</dl>
<dl>
<dt>
<b>Complexity:</b>
</dt>
<dd>
Constant (in <code>n</code>) for scalar types; linear for other types.
</dd>
</dl>
<dl>
<dt>
<b>Note:</b>
</dt>
<dd>
This method has been specially designed for types which do not require an explicit destructruction
(e.g. integer, float or a pointer). For these scalar types a call to a destructor is not required which
makes it possible to implement the "erase from beginning" operation with a constant complexity. For
non-sacalar types the complexity is linear (hence the explicit destruction is needed) and the
implementation is actually equivalent to <code><a href=
"#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(begin(), begin() +
n)</a></code>.
</dd>
</dl>
<dl>
<dt>
<b>See Also:</b>
</dt>
<dd>
<code><a href=
"#classboost_1_1circular__buffer_197155de712db1759e1698455b49a0be3">erase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1a96415389509a18bd7d7b5d8e4dda9bd">erase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
</td>
</tr>
<tr>
<td>
<a id="classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7" name=
"classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7"></a><code><b>void erase_end(<a href=
"#classboost_1_1circular__buffer_19ba12c0142a21a7d960877c22fa3ea00">size_type</a> n);</b></code><br>
<br>
Remove last <code>n</code> elements (with constant complexity for scalar types).
<dl>
<dt>
<b>Precondition:</b>
</dt>
<dd>
<code>n &lt;= <a href=
"#classboost_1_1circular__buffer_15fa0edd153e2591dd6bf070eb663ee32">size()</a></code>
</dd>
</dl>
<dl>
<dt>
<b>Effect:</b>
</dt>
<dd>
The <code>n</code> elements at the end of the <code>circular_buffer</code> will be removed.
</dd>
</dl>
<dl>
<dt>
<b>Parameter(s):</b>
</dt>
<dd>
<dl compact>
<dt>
<code>n</code>
</dt>
<dd>
The number of elements to be removed.
</dd>
</dl>
</dd>
</dl>
<dl>
<dt>
<b>Throws:</b>
</dt>
<dd>
Whatever <code>T::operator = (const T&amp;)</code> throws. (Does not throw anything in case of
scalars.)
</dd>
</dl>
<dl>
<dt>
<b>Exception Safety:</b>
</dt>
<dd>
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw
in case of scalars.)
</dd>
</dl>
<dl>
<dt>
<b>Iterator Invalidation:</b>
</dt>
<dd>
Invalidates iterators pointing to the last <code>n</code> erased elements.
</dd>
</dl>
<dl>
<dt>
<b>Complexity:</b>
</dt>
<dd>
Constant (in <code>n</code>) for scalar types; linear for other types.
</dd>
</dl>
<dl>
<dt>
<b>Note:</b>
</dt>
<dd>
This method has been specially designed for types which do not require an explicit destructruction
(e.g. integer, float or a pointer). For these scalar types a call to a destructor is not required which
makes it possible to implement the "erase from end" operation with a constant complexity. For
non-sacalar types the complexity is linear (hence the explicit destruction is needed) and the
implementation is actually equivalent to <code><a href=
"#classboost_1_1circular__buffer_1a96415389509a18bd7d7b5d8e4dda9bd">erase(end() - n, end())</a></code>.
</dd>
</dl>
<dl>
<dt>
<b>See Also:</b>
</dt>
<dd>
<code><a href=
"#classboost_1_1circular__buffer_197155de712db1759e1698455b49a0be3">erase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1a96415389509a18bd7d7b5d8e4dda9bd">erase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1826f5770a40b8b752eb9587378464d1e">clear()</a></code>
</dd>
</dl>
@@ -6511,7 +6749,7 @@ template &lt;class T, class Alloc&gt;
<b>Complexity:</b>
</dt>
<dd>
Linear (in the size of the <code>circular_buffer</code>).
Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
</dd>
</dl>
<dl>
@@ -6527,7 +6765,10 @@ template &lt;class T, class Alloc&gt;
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b6d4ae77d7445f844e30e78592f1e06f">rerase(iterator)</a></code>,
<code><a href="#classboost_1_1circular__buffer_1b0f98ae303584ded5397f067bbfc911f">rerase(iterator,
iterator)</a></code>
iterator)</a></code>, <code><a href=
"#classboost_1_1circular__buffer_1b25d379cf66ace025036a47ddb344abd">erase_begin(size_type)</a></code>,
<code><a href=
"#classboost_1_1circular__buffer_17485ee7f58b01363170114f2123a48d7">erase_end(size_type)</a></code>
</dd>
</dl>
</td>
@@ -7123,6 +7364,23 @@ template &lt;class T, class Alloc&gt;
<a name="relnotes" id="relnotes">Release Notes</a>
</h2>
<dl>
<dd>
<h3>
Boost 1.42
</h3>
</dd>
<dd>
<ul>
<li>Added methods <code>erase_begin(size_type)</code> and <code>erase_end(size_type)</code> with constant
complexity for such types of stored elements which do not need an explicit destruction e.g. <code>int</code>
or <code>double</code>.
</li>
<li>Similarly changed implementation of the <code>clear()</code> method and the destructor so their
complexity is now constant for such types of stored elements which do not require an explicit destruction
(the complexity for other types remains linear).
</li>
</ul>
</dd>
<dd>
<h3>
Boost 1.37

View File

@@ -68,7 +68,7 @@ http://www.boost.org/LICENSE_1_0.txt)
</xsl:apply-templates>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="$current[string-length(normalize-space(briefdescription)) &gt; 0]">
<xsl:for-each select="$current[string-length(normalize-space(briefdescription)) &gt; 0 and normalize-space(briefdescription) != 'no-comment']">
<xsl:apply-templates select="." mode="synopsis"/>
</xsl:for-each>
</xsl:template>
@@ -96,7 +96,7 @@ http://www.boost.org/LICENSE_1_0.txt)
</xsl:template>
<xsl:template name="member-functions-details">
<xsl:for-each select="sectiondef[@kind='public-func']/memberdef[type != '' and string-length(normalize-space(briefdescription)) &gt; 0]">
<xsl:for-each select="sectiondef[@kind='public-func']/memberdef[type != '' and string-length(normalize-space(briefdescription)) &gt; 0 and normalize-space(briefdescription) != 'no-comment']">
<xsl:apply-templates select="." mode="description"/>
</xsl:for-each>
</xsl:template>

View File

@@ -20,6 +20,7 @@
#include <boost/iterator/iterator_traits.hpp>
#include <boost/type_traits/is_stateless.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <algorithm>
#include <utility>
#include <deque>
@@ -33,6 +34,12 @@
#include <stddef.h>
#endif
#if defined(BOOST_NO_STDC_NAMESPACE)
namespace std {
using ::memset;
}
#endif
namespace boost {
/*!
@@ -393,7 +400,7 @@ public:
Does not invalidate any iterators.
\par Complexity
Constant (in the size of the <code>circular_buffer</code>).
\sa <code>operator[]</code>
\sa <code>\link operator[](size_type) operator[] \endlink</code>
*/
reference at(size_type index) {
check_position(index);
@@ -1165,7 +1172,7 @@ public:
Invalidates all iterators pointing to the <code>circular_buffer</code> (including iterators equal to
<code>end()</code>).
\par Complexity
Linear (in the size of the <code>circular_buffer</code>).
Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
\sa <code>clear()</code>
*/
~circular_buffer() {
@@ -1231,7 +1238,8 @@ public:
<code>end()</code>).
\par Complexity
Linear (in the <code>n</code>).
\sa <code>operator=</code>, <code>\link assign(capacity_type, size_type, param_value_type)
\sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
@@ -1260,8 +1268,9 @@ public:
<code>end()</code>).
\par Complexity
Linear (in the <code>n</code>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>, <code>assign(InputIterator, InputIterator)</code>,
\sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
*/
void assign(capacity_type buffer_capacity, size_type n, param_value_type item) {
@@ -1291,8 +1300,8 @@ public:
<code>end()</code>).
\par Complexity
Linear (in the <code>std::distance(first, last)</code>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>,
\sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
@@ -1330,8 +1339,8 @@ public:
Linear (in <code>std::distance(first, last)</code>; in
<code>min[capacity, std::distance(first, last)]</code> if the <code>InputIterator</code> is a
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>,
\sa <code>\link operator=(const circular_buffer&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>
@@ -1805,7 +1814,8 @@ public:
\par Complexity
Linear (in <code>std::distance(pos, end())</code>).
\sa <code>erase(iterator, iterator)</code>, <code>rerase(iterator)</code>,
<code>rerase(iterator, iterator)</code>, <code>clear()</code>
<code>rerase(iterator, iterator)</code>, <code>erase_begin(size_type)</code>,
<code>erase_end(size_type)</code>, <code>clear()</code>
*/
iterator erase(iterator pos) {
BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1842,7 +1852,7 @@ public:
\par Complexity
Linear (in <code>std::distance(first, end())</code>).
\sa <code>erase(iterator)</code>, <code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
<code>clear()</code>
<code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>, <code>clear()</code>
*/
iterator erase(iterator first, iterator last) {
BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1881,7 +1891,8 @@ public:
<code>erase(iterator)</code> if the iterator <code>pos</code> is close to the beginning of the
<code>circular_buffer</code>. (See the <i>Complexity</i>.)
\sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
<code>rerase(iterator, iterator)</code>, <code>clear()</code>
<code>rerase(iterator, iterator)</code>, <code>erase_begin(size_type)</code>,
<code>erase_end(size_type)</code>, <code>clear()</code>
*/
iterator rerase(iterator pos) {
BOOST_CB_ASSERT(pos.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1921,7 +1932,7 @@ public:
<code>erase(iterator, iterator)</code> if <code>std::distance(begin(), first)</code> is lower that
<code>std::distance(last, end())</code>.
\sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>, <code>rerase(iterator)</code>,
<code>clear()</code>
<code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>, <code>clear()</code>
*/
iterator rerase(iterator first, iterator last) {
BOOST_CB_ASSERT(first.is_valid(this)); // check for uninitialized or invalidated iterator
@@ -1947,6 +1958,70 @@ public:
return iterator(this, last.m_it);
}
//! Remove first <code>n</code> elements (with constant complexity for scalar types).
/*!
\pre <code>n \<= size()</code>
\post The <code>n</code> elements at the beginning of the <code>circular_buffer</code> will be removed.
\param n The number of elements to be removed.
\throws Whatever <code>T::operator = (const T&)</code> throws. (Does not throw anything in case of scalars.)
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw in
case of scalars.)
\par Iterator Invalidation
Invalidates iterators pointing to the first <code>n</code> erased elements.
\par Complexity
Constant (in <code>n</code>) for scalar types; linear for other types.
\note This method has been specially designed for types which do not require an explicit destructruction (e.g.
integer, float or a pointer). For these scalar types a call to a destructor is not required which makes
it possible to implement the "erase from beginning" operation with a constant complexity. For non-sacalar
types the complexity is linear (hence the explicit destruction is needed) and the implementation is
actually equivalent to
<code>\link circular_buffer::rerase(iterator, iterator) rerase(begin(), begin() + n)\endlink</code>.
\sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
<code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
<code>erase_end(size_type)</code>, <code>clear()</code>
*/
void erase_begin(size_type n) {
BOOST_CB_ASSERT(n <= size()); // check for n greater than size
#if BOOST_CB_ENABLE_DEBUG
erase_begin(n, false_type());
#else
erase_begin(n, is_scalar<value_type>());
#endif
}
//! Remove last <code>n</code> elements (with constant complexity for scalar types).
/*!
\pre <code>n \<= size()</code>
\post The <code>n</code> elements at the end of the <code>circular_buffer</code> will be removed.
\param n The number of elements to be removed.
\throws Whatever <code>T::operator = (const T&)</code> throws. (Does not throw anything in case of scalars.)
\par Exception Safety
Basic; no-throw if the operation in the <i>Throws</i> section does not throw anything. (I.e. no throw in
case of scalars.)
\par Iterator Invalidation
Invalidates iterators pointing to the last <code>n</code> erased elements.
\par Complexity
Constant (in <code>n</code>) for scalar types; linear for other types.
\note This method has been specially designed for types which do not require an explicit destructruction (e.g.
integer, float or a pointer). For these scalar types a call to a destructor is not required which makes
it possible to implement the "erase from end" operation with a constant complexity. For non-sacalar
types the complexity is linear (hence the explicit destruction is needed) and the implementation is
actually equivalent to
<code>\link circular_buffer::erase(iterator, iterator) erase(end() - n, end())\endlink</code>.
\sa <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
<code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
<code>erase_begin(size_type)</code>, <code>clear()</code>
*/
void erase_end(size_type n) {
BOOST_CB_ASSERT(n <= size()); // check for n greater than size
#if BOOST_CB_ENABLE_DEBUG
erase_end(n, false_type());
#else
erase_end(n, is_scalar<value_type>());
#endif
}
//! Remove all stored elements from the <code>circular_buffer</code>.
/*!
\post <code>size() == 0</code>
@@ -1957,9 +2032,10 @@ public:
Invalidates all iterators pointing to the <code>circular_buffer</code> (except iterators equal to
<code>end()</code>).
\par Complexity
Linear (in the size of the <code>circular_buffer</code>).
Constant (in the size of the <code>circular_buffer</code>) for scalar types; linear for other types.
\sa <code>~circular_buffer()</code>, <code>erase(iterator)</code>, <code>erase(iterator, iterator)</code>,
<code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>
<code>rerase(iterator)</code>, <code>rerase(iterator, iterator)</code>,
<code>erase_begin(size_type)</code>, <code>erase_end(size_type)</code>
*/
void clear() {
destroy_content();
@@ -2011,7 +2087,7 @@ private:
throw_exception(std::length_error("circular_buffer"));
#if BOOST_CB_ENABLE_DEBUG
pointer p = (n == 0) ? 0 : m_alloc.allocate(n, 0);
::memset(p, cb_details::UNINITIALIZED, sizeof(value_type) * n);
std::memset(p, cb_details::UNINITIALIZED, sizeof(value_type) * n);
return p;
#else
return (n == 0) ? 0 : m_alloc.allocate(n, 0);
@@ -2054,7 +2130,7 @@ private:
m_alloc.destroy(p);
#if BOOST_CB_ENABLE_DEBUG
invalidate_iterators(iterator(this, p));
::memset(p, cb_details::UNINITIALIZED, sizeof(value_type));
std::memset(p, cb_details::UNINITIALIZED, sizeof(value_type));
#endif
}
@@ -2066,6 +2142,20 @@ private:
//! Destroy the whole content of the circular buffer.
void destroy_content() {
#if BOOST_CB_ENABLE_DEBUG
destroy_content(false_type());
#else
destroy_content(is_scalar<value_type>());
#endif
}
//! Specialized destroy_content method.
void destroy_content(const true_type&) {
m_first = add(m_first, size());
}
//! Specialized destroy_content method.
void destroy_content(const false_type&) {
for (size_type ii = 0; ii < size(); ++ii, increment(m_first))
destroy_item(m_first);
}
@@ -2564,6 +2654,30 @@ private:
m_last = sub(m_last, n - construct);
m_size += construct;
}
//! Specialized erase_begin method.
void erase_begin(size_type n, const true_type&) {
m_first = add(m_first, n);
m_size -= n;
}
//! Specialized erase_begin method.
void erase_begin(size_type n, const false_type&) {
iterator b = begin();
rerase(b, b + n);
}
//! Specialized erase_end method.
void erase_end(size_type n, const true_type&) {
m_last = sub(m_last, n);
m_size -= n;
}
//! Specialized erase_end method.
void erase_end(size_type n, const false_type&) {
iterator e = end();
erase(e - n, e);
}
};
// Non-member functions

View File

@@ -189,9 +189,9 @@ public:
\par Complexity
Linear (in <code>min[size(), capacity_ctrl.%capacity()]</code>).
\note To explicitly clear the extra allocated memory use the <b>shrink-to-fit</b> technique:<br><br>
<code>boost::%circular_buffer_space_optimized\<int\> cb(1000);<br>
<code>%boost::%circular_buffer_space_optimized\<int\> cb(1000);<br>
...<br>
boost::%circular_buffer_space_optimized\<int\>(cb).swap(cb);</code><br><br>
%boost::%circular_buffer_space_optimized\<int\>(cb).swap(cb);</code><br><br>
For more information about the shrink-to-fit technique in STL see
<a href="http://www.gotw.ca/gotw/054.htm">http://www.gotw.ca/gotw/054.htm</a>.
\sa <code>rset_capacity(const capacity_type&)</code>,
@@ -513,6 +513,12 @@ public:
*/
~circular_buffer_space_optimized();
//! no-comment
void erase_begin(size_type n);
//! no-comment
void erase_end(size_type n);
#endif // #if defined(BOOST_CB_NEVER_DEFINED)
//! The assign operator.
@@ -565,7 +571,8 @@ public:
equal to <code>end()</code>).
\par Complexity
Linear (in the <code>n</code>).
\sa <code>operator=</code>, <code>\link assign(capacity_type, size_type, param_value_type)
\sa <code>\link operator=(const circular_buffer_space_optimized&) operator=\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
@@ -597,8 +604,9 @@ public:
equal to <code>end()</code>).
\par Complexity
Linear (in the <code>n</code>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>, <code>assign(InputIterator, InputIterator)</code>,
\sa <code>\link operator=(const circular_buffer_space_optimized&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
*/
void assign(capacity_type capacity_ctrl, size_type n, param_value_type item) {
@@ -630,8 +638,8 @@ public:
equal to <code>end()</code>).
\par Complexity
Linear (in the <code>std::distance(first, last)</code>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>,
\sa <code>\link operator=(const circular_buffer_space_optimized&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(capacity_type, InputIterator, InputIterator)</code>
@@ -672,8 +680,8 @@ public:
Linear (in <code>std::distance(first, last)</code>; in
<code>min[capacity_ctrl.%capacity(), std::distance(first, last)]</code> if the <code>InputIterator</code>
is a <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>).
\sa <code>operator=</code>, <code>\link assign(size_type, param_value_type)
assign(size_type, const_reference)\endlink</code>,
\sa <code>\link operator=(const circular_buffer_space_optimized&) operator=\endlink</code>,
<code>\link assign(size_type, param_value_type) assign(size_type, const_reference)\endlink</code>,
<code>\link assign(capacity_type, size_type, param_value_type)
assign(capacity_type, size_type, const_reference)\endlink</code>,
<code>assign(InputIterator, InputIterator)</code>
@@ -1252,11 +1260,7 @@ private:
ensure_reserve(new_capacity, new_size));
}
#if BOOST_CB_ENABLE_DEBUG
# if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(70190006))
this->invalidate_iterators_except(end());
# else
invalidate_iterators_except(end());
# endif
#endif
}
@@ -1276,11 +1280,7 @@ private:
circular_buffer<T, Alloc>::set_capacity(
ensure_reserve(new_capacity, size()));
#if BOOST_CB_ENABLE_DEBUG
# if BOOST_WORKAROUND(__DECCXX_VER, BOOST_TESTED_AT(70190006))
this->invalidate_iterators_except(end());
# else
invalidate_iterators_except(end());
# endif
#endif
}

View File

@@ -1 +0,0 @@
boost_module (circular_buffer DEPENDS config thread)

View File

@@ -1,13 +0,0 @@
#
# Copyright Troy D. Straszheim
#
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt
#
boost_additional_test_dependencies(circular_buffer BOOST_DEPENDS test )
boost_test_run(base_test SINGLE_THREADED)
boost_test_run(space_optimized_test SINGLE_THREADED)
boost_test_run(soft_iterator_invalidation SINGLE_THREADED)
boost_test_compile(bounded_buffer_comparison)

View File

@@ -25,5 +25,6 @@ test-suite "circular_buffer"
: [ run base_test.cpp : <threading>single : ]
[ run space_optimized_test.cpp : <threading>single : ]
[ run soft_iterator_invalidation.cpp : <threading>single : ]
[ run constant_erase_test.cpp : <threading>single : ]
[ compile bounded_buffer_comparison.cpp : <threading>multi : ]
;

View File

@@ -0,0 +1,187 @@
// Special tests for erase_begin, erase_end and clear methods.
// Copyright (c) 2009 Jan Gaspar
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#define BOOST_CB_DISABLE_DEBUG
#include "test.hpp"
int MyInteger::ms_exception_trigger = 0;
int InstanceCounter::ms_count = 0;
void erase_begin_test() {
circular_buffer<int> cb1(5);
cb1.push_back(1);
cb1.push_back(2);
cb1.push_back(3);
cb1.push_back(4);
cb1.push_back(5);
cb1.push_back(6);
circular_buffer<int>::pointer p = &cb1[0];
cb1.erase_begin(2);
BOOST_CHECK(cb1.size() == 3);
BOOST_CHECK(cb1[0] == 4);
BOOST_CHECK(cb1[1] == 5);
BOOST_CHECK(cb1[2] == 6);
cb1.erase_begin(3);
BOOST_CHECK(cb1.empty());
BOOST_CHECK(*p == 2);
BOOST_CHECK(*(p + 1) == 3);
BOOST_CHECK(*(p + 2) == 4);
cb1.push_back(10);
cb1.push_back(11);
cb1.push_back(12);
BOOST_CHECK(cb1.size() == 3);
BOOST_CHECK(cb1[0] == 10);
BOOST_CHECK(cb1[1] == 11);
BOOST_CHECK(cb1[2] == 12);
circular_buffer<InstanceCounter> cb2(5, InstanceCounter());
BOOST_CHECK(cb2.size() == 5);
BOOST_CHECK(InstanceCounter::count() == 5);
cb2.erase_begin(2);
BOOST_CHECK(cb2.size() == 3);
BOOST_CHECK(InstanceCounter::count() == 3);
circular_buffer<MyInteger> cb3(5);
cb3.push_back(1);
cb3.push_back(2);
cb3.push_back(3);
cb3.push_back(4);
cb3.push_back(5);
cb3.push_back(6);
cb3.erase_begin(2);
BOOST_CHECK(cb3.size() == 3);
BOOST_CHECK(cb3[0] == 4);
BOOST_CHECK(cb3[1] == 5);
BOOST_CHECK(cb3[2] == 6);
}
void erase_end_test() {
circular_buffer<int> cb1(5);
cb1.push_back(1);
cb1.push_back(2);
cb1.push_back(3);
cb1.push_back(4);
cb1.push_back(5);
cb1.push_back(6);
circular_buffer<int>::pointer p = &cb1[3];
cb1.erase_end(2);
BOOST_CHECK(cb1.size() == 3);
BOOST_CHECK(cb1[0] == 2);
BOOST_CHECK(cb1[1] == 3);
BOOST_CHECK(cb1[2] ==4);
cb1.erase_end(3);
BOOST_CHECK(cb1.empty());
BOOST_CHECK(*p == 5);
BOOST_CHECK(*(p - 1) == 4);
BOOST_CHECK(*(p - 2) == 3);
cb1.push_back(10);
cb1.push_back(11);
cb1.push_back(12);
BOOST_CHECK(cb1.size() == 3);
BOOST_CHECK(cb1[0] == 10);
BOOST_CHECK(cb1[1] == 11);
BOOST_CHECK(cb1[2] == 12);
circular_buffer<InstanceCounter> cb2(5, InstanceCounter());
BOOST_CHECK(cb2.size() == 5);
BOOST_CHECK(InstanceCounter::count() == 5);
cb2.erase_end(2);
BOOST_CHECK(cb2.size() == 3);
BOOST_CHECK(InstanceCounter::count() == 3);
circular_buffer<MyInteger> cb3(5);
cb3.push_back(1);
cb3.push_back(2);
cb3.push_back(3);
cb3.push_back(4);
cb3.push_back(5);
cb3.push_back(6);
cb3.erase_end(2);
BOOST_CHECK(cb3.size() == 3);
BOOST_CHECK(cb3[0] == 2);
BOOST_CHECK(cb3[1] == 3);
BOOST_CHECK(cb3[2] == 4);
}
void clear_test() {
circular_buffer<int> cb1(5);
cb1.push_back(1);
cb1.push_back(2);
cb1.push_back(3);
cb1.push_back(4);
cb1.push_back(5);
cb1.push_back(6);
circular_buffer<int>::pointer p = &cb1[0];
cb1.clear();
BOOST_CHECK(cb1.empty());
BOOST_CHECK(*p == 2);
BOOST_CHECK(*(p + 1) == 3);
BOOST_CHECK(*(p + 2) == 4);
BOOST_CHECK(*(p + 3) == 5);
BOOST_CHECK(*(p - 1) == 6);
circular_buffer<InstanceCounter> cb2(5, InstanceCounter());
BOOST_CHECK(cb2.size() == 5);
BOOST_CHECK(InstanceCounter::count() == 5);
cb2.clear();
BOOST_CHECK(cb2.empty());
BOOST_CHECK(InstanceCounter::count() == 0);
circular_buffer<MyInteger> cb3(5);
cb3.push_back(1);
cb3.push_back(2);
cb3.push_back(3);
cb3.push_back(4);
cb3.push_back(5);
cb3.push_back(6);
cb3.clear();
BOOST_CHECK(cb3.empty());
}
// test main
test_suite* init_unit_test_suite(int /*argc*/, char* /*argv*/[]) {
test_suite* tests = BOOST_TEST_SUITE("Unit tests for erase_begin/end and clear methods of the circular_buffer.");
tests->add(BOOST_TEST_CASE(&erase_begin_test));
tests->add(BOOST_TEST_CASE(&erase_end_test));
tests->add(BOOST_TEST_CASE(&clear_test));
return tests;
}