From 39f497ee192e2ea338eaf4563a8a4b7ea7fbaf7c Mon Sep 17 00:00:00 2001 From: Jan Gaspar Date: Wed, 27 Apr 2005 10:44:44 +0000 Subject: [PATCH] Fix for VC6, updated TODO, source formatting. [SVN r2592] --- doc/Doxyfile | 78 ++-- doc/TODO | 44 +- doc/circular_buffer.html | 488 +++++++++++----------- doc/circular_buffer.xslt | 20 +- doc/circular_buffer_space_optimized.html | 206 ++++----- doc/circular_buffer_space_optimized.xslt | 10 +- doc/copy.xslt | 10 +- doc/doxygen2html.xslt | 44 +- doc/html2xhtml.xslt | 4 +- doc/unblank.sh | 24 +- doc/update_srcdoc.sh | 10 +- include/boost/circular_buffer/adaptor.hpp | 2 +- include/boost/circular_buffer/base.hpp | 30 +- include/boost/circular_buffer/debug.hpp | 220 +++++----- include/boost/circular_buffer/details.hpp | 4 +- index.html | 14 +- test/common.cpp | 92 ++-- test/test.hpp | 6 +- 18 files changed, 677 insertions(+), 629 deletions(-) diff --git a/doc/Doxyfile b/doc/Doxyfile index 064da5d..c571fcb 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -11,12 +11,12 @@ OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = +ABBREVIATE_BRIEF = ALWAYS_DETAILED_SEC = YES INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = NO -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO @@ -24,7 +24,7 @@ DETAILS_AT_TOP = NO INHERIT_DOCS = YES DISTRIBUTE_GROUP_DOC = NO TAB_SIZE = 8 -ALIASES = +ALIASES = OPTIMIZE_OUTPUT_FOR_C = NO OPTIMIZE_OUTPUT_JAVA = NO SUBGROUPING = YES @@ -52,11 +52,11 @@ GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = +ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = NO SHOW_DIRECTORIES = YES -FILE_VERSION_FILTER = +FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- @@ -66,7 +66,7 @@ WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = YES WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- @@ -76,13 +76,13 @@ RECURSIVE = YES EXCLUDE = ../../../boost/circular_buffer/debug.hpp \ ../../../boost/circular_buffer/details.hpp EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing @@ -98,20 +98,20 @@ VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 -IGNORE_PREFIX = +IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = NO HTML_OUTPUT = html HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = +CHM_FILE = +HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO @@ -128,8 +128,8 @@ LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = +EXTRA_PACKAGES = +LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO @@ -141,8 +141,8 @@ GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- @@ -155,8 +155,8 @@ MAN_LINKS = NO #--------------------------------------------------------------------------- GENERATE_XML = YES XML_OUTPUT = . -XML_SCHEMA = -XML_DTD = +XML_SCHEMA = +XML_DTD = XML_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output @@ -168,29 +168,29 @@ GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = +PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- -# Configuration options related to the preprocessor +# Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = NO MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- -# Configuration::additions related to external references +# Configuration::additions related to external references #--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = +TAGFILES = +GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = NO -PERL_PATH = +PERL_PATH = #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = NO HIDE_UNDOC_RELATIONS = NO @@ -206,8 +206,8 @@ CALL_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = +DOT_PATH = +DOTFILE_DIRS = MAX_DOT_GRAPH_WIDTH = 1024 MAX_DOT_GRAPH_HEIGHT = 1024 MAX_DOT_GRAPH_DEPTH = 0 @@ -216,6 +216,6 @@ DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- -# Configuration::additions related to the search engine +# Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO diff --git a/doc/TODO b/doc/TODO index 1c137c1..6f422bf 100644 --- a/doc/TODO +++ b/doc/TODO @@ -6,7 +6,8 @@ t02 DONE docs: paragraph "Rationale": remove the "producer-consumer" usage (it is confusing) -t03 docs: "Friend Functions" should be rather "Standalone Functions" +t03 DONE + docs: "Friend Functions" should be rather "Standalone Functions" and should mention swap, <=, >= as well t04 DONE @@ -21,9 +22,11 @@ t06 docs: define the element type requirements (as a precondition) for every t07 adaptor.hpp: fix needed to compile the test with BCB 6.4 -t08 base_test.cpp: fix needed to compile with VC 6.5 +t08 DONE + base_test.cpp: fix needed to compile with VC 6.5 -t09 fix needed to compile the tests with GCC 3.4 +t09 DONE + fix needed to compile the tests with GCC 3.4 t10 docs: define exception safety for every method "Guarantee of basic exception safety" as a design criteria for the whole @@ -44,7 +47,7 @@ t14 docs: explicitly document methods which do not throw any exception, e.g. "Exceptions: none" t15 rename the data() method to something meaningful concerning its mutation - status; mention its linear complexity in the docs REFINE!!! + status (e.g to_array); mention its linear complexity in the docs t16 docs: document that push_back() or other methods that they can choose NOT to insert something -> in general document the boundary conditions @@ -55,16 +58,20 @@ t17 docs: delete the "Semantics" paragraph and move its content directly t18 Perhaps in addition to a data() function, it would be useful if the container provided constant-time access to the data as two arrays. - Perhaps something like std::pair first_range() and - std::pair second_range(). REFINE!!! + Perhaps something like std::pair array_1() and + std::pair array_2(). (Consider also returning of + std::pair.) -t19 docs: merge the source documentation with the main documentation +t19 DONE + docs: merge the source documentation with the main documentation t20 docs: define requirements on the Alloc type parameter -t21 docs: consider better documentation for the "overwrite" term +t21 docs: consider better documentation for the "overwrite" term; add glossary + section -t22 implement a "hook" for the overwrite operation (maybe as an adaptor) +t22 DEPRIVED + implement a "hook" for the overwrite operation (maybe as an adaptor) t23 amend the source code according to the formal review (line 1578); use the new iterator if possible @@ -75,29 +82,31 @@ t24 ammend the test in order to compile with the new iterator if really t25 add constructor taking just two iterators as a parameter t26 change the current implementation of "overwrite" operation -> overwrite - will be equivalent to assign; adaptor can change the meaning of overwrite - operation (to destruct/construct) REFINE!!! + will be equivalent to assign t27 docs: apply the DefaultConstructible and Assignable type requirements t28 docs: the difference between resize() and set_capacity() should be mentioned more explicitly -t29 add rerase method REFINE!!! +t29 DONE + add rerase methods t30 The insert() function has its rinsert() counterpart. The same issue for resize and set_capacity is solved with the boolean parameter - remove_front, which is not consistent. CONSIDER!!! + remove_front, which is not consistent. t31 docs: "... According to the semantics of rinsert, insertion overwrites front-most items as necessary ..." should probably read "back-most items" if this is a valid english word -t32 CONSIDER!!! reimplementing the comparison functions (line 3801) +t32 DEPRIVED + reimplementing the comparison functions (line 3801) t33 fix needed to compile the tests with Comeau 4.3.0 compiler -t34 CONSIDER!!! throwing exception when push_back() to empty container +t34 DEPRIVED + consider throwing exception when pop_back() an empty container t35 docs: there should be warning for data() documentation that the returned pointer gets very easily invalidated @@ -124,6 +133,11 @@ t42 documentation may add some rationale on its internal data structures t43 adaptor.hpp: apply workaround for borland (line 5764) +t44 add some "post tests" after testing non-const methods (such as inserting + an element into container which is tested for erase) + +t55 ammend the file header text (remove the reference to the accompanying file + LICENSE_1_0.txt) ------------------------------------------------------------------------------- diff --git a/doc/circular_buffer.html b/doc/circular_buffer.html index e52d492..e516e7c 100644 --- a/doc/circular_buffer.html +++ b/doc/circular_buffer.html @@ -2,70 +2,70 @@ - + Templated Circular Buffer Container - - +

Templated Circular Buffer Container

+

circular_buffer<T, Alloc>

+ + +
-

Templated Circular Buffer Container

-

circular_buffer<T, Alloc>

-
Boost
Boost

Contents

- Description
- Simple Example
- Synopsis
- Rationale
- Header files
- Modeled concepts
- Template Parameters
- Public Types
- Constructors & Destructor
- Public Member Functions
- Standalone Functions
- Semantics
- Caveats
- Debug Support
- Example
- Notes
- See also
- Ideas for Future Improvements
- Acknowledgments + Description
+ Simple Example
+ Synopsis
+ Rationale
+ Header files
+ Modeled concepts
+ Template Parameters
+ Public Types
+ Constructors & Destructor
+ Public Member Functions
+ Standalone Functions
+ Semantics
+ Caveats
+ Debug Support
+ Example
+ Notes
+ See also
+ Ideas for Future Improvements
+ Acknowledgments - + +
Circular Buffer
- +
- -
Figure:The circular buffer (for someone known as ring or cyclic buffer).
+
The circular buffer (for someone known as ring or cyclic buffer).
- +

Description

-

The circular_buffer container provides fixed capacity storage with - constant time insertion and removal of elements at each end of a circular - buffer. When the capacity of the circular_buffer is exhausted, - inserted elements will cause elements at the opposite end to be overwritten (see the Figure). - The circular_buffer only allocates memory when - created, when the capacity is adjusted explicitly, or as necessary to - accommodate a resizing or assign operation. (There is also a circular_buffer_space_optimized - available. It is an adaptor of the circular_buffer - which does not allocate memory at once when created rather it allocates memory as needed.) -

+

The circular_buffer container provides fixed capacity storage with + constant time insertion and removal of elements at each end of a circular + buffer. When the capacity of the circular_buffer is exhausted, + inserted elements will cause elements at the opposite end to be overwritten (see the Figure). + The circular_buffer only allocates memory when + created, when the capacity is adjusted explicitly, or as necessary to + accommodate a resizing or assign operation. (There is also a circular_buffer_space_optimized + available. It is an adaptor of the circular_buffer + which does not allocate memory at once when created rather it allocates memory as needed.) +

Simple Example

A brief example using the circular_buffer: -

+

   #include <boost/circular_buffer.hpp>
 
    int main(int argc, char* argv[]) {
@@ -79,7 +79,7 @@
 
       // The buffer is full now, pushing subsequent
       // elements will overwrite the front-most elements.
-      
+
       cb.push_back(4);  // Overwrite 1 with 4.
       cb.push_back(5);  // Overwrite 2 with 5.
 
@@ -125,11 +125,11 @@ public:
    typedef typename Alloc::value_type value_type;
 
    template <class InputIterator>
-      circular_buffer(size_type capacity, 
-         InputIterator first, InputIterator last, 
+      circular_buffer(size_type capacity,
+         InputIterator first, InputIterator last,
          const allocator_type& alloc = allocator_type());
    circular_buffer(const circular_buffer<T,Alloc>& cb);
-   circular_buffer(size_type capacity, 
+   circular_buffer(size_type capacity,
       value_type item, const allocator_type& alloc = allocator_type());
    explicit circular_buffer(size_type capacity, const allocator_type& alloc = allocator_type());
    ~circular_buffer();
@@ -210,84 +210,84 @@ template <class T, class Alloc>
     

Rationale

-

A contiguous region of memory utilized as a circular buffer has several unique - and useful characteristics: -

+

A contiguous region of memory utilized as a circular buffer has several unique + and useful characteristics: +

  1. - Fixed memory use and no implicit or unexpected memory - allocation. - + Fixed memory use and no implicit or unexpected memory + allocation. +
  2. - Fast constant-time insertion and removal of elements - from the front and back. - + Fast constant-time insertion and removal of elements + from the front and back. +
  3. - Fast constant-time random access of elements. - + Fast constant-time random access of elements. +
  4. - Suitability for real-time and performance critical applications. -
  5. -
+ Suitability for real-time and performance critical applications. + +

The circular_buffer container provides a similar interface to std::vector, - std::deque and std::list including push, - pop, insert, erase, iterators and - compatibility with std algorithms. -

+ std::deque and std::list including push, + pop, insert, erase, iterators and + compatibility with std algorithms. +

Possible applications of the circular_buffer include: -

+

  • - Storage of the most recently received samples, - overwriting the oldest as new samples arrive. - + Storage of the most recently received samples, + overwriting the oldest as new samples arrive. +
  • - Efficient fixed capacity FIFO (First In, First Out) - queue. - + Efficient fixed capacity FIFO (First In, First Out) + queue. +
  • - Efficient fixed capacity LIFO (Last In, First Out) queue. -
  • -
-

The design of the circular_buffer container is guided by the - following principles: -

+ Efficient fixed capacity LIFO (Last In, First Out) queue. + + +

The design of the circular_buffer container is guided by the + following principles: +

  1. - Maximum efficiency for - envisaged applications. + Maximum efficiency for + envisaged applications.
  2. - Suitable for general purpose use. + Suitable for general purpose use.
  3. - Interoperable with other std containers and algorithms. + Interoperable with other std containers and algorithms.
  4. - The behaviour of the buffer as intuitive as possible. + The behaviour of the buffer as intuitive as possible.
  5. - Suitable for specialization by means of adaptors. (The circular_buffer_space_optimized - is such an example of the adaptor.) + Suitable for specialization by means of adaptors. (The circular_buffer_space_optimized + is such an example of the adaptor.)
  6. - Guarantee of basic exception safety.
  7. + Guarantee of basic exception safety.

Header files

- The circular_buffer is defined in the file + The circular_buffer is defined in the file boost/circular_buffer.hpp. There is also a forward declaration for the circular_buffer in the header file boost/circular_buffer_fwd.hpp. -

+

Modeled concepts

-

Random Access - Container, - Front Insertion Sequence, - Back Insertion Sequence, - Assignable (SGI specific), - Equality Comparable, - LessThan Comparable (SGI specific) -

+

Random Access + Container, + Front Insertion Sequence, + Back Insertion Sequence, + Assignable (SGI specific), + Equality Comparable, + LessThan Comparable (SGI specific) +

Template Parameters

@@ -453,7 +453,7 @@ The type of the elements stored in the circular buffer. template <class InputIterator>
    - circular_buffer(size_type capacity,
    + circular_buffer(size_type capacity,
       InputIterator first, InputIterator last,
       const allocator_type& alloc = allocator_type());

@@ -516,7 +516,7 @@ Create a full circular buffer with a given capacity and filled with copies of Postcondition: -(*this).size() +(*this).size() == capacity && (*this)[0] == (*this)[1] == ... == (*this).back() == item @@ -575,7 +575,7 @@ Destructor. - template <class InputIterator>
    + template <class InputIterator>
    void assign(InputIterator first, InputIterator last);

@@ -802,7 +802,7 @@ Erase all the stored elements.
Return pointer to data stored in the circular buffer as a continuous array of values.
-
This method can be useful e.g. when passing the stored data into the legacy C API. +
This method can be useful e.g. when passing the stored data into the legacy C API. @@ -1063,7 +1063,7 @@ Return the allocator.
template <class InputIterator>
    - void insert(iterator pos, + void insert(iterator pos, InputIterator first, InputIterator last);

@@ -1559,7 +1559,7 @@ Change the size of the circular buffer.
template <class InputIterator>
    - void rinsert(iterator pos, + void rinsert(iterator pos, InputIterator first, InputIterator last);

@@ -1775,7 +1775,7 @@ Swap the contents of two circular buffers. - template <class T, class Alloc>
    + template <class T, class Alloc>
    bool operator!=(const circular_buffer<T,Alloc>& lhs, const circular_buffer<T,Alloc>& rhs);

@@ -1795,7 +1795,7 @@ Test two circular buffers for non-equality. - template <class T, class Alloc>
    + template <class T, class Alloc>
    bool operator<(const circular_buffer<T,Alloc>& lhs, const circular_buffer<T,Alloc>& rhs);

@@ -1815,7 +1815,7 @@ Lexicographical comparison. - template <class T, class Alloc>
    + template <class T, class Alloc>
    bool operator<=(const circular_buffer<T,Alloc>& lhs, const circular_buffer<T,Alloc>& rhs);

@@ -1835,7 +1835,7 @@ Lexicographical comparison. - template <class T, class Alloc>
    + template <class T, class Alloc>
    bool operator==(const circular_buffer<T,Alloc>& lhs, const circular_buffer<T,Alloc>& rhs);

@@ -1855,7 +1855,7 @@ Test two circular buffers for equality. - template <class T, class Alloc>
    + template <class T, class Alloc>
    bool operator>(const circular_buffer<T,Alloc>& lhs, const circular_buffer<T,Alloc>& rhs);

@@ -1875,7 +1875,7 @@ Lexicographical comparison. - template <class T, class Alloc>
    + template <class T, class Alloc>
    bool operator>=(const circular_buffer<T,Alloc>& lhs, const circular_buffer<T,Alloc>& rhs);

@@ -1895,7 +1895,7 @@ Lexicographical comparison. - template <class T, class Alloc>
    + template <class T, class Alloc>
    void swap(circular_buffer<T,Alloc>& lhs, circular_buffer<T,Alloc>& rhs);

@@ -1916,145 +1916,145 @@ Swap the contents of two circular buffers. Semantics

The behaviour of insertion for circular_buffer is as follows: -

+

  • - The capacity of a circular_buffer remains fixed unless adjusted - via set_capacity or resize. - + The capacity of a circular_buffer remains fixed unless adjusted + via set_capacity or resize. +
  • - insert will - overwrite front elements as necessary. - + insert will + overwrite front elements as necessary. +
  • - rinsert will overwrite back elements as necessary. -
  • -
+ rinsert will overwrite back elements as necessary. + +

The behaviour of resizing a circular_buffer is as follows: -

+

  • - The capacity will be adjusted to accommodate a resize. (The - capacity can be only increased, not decreased.) -
  • -
+ The capacity will be adjusted to accommodate a resize. (The + capacity can be only increased, not decreased.) + +

The behaviour of assigning to a circular_buffer is as follows: -

+

  • - The capacity will be adjusted to accommodate an assign. (The - capacity can be only increased, not decreased.) -
  • -
-

The rules for iterator (and result of data()) - invalidation for circular_buffer are as follows: -

+ The capacity will be adjusted to accommodate an assign. (The + capacity can be only increased, not decreased.) + + +

The rules for iterator (and result of data()) + invalidation for circular_buffer are as follows: +

  • - insert at the end of the circular_buffer (including - push_back) does not invalidate any iterator except - the case the iterator points to the overwritten element. - + insert at the end of the circular_buffer (including + push_back) does not invalidate any iterator except + the case the iterator points to the overwritten element. +
  • - rinsert at the beginning of the circular_buffer (including - push_front) does not invalidate any iterator - except the case the iterator points to the overwritten element. - + rinsert at the beginning of the circular_buffer (including + push_front) does not invalidate any iterator + except the case the iterator points to the overwritten element. +
  • - insert in the middle of the circular_buffer invalidates - iterators pointing to the elements at the insertion point and behind the - insertion point. It also invalidates iterators pointing to the overwritten - element(s). - + insert in the middle of the circular_buffer invalidates + iterators pointing to the elements at the insertion point and behind the + insertion point. It also invalidates iterators pointing to the overwritten + element(s). +
  • - rinsert in the middle of the circular_buffer invalidates - iterators pointing to the elements before the insertion point and iterators - pointing to the overwritten element(s). - + rinsert in the middle of the circular_buffer invalidates + iterators pointing to the elements before the insertion point and iterators + pointing to the overwritten element(s). +
  • - erase at the end of the circular_buffer (including pop_back) invalidates only iterators pointing to - the erased element(s). - + erase at the end of the circular_buffer (including pop_back) invalidates only iterators pointing to + the erased element(s). +
  • - pop_front - invalidates only iterators pointing to the erased element. - + pop_front + invalidates only iterators pointing to the erased element. +
  • - erase at the beginning or in the middle of the circular_buffer invalidates iterators pointing to - the erased element(s) and iterators pointing to the elements behind the erase - point. - + erase at the beginning or in the middle of the circular_buffer invalidates iterators pointing to + the erased element(s) and iterators pointing to the elements behind the erase + point. +
  • - data, set_capacity, resize, operator=, - assign, swap and clear invalidate all - iterators pointing to the circular_buffer. -
  • -
-

In addition to the preceding rules the iterators get also invalidated due to - overwritting (e.g. iterator pointing to the front-most element gets invalidated - when inserting into the full circular_buffer). They get - invalidated in that sense they do not point to the same element as before but - they do still point to the same valid place in the memory. If you want - to rely on this feature you have to turn of the Debug Support - otherwise an assertion will report an error if such invalidated iterator is used.

+ data, set_capacity, resize, operator=, + assign, swap and clear invalidate all + iterators pointing to the circular_buffer. + + +

In addition to the preceding rules the iterators get also invalidated due to + overwritting (e.g. iterator pointing to the front-most element gets invalidated + when inserting into the full circular_buffer). They get + invalidated in that sense they do not point to the same element as before but + they do still point to the same valid place in the memory. If you want + to rely on this feature you have to turn of the Debug Support + otherwise an assertion will report an error if such invalidated iterator is used.

Caveats

-

The circular_buffer should not be used for storing pointers to - dynamically allocated objects. When a circular_buffer becomes - full, further insertion will overwrite the stored pointers - resulting in a memory - leak. One recommend alternative is the use of smart pointers [1]. - (Any container of std::auto_ptr is considered particularly - hazardous. [2]) -

-

Elements inserted near the front of a full circular_buffer can be - lost. According to the semantics of insert, - insertion overwrites front-most items as necessary - possibly including - elements currently being inserted at the front of the buffer. - Conversely, push_front to a full circular_buffer is - guaranteed to overwrite the back-most element. -

-

Elements inserted near the back of a full circular_buffer can be - lost. According to the semantics of rinsert, - insertion overwrites front-most items as necessary - possibly including - elements currently being inserted at the back of the buffer. Conversely, - push_back to a full circular_buffer is guaranteed to - overwrite the front-most element. -

-

While internals of a circular_buffer are circular, iterators are not. - Iterators of a circular_buffer are only valid for the range [begin(), - end()]. E.g. iterators (begin() - 1) and (end() + 1) - are invalid. -

+

The circular_buffer should not be used for storing pointers to + dynamically allocated objects. When a circular_buffer becomes + full, further insertion will overwrite the stored pointers - resulting in a memory + leak. One recommend alternative is the use of smart pointers [1]. + (Any container of std::auto_ptr is considered particularly + hazardous. [2]) +

+

Elements inserted near the front of a full circular_buffer can be + lost. According to the semantics of insert, + insertion overwrites front-most items as necessary - possibly including + elements currently being inserted at the front of the buffer. + Conversely, push_front to a full circular_buffer is + guaranteed to overwrite the back-most element. +

+

Elements inserted near the back of a full circular_buffer can be + lost. According to the semantics of rinsert, + insertion overwrites front-most items as necessary - possibly including + elements currently being inserted at the back of the buffer. Conversely, + push_back to a full circular_buffer is guaranteed to + overwrite the front-most element. +

+

While internals of a circular_buffer are circular, iterators are not. + Iterators of a circular_buffer are only valid for the range [begin(), + end()]. E.g. iterators (begin() - 1) and (end() + 1) + are invalid. +

Debug Support

In order to help a programmer to avoid and find common bugs, the circular_buffer - contains a kind of debug support.

+ contains a kind of debug support.

- The circular_buffer maintains a list of valid iterators. As soon - as any element gets destroyed all iterators pointing to this element are - removed from this list and explicitly invalidated (an invalidation flag is - set). The debug support also consists of many assertions (BOOST_ASSERT - macros) which ensure the circular_buffer and its iterators are - used in the correct manner at runtime. In case an invalid iterator is used the - assertion will report an error. The connection of explicit iterator - invalidation and assertions makes a very robust debug technique which catches - most of the errors.

-

Moreover, the uninitialized memory allocated by circular_buffer is - filled with the value 0xcc in the debug mode. This can help the - programmer when debugging the code to recognize the initialized memory from the - uninitialized. For details refer the - source code. -

+ The circular_buffer maintains a list of valid iterators. As soon + as any element gets destroyed all iterators pointing to this element are + removed from this list and explicitly invalidated (an invalidation flag is + set). The debug support also consists of many assertions (BOOST_ASSERT + macros) which ensure the circular_buffer and its iterators are + used in the correct manner at runtime. In case an invalid iterator is used the + assertion will report an error. The connection of explicit iterator + invalidation and assertions makes a very robust debug technique which catches + most of the errors.

+

Moreover, the uninitialized memory allocated by circular_buffer is + filled with the value 0xcc in the debug mode. This can help the + programmer when debugging the code to recognize the initialized memory from the + uninitialized. For details refer the + source code. +

The debug support is enabled only in the debug mode (when the NDEBUG - is not defined). It can also be explicitly disabled by defining BOOST_DISABLE_CB_DEBUG - macro.

+ is not defined). It can also be explicitly disabled by defining BOOST_DISABLE_CB_DEBUG + macro.

Example

The following example includes various usage of the circular_buffer. -

+

   #include <boost/circular_buffer.hpp>
    #include <numeric>
    #include <assert.h>
@@ -2062,7 +2062,7 @@ Swap the contents of two circular buffers.         
    int main(int argc, char* argv[])
    {
       // create a circular buffer of capacity 3
-      boost::circular_buffer<int> cb(3); 
+      boost::circular_buffer<int> cb(3);
 
       // insert some elements into the circular buffer
       cb.push_back(1);
@@ -2090,35 +2090,35 @@ Swap the contents of two circular buffers.         
       assert(cb.full());
       assert(cb.size() == 3);
       assert(cb.capacity() == 3);
-      
+
       return 0;
    }
 
-

The circular_buffer has a capacity of three int. - Therefore, the size of the buffer will not exceed three. The - accumulate algorithm evaluates the sum of the stored - elements. The semantics of the circular_buffer can be inferred from - the assertions. -

+

The circular_buffer has a capacity of three int. + Therefore, the size of the buffer will not exceed three. The + accumulate algorithm evaluates the sum of the stored + elements. The semantics of the circular_buffer can be inferred from + the assertions. +

Notes

[1] A good implementation of smart pointers is included in - Boost. -

-

[2] Never create a circular buffer of std::auto_ptr. - Refer to Scott Meyers' excellent book Effective - STL for a detailed discussion. (Meyers S., Effective STL: 50 Specific - Ways to Improve Your Use of the Standard Template Library. - Addison-Wesley, 2001.) -

+ Boost. +

+

[2] Never create a circular buffer of std::auto_ptr. + Refer to Scott Meyers' excellent book Effective + STL for a detailed discussion. (Meyers S., Effective STL: 50 Specific + Ways to Improve Your Use of the Standard Template Library. + Addison-Wesley, 2001.) +

See also

boost::circular_buffer_space_optimized, - std::vector, - std::list, std::deque -

+ std::vector, + std::list, std::deque
+

Ideas for Future Improvements

The formal review revealed that the library is lack of adaptors which would provide additional @@ -2130,18 +2130,18 @@ e.g. for invoking some method on the element being overwritten or for throwing a exception.

Acknowledgments

-

The circular_buffer has a short history. Its first version was a std::deque adaptor. This container was not very -effective because of many reallocations when inserting/removing an element. -Thomas Wenish did a review of this version and motivated me to create a circular +

The circular_buffer has a short history. Its first version was a std::deque adaptor. This container was not very +effective because of many reallocations when inserting/removing an element. +Thomas Wenish did a review of this version and motivated me to create a circular buffer which allocates memory at once when created.

-

The second version adapted std::vector but it has been abandoned - soon because of limited control over iterator invalidation.

-

The current version is - a full-fledged STL compliant container. Pavel Vozenilek did a thorough review of this version - and came with many good ideas and improvements. Also, I would like to - thank Howard Hinnant, Nigel Stewart and everyone who participated at the formal review for valuable - comments and ideas. -

+

The second version adapted std::vector but it has been abandoned + soon because of limited control over iterator invalidation.

+

The current version is + a full-fledged STL compliant container. Pavel Vozenilek did a thorough review of this version + and came with many good ideas and improvements. Also, I would like to + thank Howard Hinnant, Nigel Stewart and everyone who participated at the formal review for valuable + comments and ideas. +


diff --git a/doc/circular_buffer.xslt b/doc/circular_buffer.xslt index f3dc474..859e60c 100644 --- a/doc/circular_buffer.xslt +++ b/doc/circular_buffer.xslt @@ -5,9 +5,9 @@ Author: Jan Gaspar (jano_gaspar[at]yahoo.com) --> - + - + @@ -16,17 +16,17 @@ Author: Jan Gaspar (jano_gaspar[at]yahoo.com) - + - + - + @@ -39,29 +39,29 @@ Author: Jan Gaspar (jano_gaspar[at]yahoo.com) - + - + - + - + - + diff --git a/doc/circular_buffer_space_optimized.html b/doc/circular_buffer_space_optimized.html index 26bf50a..687c5e7 100644 --- a/doc/circular_buffer_space_optimized.html +++ b/doc/circular_buffer_space_optimized.html @@ -2,7 +2,7 @@ - + Space Optimized Circular Buffer Container Adaptor @@ -10,47 +10,47 @@ - - +

circular_buffer_space_optimized<T, Alloc>

+ + +
-

circular_buffer_space_optimized<T, Alloc>

-
Boost
Boost

Contents

Description
- Synopsis
- Rationale
- Header files
- Modeled concepts
- Template Parameters, Members and Standalone - Functions
- Semantics
- See also
- Acknowledgments + Synopsis
+ Rationale
+ Header files
+ Modeled concepts
+ Template Parameters, Members and Standalone + Functions
+ Semantics
+ See also
+ Acknowledgments

Description

The circular_buffer_space_optimized container is an adaptor of the - circular_buffer. The - functionality of the circular_buffer_space_optimized is similar to - the base circular_buffer except it does not allocate memory at - once when created rather it allocates memory as needed. (The predictive memory - allocation is similar to typical std::vector implementation.) - Moreover the memory is automatically freed as the size of the container - decreases. -

+ circular_buffer. The + functionality of the circular_buffer_space_optimized is similar to + the base circular_buffer except it does not allocate memory at + once when created rather it allocates memory as needed. (The predictive memory + allocation is similar to typical std::vector implementation.) + Moreover the memory is automatically freed as the size of the container + decreases. +

- - + + - - + +
Space Optimized Circular Buffer
Space Optimized Circular Buffer
Figure:The memory allocation process of the space optimized circular - buffer. The min_capacity represents the minimal guaranteed amount - of allocated memory. The allocated memory will never drop under this value. By - default the min_capacity is set to 0. -
The memory allocation process of the space optimized circular + buffer. The min_capacity represents the minimal guaranteed amount + of allocated memory. The allocated memory will never drop under this value. By + default the min_capacity is set to 0. +

@@ -81,13 +81,13 @@ public:    typedef typename Alloc::value_type value_type;    template <class InputIterator> -      circular_buffer_space_optimized(size_type capacity, -         size_type min_capacity, InputIterator first, +      circular_buffer_space_optimized(size_type capacity, +         size_type min_capacity, InputIterator first,          InputIterator last, const allocator_type& alloc = allocator_type()); -   circular_buffer_space_optimized(size_type capacity, -      size_type min_capacity, value_type item, +   circular_buffer_space_optimized(size_type capacity, +      size_type min_capacity, value_type item,       const allocator_type& alloc = allocator_type()); -   explicit circular_buffer_space_optimized(size_type capacity, +   explicit circular_buffer_space_optimized(size_type capacity,       size_type min_capacity = 0, const allocator_type& alloc = allocator_type());    template <class InputIterator> @@ -145,25 +145,25 @@ public: }; template <class T, class Alloc> -   bool operator!=(const circular_buffer_space_optimized<T,Alloc>& lhs, +   bool operator!=(const circular_buffer_space_optimized<T,Alloc>& lhs,       const circular_buffer_space_optimized<T,Alloc>& rhs); template <class T, class Alloc> -   bool operator<(const circular_buffer_space_optimized<T,Alloc>& lhs, +   bool operator<(const circular_buffer_space_optimized<T,Alloc>& lhs,       const circular_buffer_space_optimized<T,Alloc>& rhs); template <class T, class Alloc> -   bool operator<=(const circular_buffer_space_optimized<T,Alloc>& lhs, +   bool operator<=(const circular_buffer_space_optimized<T,Alloc>& lhs,       const circular_buffer_space_optimized<T,Alloc>& rhs); template <class T, class Alloc> -   bool operator==(const circular_buffer_space_optimized<T,Alloc>& lhs, +   bool operator==(const circular_buffer_space_optimized<T,Alloc>& lhs,       const circular_buffer_space_optimized<T,Alloc>& rhs); template <class T, class Alloc> -   bool operator>(const circular_buffer_space_optimized<T,Alloc>& lhs, +   bool operator>(const circular_buffer_space_optimized<T,Alloc>& lhs,       const circular_buffer_space_optimized<T,Alloc>& rhs); template <class T, class Alloc> -   bool operator>=(const circular_buffer_space_optimized<T,Alloc>& lhs, +   bool operator>=(const circular_buffer_space_optimized<T,Alloc>& lhs,       const circular_buffer_space_optimized<T,Alloc>& rhs); template <class T, class Alloc> -   void swap(circular_buffer_space_optimized<T,Alloc>& lhs, +   void swap(circular_buffer_space_optimized<T,Alloc>& lhs,       circular_buffer_space_optimized<T,Alloc>& rhs); } // namespace boost @@ -175,43 +175,43 @@ template

Rationale

-

The auto-resizing mode of the space optimized circular buffer can be useful in - situations when the container can possibly store large number of elements but - most of its lifetime the container stores just few of them. The usage of the circular_buffer_space_optimized - will result in decreased memory consumption and can improve the CPU cache - effectiveness. -

+

The auto-resizing mode of the space optimized circular buffer can be useful in + situations when the container can possibly store large number of elements but + most of its lifetime the container stores just few of them. The usage of the circular_buffer_space_optimized + will result in decreased memory consumption and can improve the CPU cache + effectiveness. +

Header files

- The circular_buffer_space_optimized is defined in the file + The circular_buffer_space_optimized is defined in the file boost/circular_buffer.hpp. There is also a forward declaration for the circular_buffer_space_optimized in the header file boost/circular_buffer_fwd.hpp. -

+

Modeled concepts

-

Random Access - Container, - Front Insertion Sequence, - Back Insertion Sequence, - Assignable (SGI specific), - Equality Comparable, - LessThan Comparable (SGI specific) -

+

Random Access + Container, + Front Insertion Sequence, + Back Insertion Sequence, + Assignable (SGI specific), + Equality Comparable, + LessThan Comparable (SGI specific) +

Template Parameters, Members and Friend Functions

Template parameters, members and friend functions of the circular_buffer_space_optimized - are almost the same as for the base circular_buffer. Refer the circular_buffer - documentation and also its - source code documentation for a detailed description. -

-

The specific methods of the circular_buffer_space_optimized are - listed below. -

+ are almost the same as for the base circular_buffer. Refer the circular_buffer + documentation and also its + source code documentation for a detailed description. +

+

The specific methods of the circular_buffer_space_optimized are + listed below. +

Constructors

@@ -718,60 +718,60 @@ See the circular_buffer source doc Semantics

The behaviour of memory auto-resizing is as follows: -

+

  • - Minimal capacity is allocated when an empty circular_buffer_space_optimized - is created. -
  • + Minimal capacity is allocated when an empty circular_buffer_space_optimized + is created. +
  • - When a non-empty circular_buffer_space_optimized - container is created the allocated memory reflects the size of the container. -
  • + When a non-empty circular_buffer_space_optimized + container is created the allocated memory reflects the size of the container. +
  • - push_back, push_front, insert and rinsert - will predictively increase the allocated memory if necessary. (The predictive - memory allocation is similar to std::vector.) -
  • + push_back, push_front, insert and rinsert + will predictively increase the allocated memory if necessary. (The predictive + memory allocation is similar to std::vector.) +
  • - set_capacity, resize, assign, insert - (range or n items), rinsert (range or n items), erase - (range) and clear - will accommodate the allocated memory as necessary. -
  • + set_capacity, resize, assign, insert + (range or n items), rinsert (range or n items), erase + (range) and clear + will accommodate the allocated memory as necessary. +
  • - pop_back, pop_front, erase and clear - will predictively decrease the allocated memory. -
  • -
-

The semantics of the circular_buffer_space_optimized then follows - the semantics of the base circular_buffer - except the invalidation rules. -

+ pop_back, pop_front, erase and clear + will predictively decrease the allocated memory. + + +

The semantics of the circular_buffer_space_optimized then follows + the semantics of the base circular_buffer + except the invalidation rules. +

The rule for iterator invalidation for circular_buffer_space_optimized - is as follows: -

+ is as follows: +

  • - data, set_capacity, resize, operator=, - assign, swap, push_back, push_front, - pop_back, pop_front, insert, rinsert, - erase and clear invalidate all iterators pointing to - the circular_buffer_space_optimized. -
  • -
+ data, set_capacity, resize, operator=, + assign, swap, push_back, push_front, + pop_back, pop_front, insert, rinsert, + erase and clear invalidate all iterators pointing to + the circular_buffer_space_optimized. + +

See also

boost::circular_buffer, - std::vector -

+ std::vector +

Acknowledgments

-

The idea of the space optimized circular buffer has been introduced by Pavel - Vozenilek. -

+

The idea of the space optimized circular buffer has been introduced by Pavel + Vozenilek. +


diff --git a/doc/circular_buffer_space_optimized.xslt b/doc/circular_buffer_space_optimized.xslt index ef2415d..931fc2d 100644 --- a/doc/circular_buffer_space_optimized.xslt +++ b/doc/circular_buffer_space_optimized.xslt @@ -9,19 +9,19 @@ Author: Jan Gaspar (jano_gaspar[at]yahoo.com) - + - + - + @@ -45,7 +45,7 @@ Author: Jan Gaspar (jano_gaspar[at]yahoo.com) - + @@ -100,7 +100,7 @@ Author: Jan Gaspar (jano_gaspar[at]yahoo.com) - + diff --git a/doc/copy.xslt b/doc/copy.xslt index 5c4dbfe..d483a4c 100644 --- a/doc/copy.xslt +++ b/doc/copy.xslt @@ -1,10 +1,10 @@ - - - - - + + + + + diff --git a/doc/doxygen2html.xslt b/doc/doxygen2html.xslt index 0c80ec8..b55423b 100644 --- a/doc/doxygen2html.xslt +++ b/doc/doxygen2html.xslt @@ -6,7 +6,7 @@ ]> - + Default: @@ -14,7 +14,7 @@ - + Warning: The source documentation was generated by the doxygen version which differs from the reference doxygen version (). @@ -27,15 +27,15 @@ - +
- + - + @@ -46,11 +46,11 @@ - + - +
@@ -66,7 +66,7 @@ - + @@ -74,7 +74,7 @@
- + @@ -82,25 +82,25 @@
- +
Returns:
- +
Precondition:
- +
Postcondition:
- + @@ -112,7 +112,7 @@
Note:
- + @@ -123,7 +123,7 @@ - +
@@ -151,12 +151,12 @@ public:
- +   - +    typedef  @@ -205,9 +205,9 @@ public:   - + - +
@@ -237,7 +237,7 @@ public:
- + @@ -251,14 +251,14 @@ public: - + - + diff --git a/doc/html2xhtml.xslt b/doc/html2xhtml.xslt index 518d606..a8e7866 100644 --- a/doc/html2xhtml.xslt +++ b/doc/html2xhtml.xslt @@ -4,9 +4,9 @@ Helper XSL transformation which converts HTML into XHTML. Author: Jan Gaspar (jano_gaspar[at]yahoo.com) --> - + - + diff --git a/doc/unblank.sh b/doc/unblank.sh index a42ec02..9110d48 100644 --- a/doc/unblank.sh +++ b/doc/unblank.sh @@ -5,4 +5,26 @@ function rb { mv $1.temp $1 } -rb 'test.txt' +rb ../../../boost/circular_buffer.hpp +rb ../../../boost/circular_buffer_fwd.hpp +rb ../../../boost/circular_buffer/adaptor.hpp +rb ../../../boost/circular_buffer/base.hpp +rb ../../../boost/circular_buffer/debug.hpp +rb ../../../boost/circular_buffer/details.hpp +rb ../index.html +rb Doxyfile +rb circular_buffer.html +rb circular_buffer.xslt +rb circular_buffer_space_optimized.html +rb circular_buffer_space_optimized.xslt +rb copy.xslt +rb doxygen2html.xslt +rb html2xhtml.xslt +rb update_srcdoc.bat +rb update_srcdoc.sh +rb update_srcdoc.xslt +rb ../test/Jamfile +rb ../test/adaptor_test.cpp +rb ../test/base_test.cpp +rb ../test/common.cpp +rb ../test/test.hpp diff --git a/doc/update_srcdoc.sh b/doc/update_srcdoc.sh index d857fcf..824184d 100644 --- a/doc/update_srcdoc.sh +++ b/doc/update_srcdoc.sh @@ -6,19 +6,19 @@ if [ -f $DOCFILE ]; then echo Starting Doxygen ... # doxygen - + echo Generating source XHTML documentation ... xsltproc --stringparam container $1 --stringparam xmldir srcdoc -o srcdoc/srcdoc.xhtml $1.xslt srcdoc/index.xml - + echo Converting original HTML documentation into XHTML ... xsltproc --html -o srcdoc/$1.xhtml html2xhtml.xslt $DOCFILE - + echo Creating HTML documentation with updated source documentation ... xsltproc --stringparam srcdoc srcdoc/srcdoc.xhtml -o $DOCFILE update_srcdoc.xslt srcdoc/$1.xhtml - + echo Removing temporary directory ... # rm -rf srcdoc - + echo Done. else diff --git a/include/boost/circular_buffer/adaptor.hpp b/include/boost/circular_buffer/adaptor.hpp index 050e465..55a33d6 100644 --- a/include/boost/circular_buffer/adaptor.hpp +++ b/include/boost/circular_buffer/adaptor.hpp @@ -448,7 +448,7 @@ public: return begin() + index; } - //!! See the circular_buffer source documentation. + //!! See the circular_buffer source documentation. /*! \warning The rules for iterator invalidation differ from the original circular_buffer. See the diff --git a/include/boost/circular_buffer/base.hpp b/include/boost/circular_buffer/base.hpp index b75b502..3b00f35 100644 --- a/include/boost/circular_buffer/base.hpp +++ b/include/boost/circular_buffer/base.hpp @@ -160,7 +160,7 @@ public: //! Return a reverse iterator pointing to the end of the reversed circular buffer. reverse_iterator rend() { return reverse_iterator(begin()); } - + //! Return a const reverse iterator pointing to the beginning of the reversed circular buffer. const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } @@ -306,7 +306,7 @@ public: //! Return the largest possible size (or capacity) of the circular buffer. size_type max_size() const { return m_alloc.max_size(); } - + //! Is the circular buffer empty? /*! \return true if there are no elements stored in the circular buffer. @@ -553,7 +553,7 @@ public: \note For iterator invalidation see the documentation. */ void assign(size_type n, param_value_type item) { do_assign(n, assign_n(n, item, m_alloc)); } - + //! Assign a copy of range. /*! \pre Valid range [first, last). @@ -999,18 +999,18 @@ public: BOOST_CB_ASSERT(first <= last); // check for wrong range if (first == last) return first; - pointer p = first.m_it; + pointer p = first.m_it; while (last.m_it != 0) replace((first++).m_it, *last++); do { - decrement(m_last); - destroy_item(m_last); - --m_size; - } while(m_last != first.m_it); + decrement(m_last); + destroy_item(m_last); + --m_size; + } while(m_last != first.m_it); return m_last == p ? end() : iterator(this, p); } - //! Erase the element at the given position. + //! Erase the element at the given position. /*! \pre Valid pos iterator. \pre size_type old_size = (*this).size() @@ -1024,11 +1024,11 @@ public: BOOST_CB_ASSERT(pos.is_valid()); // check for uninitialized or invalidated iterator BOOST_CB_ASSERT(pos.m_it != 0); // check for iterator pointing to end() pointer prev = pos.m_it; - pointer p = prev; + pointer p = prev; for (decrement(prev); p != m_first; p = prev, decrement(prev)) replace(p, *prev); destroy_item(m_first); - increment(m_first); + increment(m_first); --m_size; #if BOOST_CB_ENABLE_DEBUG return p == pos.m_it ? begin() : iterator(this, pos.m_it); @@ -1067,9 +1067,9 @@ public: --m_size; } while(m_first != p); if (m_first == last.m_it) - return begin(); - decrement(last.m_it); - return iterator(this, last.m_it); + return begin(); + decrement(last.m_it); + return iterator(this, last.m_it); } //! Erase all stored elements. @@ -1149,7 +1149,7 @@ private: //! Replace an element. void replace(pointer pos, param_value_type item) { - *pos = item; + *pos = item; #if BOOST_CB_ENABLE_DEBUG invalidate_iterators(iterator(this, pos)); #endif diff --git a/include/boost/circular_buffer/debug.hpp b/include/boost/circular_buffer/debug.hpp index 37d316e..5ee758b 100644 --- a/include/boost/circular_buffer/debug.hpp +++ b/include/boost/circular_buffer/debug.hpp @@ -19,51 +19,7 @@ namespace cb_details { #if BOOST_CB_ENABLE_DEBUG -class cb_iterator_base; - -/*! - \class cb_iterator_registry - \brief Registry of valid iterators. - - This class is intended to be a base class of a container. -*/ -class cb_iterator_registry { - - //! Pointer to the chain of valid iterators. - mutable const cb_iterator_base* m_iterators; - -public: -// Methods - - //! Default constructor. - cb_iterator_registry() : m_iterators(0) {} - - //! Register an iterator into the list of valid iterators. - /*! - \note The method is const in order to register iterators into const containers, too. - */ - void register_iterator(const cb_iterator_base* it) const; - - //! Unregister an iterator from the list of valid iterators. - /*! - \note The method is const in order to unregister iterators from const containers, too. - */ - void unregister_iterator(const cb_iterator_base* it) const; - - //! Invalidate all iterators. - void invalidate_all_iterators(); - - //! Invalidate every iterator conforming to the condition. - template - void invalidate_iterators(const Iterator0& it); - -private: -// Helpers - - //! Remove the current iterator from the iterator chain. - void remove(const cb_iterator_base* current, - const cb_iterator_base* previous) const; // the implementation is below -}; +class cb_iterator_registry; /*! \class cb_iterator_base @@ -86,105 +42,161 @@ public: // Construction/destruction //! Default constructor. - cb_iterator_base() : m_registry(0), m_next(0) {} + cb_iterator_base(); //! Constructor taking the iterator registry as a parameter. - cb_iterator_base(const cb_iterator_registry* registry) - : m_registry(registry), m_next(0) { - register_self(); - } + cb_iterator_base(const cb_iterator_registry* registry); //! Copy constructor. - cb_iterator_base(const cb_iterator_base& rhs) - : m_registry(rhs.m_registry), m_next(0) { - register_self(); - } + cb_iterator_base(const cb_iterator_base& rhs); //! Destructor. - ~cb_iterator_base() { unregister_self(); } - - //! Assign operator. - cb_iterator_base& operator = (const cb_iterator_base& rhs) { - if (m_registry == rhs.m_registry) - return *this; - unregister_self(); - m_registry = rhs.m_registry; - register_self(); - return *this; - } + ~cb_iterator_base(); // Methods + //! Assign operator. + cb_iterator_base& operator = (const cb_iterator_base& rhs); + //! Is the iterator valid? - bool is_valid() const { return m_registry != 0; } + bool is_valid() const; //! Invalidate the iterator. /*! \note The method is const in order to invalidate const iterators, too. */ - void invalidate() const { m_registry = 0; } + void invalidate() const; //! Return the next iterator in the iterator chain. - const cb_iterator_base* next() const { return m_next; } + const cb_iterator_base* next() const; //! Set the next iterator in the iterator chain. /*! \note The method is const in order to set a next iterator to a const iterator, too. */ - void set_next(const cb_iterator_base* it) const { m_next = it; } + void set_next(const cb_iterator_base* it) const; private: // Helpers //! Register self as a valid iterator. - void register_self() { - if (m_registry != 0) - m_registry->register_iterator(this); - } + void register_self(); //! Unregister self from valid iterators. - void unregister_self() { - if (m_registry != 0) - m_registry->unregister_iterator(this); + void unregister_self(); +}; + +/*! + \class cb_iterator_registry + \brief Registry of valid iterators. + + This class is intended to be a base class of a container. +*/ +class cb_iterator_registry { + + //! Pointer to the chain of valid iterators. + mutable const cb_iterator_base* m_iterators; + +public: +// Methods + + //! Default constructor. + cb_iterator_registry() : m_iterators(0) {} + + //! Register an iterator into the list of valid iterators. + /*! + \note The method is const in order to register iterators into const containers, too. + */ + void register_iterator(const cb_iterator_base* it) const { + it->set_next(m_iterators); + m_iterators = it; + } + + //! Unregister an iterator from the list of valid iterators. + /*! + \note The method is const in order to unregister iterators from const containers, too. + */ + void unregister_iterator(const cb_iterator_base* it) const { + const cb_iterator_base* previous = 0; + for (const cb_iterator_base* p = m_iterators; p != it; previous = p, p = p->next()); + remove(it, previous); + } + + //! Invalidate all iterators. + void invalidate_all_iterators() { + for (const cb_iterator_base* p = m_iterators; p != 0; p = p->next()) + p->invalidate(); + m_iterators = 0; + } + + //! Invalidate every iterator conforming to the condition. + template + void invalidate_iterators(const Iterator0& it) { + const cb_iterator_base* previous = 0; + for (const cb_iterator_base* p = m_iterators; p != 0; p = p->next()) { + if (((Iterator0*)p)->m_it == it.m_it) { + p->invalidate(); + remove(p, previous); + continue; + } + previous = p; + } + } + +private: +// Helpers + + //! Remove the current iterator from the iterator chain. + void remove(const cb_iterator_base* current, + const cb_iterator_base* previous) const { + if (previous == 0) + m_iterators = m_iterators->next(); + else + previous->set_next(current->next()); } }; -inline void cb_iterator_registry::register_iterator(const cb_iterator_base* it) const { - it->set_next(m_iterators); - m_iterators = it; +// Implementation of the cb_iterator_base methods. + +inline cb_iterator_base::cb_iterator_base() : m_registry(0), m_next(0) {} + +inline cb_iterator_base::cb_iterator_base(const cb_iterator_registry* registry) +: m_registry(registry), m_next(0) { + register_self(); } -inline void cb_iterator_registry::unregister_iterator(const cb_iterator_base* it) const { - const cb_iterator_base* previous = 0; - for (const cb_iterator_base* p = m_iterators; p != it; previous = p, p = p->next()); - remove(it, previous); +inline cb_iterator_base::cb_iterator_base(const cb_iterator_base& rhs) +: m_registry(rhs.m_registry), m_next(0) { + register_self(); } -inline void cb_iterator_registry::invalidate_all_iterators() { - for (const cb_iterator_base* p = m_iterators; p != 0; p = p->next()) - p->invalidate(); - m_iterators = 0; +inline cb_iterator_base::~cb_iterator_base() { unregister_self(); } + +inline cb_iterator_base& cb_iterator_base::operator = (const cb_iterator_base& rhs) { + if (m_registry == rhs.m_registry) + return *this; + unregister_self(); + m_registry = rhs.m_registry; + register_self(); + return *this; } -template -inline void cb_iterator_registry::invalidate_iterators(const Iterator0& it) { - const cb_iterator_base* previous = 0; - for (const cb_iterator_base* p = m_iterators; p != 0; p = p->next()) { - if (((Iterator0*)p)->m_it == it.m_it) { - p->invalidate(); - remove(p, previous); - continue; - } - previous = p; - } +inline bool cb_iterator_base::is_valid() const { return m_registry != 0; } + +inline void cb_iterator_base::invalidate() const { m_registry = 0; } + +inline const cb_iterator_base* cb_iterator_base::next() const { return m_next; } + +inline void cb_iterator_base::set_next(const cb_iterator_base* it) const { m_next = it; } + +inline void cb_iterator_base::register_self() { + if (m_registry != 0) + m_registry->register_iterator(this); } -inline void cb_iterator_registry::remove(const cb_iterator_base* current, - const cb_iterator_base* previous) const { - if (previous == 0) - m_iterators = m_iterators->next(); - else - previous->set_next(current->next()); +inline void cb_iterator_base::unregister_self() { + if (m_registry != 0) + m_registry->unregister_iterator(this); } #else // #if BOOST_CB_ENABLE_DEBUG diff --git a/include/boost/circular_buffer/details.hpp b/include/boost/circular_buffer/details.hpp index 5df8b93..cb503a7 100644 --- a/include/boost/circular_buffer/details.hpp +++ b/include/boost/circular_buffer/details.hpp @@ -123,8 +123,8 @@ struct cb_helper_pointer { \note This iterator is not circular. It was designed for iterating from begin() to end() of the circular buffer. */ -template -class cb_iterator : +template +class cb_iterator : public boost::iterator< std::random_access_iterator_tag, typename Traits::value_type, diff --git a/index.html b/index.html index fcd305c..013fbf4 100644 --- a/index.html +++ b/index.html @@ -1,10 +1,10 @@ - - - - - - Automatic redirection failed, please go to circular_buffer.html. - + + + + + + Automatic redirection failed, please go to circular_buffer.html. + diff --git a/test/common.cpp b/test/common.cpp index 16d100f..66c1c8b 100644 --- a/test/common.cpp +++ b/test/common.cpp @@ -117,7 +117,7 @@ void element_access_and_insert_test() { void at_test() { #if !defined(BOOST_NO_EXCEPTIONS) - + CB_CONTAINER cb(3); cb.push_back(1); @@ -138,7 +138,7 @@ void front_and_back_test() { CB_CONTAINER cb(1); cb.push_back(2); cb.push_back(3); - + BOOST_CHECK(cb.front() == cb.back()); BOOST_CHECK(cb.back() == 3); } @@ -243,7 +243,7 @@ void set_capacity_test() { cb3.push_back(2); cb3.push_back(3); cb3.push_back(1); - cb3.set_capacity(2); + cb3.set_capacity(2); cb3.set_capacity(2); CB_CONTAINER cb4(10); cb4.push_back(2); @@ -372,7 +372,7 @@ void copy_constructor_and_assign_test() { CB_CONTAINER cb2 = cb1; BOOST_CHECK(cb1 == cb2); - + CB_CONTAINER cb3(20); cb1.pop_back(); CB_CONTAINER cb4(3); @@ -392,7 +392,7 @@ void copy_constructor_and_assign_test() { } void swap_test() { - + CB_CONTAINER cb1(2); cb1.push_back(1); cb1.push_back(2); @@ -411,7 +411,7 @@ void swap_test() { } void push_back_test() { - + CB_CONTAINER cb1(5); cb1.push_back(); cb1.push_back(A(2)); @@ -442,7 +442,7 @@ void pop_back_test() { } void insert_test() { - + CB_CONTAINER cb1(4); cb1.push_back(1); cb1.push_back(2); @@ -554,7 +554,7 @@ void insert_range_test() { } void push_front_test() { - + CB_CONTAINER cb1(5); cb1.push_front(); cb1.push_front(A(2)); @@ -589,7 +589,7 @@ void pop_front_test() { } void rinsert_test() { - + CB_CONTAINER cb1(4); cb1.push_front(1); cb1.push_front(2); @@ -743,11 +743,11 @@ void erase_test() { cb1.push_back(2); cb1.push_back(3); CB_CONTAINER::iterator it1 = cb1.erase(cb1.begin() + 1); - + CB_CONTAINER cb2(1 CB_MIN_CAPACITY, 1); CB_CONTAINER::iterator it2 = cb2.erase(cb2.begin()); - CB_CONTAINER cb3(4); + CB_CONTAINER cb3(4); cb3.push_back(1); cb3.push_back(2); cb3.push_back(3); @@ -756,16 +756,16 @@ void erase_test() { BOOST_CHECK(cb1.size() == 2); BOOST_CHECK(cb1.capacity() == 4); BOOST_CHECK(*it1 == 3); - BOOST_CHECK(cb1[0] == 1); - BOOST_CHECK(cb1[1] == 3); + BOOST_CHECK(cb1[0] == 1); + BOOST_CHECK(cb1[1] == 3); BOOST_CHECK(cb2.size() == 0); BOOST_CHECK(cb2.capacity() == 1); BOOST_CHECK(it2 == cb2.end()); - BOOST_CHECK(cb3.size() == 2); + BOOST_CHECK(cb3.size() == 2); BOOST_CHECK(cb3.capacity() == 4); BOOST_CHECK(it3 == cb3.end()); - BOOST_CHECK(cb3[0] == 1); - BOOST_CHECK(cb3[1] == 2); + BOOST_CHECK(cb3[0] == 1); + BOOST_CHECK(cb3[1] == 2); } void erase_range_test() { @@ -776,39 +776,39 @@ void erase_range_test() { cb1.push_back(3); cb1.push_back(4); CB_CONTAINER::iterator it1 = cb1.erase(cb1.begin() + 1, cb1.begin() + 3); - - CB_CONTAINER cb2(4); + + CB_CONTAINER cb2(4); cb2.push_back(1); cb2.push_back(2); cb2.push_back(3); cb2.push_back(4); CB_CONTAINER::iterator it2 = cb2.erase(cb2.begin(), cb2.begin()); - CB_CONTAINER cb3(4); + CB_CONTAINER cb3(4); cb3.push_back(1); cb3.push_back(2); cb3.push_back(3); cb3.push_back(4); CB_CONTAINER::iterator it3 = cb3.erase(cb3.begin() + 2, cb3.end()); - CB_CONTAINER cb4(10 CB_MIN_CAPACITY, 1); + CB_CONTAINER cb4(10 CB_MIN_CAPACITY, 1); CB_CONTAINER::iterator it4 = cb4.erase(cb4.begin(), cb4.end()); BOOST_CHECK(cb1.size() == 2); BOOST_CHECK(cb1.capacity() == 4); BOOST_CHECK(cb1[0] == 1); BOOST_CHECK(cb1[1] == 4); - BOOST_CHECK(*it1 == 4); + BOOST_CHECK(*it1 == 4); BOOST_CHECK(cb2.size() == 4); BOOST_CHECK(cb2[0] == 1); BOOST_CHECK(cb2[3] == 4); BOOST_CHECK(*it2 == 1); - BOOST_CHECK(cb3.size() == 2); + BOOST_CHECK(cb3.size() == 2); BOOST_CHECK(cb3.capacity() == 4); - BOOST_CHECK(cb3[0] == 1); + BOOST_CHECK(cb3[0] == 1); BOOST_CHECK(cb3[1] == 2); BOOST_CHECK(it3 == cb3.end()); - BOOST_CHECK(cb4.size() == 0); + BOOST_CHECK(cb4.size() == 0); BOOST_CHECK(cb4.capacity() == 10); BOOST_CHECK(it4 == cb4.end()); } @@ -820,11 +820,11 @@ void rerase_test() { cb1.push_back(2); cb1.push_back(3); CB_CONTAINER::iterator it1 = cb1.rerase(cb1.begin() + 1); - + CB_CONTAINER cb2(1 CB_MIN_CAPACITY, 1); CB_CONTAINER::iterator it2 = cb2.rerase(cb2.begin()); - CB_CONTAINER cb3(4); + CB_CONTAINER cb3(4); cb3.push_back(1); cb3.push_back(2); cb3.push_back(3); @@ -833,17 +833,17 @@ void rerase_test() { BOOST_CHECK(cb1.size() == 2); BOOST_CHECK(cb1.capacity() == 4); BOOST_CHECK(*it1 == 1); - BOOST_CHECK(cb1[0] == 1); - BOOST_CHECK(cb1[1] == 3); + BOOST_CHECK(cb1[0] == 1); + BOOST_CHECK(cb1[1] == 3); BOOST_CHECK(cb2.size() == 0); BOOST_CHECK(cb2.capacity() == 1); BOOST_CHECK(it2 == cb2.begin()); - BOOST_CHECK(cb3.size() == 2); + BOOST_CHECK(cb3.size() == 2); BOOST_CHECK(cb3.capacity() == 4); BOOST_CHECK(it3 == cb3.begin()); - BOOST_CHECK(*it3 == 2); - BOOST_CHECK(cb3[0] == 2); - BOOST_CHECK(cb3[1] == 3); + BOOST_CHECK(*it3 == 2); + BOOST_CHECK(cb3[0] == 2); + BOOST_CHECK(cb3[1] == 3); } void rerase_range_test() { @@ -854,39 +854,39 @@ void rerase_range_test() { cb1.push_back(3); cb1.push_back(4); CB_CONTAINER::iterator it1 = cb1.rerase(cb1.begin() + 1, cb1.begin() + 3); - - CB_CONTAINER cb2(4); + + CB_CONTAINER cb2(4); cb2.push_back(1); cb2.push_back(2); cb2.push_back(3); cb2.push_back(4); CB_CONTAINER::iterator it2 = cb2.rerase(cb2.begin(), cb2.begin()); - CB_CONTAINER cb3(4); + CB_CONTAINER cb3(4); cb3.push_back(1); cb3.push_back(2); cb3.push_back(3); cb3.push_back(4); CB_CONTAINER::iterator it3 = cb3.rerase(cb3.begin(), cb3.begin() + 2); - CB_CONTAINER cb4(10 CB_MIN_CAPACITY, 1); + CB_CONTAINER cb4(10 CB_MIN_CAPACITY, 1); CB_CONTAINER::iterator it4 = cb4.rerase(cb4.begin(), cb4.end()); BOOST_CHECK(cb1.size() == 2); BOOST_CHECK(cb1.capacity() == 4); BOOST_CHECK(cb1[0] == 1); BOOST_CHECK(cb1[1] == 4); - BOOST_CHECK(*it1 == 1); + BOOST_CHECK(*it1 == 1); BOOST_CHECK(cb2.size() == 4); BOOST_CHECK(cb2[0] == 1); BOOST_CHECK(cb2[3] == 4); BOOST_CHECK(*it2 == 1); - BOOST_CHECK(cb3.size() == 2); + BOOST_CHECK(cb3.size() == 2); BOOST_CHECK(cb3.capacity() == 4); - BOOST_CHECK(cb3[0] == 3); + BOOST_CHECK(cb3[0] == 3); BOOST_CHECK(cb3[1] == 4); BOOST_CHECK(it3 == cb3.begin()); - BOOST_CHECK(cb4.size() == 0); + BOOST_CHECK(cb4.size() == 0); BOOST_CHECK(cb4.capacity() == 10); BOOST_CHECK(it4 == cb4.begin()); } @@ -1003,7 +1003,7 @@ void example_test() { BOOST_CHECK(cb2[3] == 1); BOOST_CHECK(cb2[4] == 1); - CB_CONTAINER cb3(3); + CB_CONTAINER cb3(3); cb3.push_back(1); cb3.push_back(2); cb3.push_back(3); @@ -1012,28 +1012,28 @@ void example_test() { BOOST_CHECK(cb3[0] == 3); BOOST_CHECK(cb3[1] == 4); BOOST_CHECK(cb3[2] == 5); - + cb3.pop_back(); cb3.pop_front(); BOOST_CHECK(cb3[0] == 4); } void element_destruction_test() { - + CB_CONTAINER cb(5); cb.push_back(B()); cb.push_back(B()); cb.push_back(B()); int prevCount = B::count(); cb.clear(); - + BOOST_CHECK(cb.empty()); BOOST_CHECK(prevCount == 3); BOOST_CHECK(B::count() == 0); } void const_methods_test() { - + vector v; v.push_back(1); v.push_back(2); @@ -1111,7 +1111,7 @@ void add_common_tests(test_suite* tests) { tests->add(BOOST_TEST_CASE(&rinsert_range_test)); tests->add(BOOST_TEST_CASE(&erase_test)); tests->add(BOOST_TEST_CASE(&erase_range_test)); - tests->add(BOOST_TEST_CASE(&rerase_test)); + tests->add(BOOST_TEST_CASE(&rerase_test)); tests->add(BOOST_TEST_CASE(&rerase_range_test)); tests->add(BOOST_TEST_CASE(&clear_test)); tests->add(BOOST_TEST_CASE(&equality_test)); diff --git a/test/test.hpp b/test/test.hpp index b1571af..e5dfb08 100644 --- a/test/test.hpp +++ b/test/test.hpp @@ -42,7 +42,7 @@ public: Integer(int i) : m_pValue(new int(i)) { check_exception(); } Integer(const Integer& src) : m_pValue(new int(src)) { check_exception(); } ~Integer() { delete m_pValue; } - Integer& operator = (const Integer& src) { + Integer& operator = (const Integer& src) { if (this == &src) return *this; check_exception(); @@ -88,7 +88,7 @@ private: public: typedef typename boost::circular_buffer::iterator iterator; typedef typename boost::circular_buffer::size_type size_type; - + Adaptor(size_type capacity) : m_buff(capacity) {} template Adaptor(size_type capacity, InputIterator first, InputIterator last) @@ -99,7 +99,7 @@ public: size_type size() const { return m_buff.size(); } size_type capacity() const { return m_buff.capacity(); } T& operator [] (size_type index) { return m_buff[index]; } - + template void insert(iterator pos, InputIterator first, InputIterator last) { size_type new_size = size() + distance(first, last);