stlab.adobe.com Adobe Systems Incorporated

circular_queue.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2007 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://stlab.adobe.com/licenses.html)
00005 */
00006 
00007 /*************************************************************************************************/
00008 
00009 #ifndef ADOBE_CIRCULAR_QUEUE_HPP
00010 #define ADOBE_CIRCULAR_QUEUE_HPP
00011 
00012 /*************************************************************************************************/
00013 
00014 #include <adobe/config.hpp>
00015 
00016 #include <adobe/algorithm/equal.hpp>
00017 #include <adobe/iterator.hpp>
00018 #include <adobe/move.hpp>
00019 
00020 #include <boost/operators.hpp>
00021 
00022 #include <cassert>
00023 #include <vector>
00024 
00025 /*************************************************************************************************/
00026 
00027 namespace adobe {
00207 /*************************************************************************************************/
00208 
00209 #if 1 // REVISIT (fbrereto) : Possible compiler optimization?
00210     #define ADOBE_NOTHROW throw()
00211 #else
00212     #define ADOBE_NOTHROW
00213 #endif
00214 
00215 /*************************************************************************************************/
00216 
00217 template <typename T> class circular_queue;
00218 
00219 template <typename T>
00220 bool operator == (const circular_queue<T>& x, const circular_queue<T>& y);
00221 
00222 template <typename T>
00223 void swap(circular_queue<T>&, circular_queue<T>&);
00224 
00225 /*************************************************************************************************/
00226 
00243 template <typename T>
00244 class circular_queue : boost::equality_comparable<circular_queue<T> >
00245 {
00246 public:
00247     typedef T           value_type;
00248     typedef T*          pointer;
00249     typedef const T*    const_pointer;
00250     typedef T&          reference;
00251     typedef const T&    const_reference;
00252     typedef std::size_t size_type;
00253 
00254     circular_queue(std::size_t capacity = 0);
00255 
00256 #if !defined(ADOBE_NO_DOCUMENTATION)
00257     circular_queue(const circular_queue& rhs);
00258 
00259     circular_queue& operator = (circular_queue rhs);
00260 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00261 
00262     size_type size() const ADOBE_NOTHROW;
00263     size_type max_size() const ADOBE_NOTHROW { return container_m.size(); }
00264     size_type capacity() const ADOBE_NOTHROW { return container_m.size(); }
00265 
00266     bool empty() const ADOBE_NOTHROW { return is_empty_m; }
00267     bool full() const ADOBE_NOTHROW { return !is_empty_m && begin_m == end_m; }
00268 
00269     void clear() ADOBE_NOTHROW { begin_m = end_m; is_empty_m = true; }
00270 
00271     reference       front() ADOBE_NOTHROW;
00272     const_reference front() const ADOBE_NOTHROW;
00273 
00274     void push_back(T x);
00275 
00276     void pop_front() ADOBE_NOTHROW;
00277 
00278     void putback() ADOBE_NOTHROW;
00279 
00280 #if !defined(ADOBE_NO_DOCUMENTATION)
00281 private:
00282     friend inline void swap(circular_queue& x, circular_queue& y)
00283     {
00284         swap(x.container_m, y.container_m);
00285         std::swap(x.begin_m, y.begin_m);
00286         std::swap(x.end_m, y.end_m);
00287         swap(x.is_empty_m, y.is_empty_m);
00288     }
00289 
00290     friend bool operator == <> (const circular_queue& x,
00291                                 const circular_queue& y);
00292 
00293     typedef typename std::vector<value_type>        container_t;
00294     typedef typename container_t::iterator          iterator;
00295     typedef typename container_t::const_iterator    const_iterator;
00296 
00297     /* WARNING (sparent) : Order of members is important to initialization */
00298     container_t container_m;
00299     iterator    begin_m;
00300     iterator    end_m;
00301     bool        is_empty_m;
00302     /* WARNING (sparent) : Order of members is important to initialization */
00303 
00304     // Note that these ranges assume non-empty.
00305 
00306     typedef std::pair<const_iterator, const_iterator> const_range;
00307 
00308     const_range first_range() const
00309     { return const_range(begin_m, begin_m < end_m ? const_iterator(end_m) : boost::end(container_m)); }
00310 
00311     const_range second_range() const
00312     { return const_range(begin_m < end_m ? const_iterator(end_m) : boost::begin(container_m), end_m); }
00313 
00314 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00315 };
00316 
00317 /*************************************************************************************************/
00318 
00319 template <typename T>
00320 circular_queue<T>::circular_queue(std::size_t capacity) :
00321     container_m(capacity),
00322     begin_m(boost::begin(container_m)),
00323     end_m(boost::begin(container_m)),
00324     is_empty_m(true)
00325 { }
00326 
00327 #if !defined(ADOBE_NO_DOCUMENTATION)
00328 
00329 /*************************************************************************************************/
00330 
00331 template <typename T>
00332 circular_queue<T>::circular_queue(const circular_queue& rhs) :
00333     container_m (rhs.capacity()),
00334     begin_m     (boost::begin(container_m)),
00335     end_m       (boost::begin(container_m)),
00336     is_empty_m  (rhs.is_empty_m)
00337 {
00338     if (is_empty_m) return;
00339 
00340     end_m = copy(rhs.first_range(), end_m);
00341     end_m = copy(rhs.second_range(), end_m);
00342 }
00343 
00344 /*************************************************************************************************/
00345 
00346 template <typename T>
00347 inline circular_queue<T>& circular_queue<T>::operator = (circular_queue rhs)
00348 {  swap(*this, rhs); return *this; }
00349 
00350 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00351 /*************************************************************************************************/
00352 
00353 template <typename T>
00354 typename circular_queue<T>::reference circular_queue<T>::front() ADOBE_NOTHROW
00355 {
00356     assert(!empty());
00357     return *begin_m;
00358 }
00359 
00360 /*************************************************************************************************/
00361 
00362 template <typename T>
00363 typename circular_queue<T>::const_reference circular_queue<T>::front() const
00364         ADOBE_NOTHROW
00365 {
00366     assert(!empty());
00367     return *begin_m;
00368 }
00369 
00370 /*************************************************************************************************/
00371 
00372 template <typename T>
00373 void circular_queue<T>::push_back(T x)
00374 {
00375     *end_m = adobe::move(x);
00376 
00377     bool was_full (full());
00378 
00379     if (++end_m == boost::end(container_m)) end_m = boost::begin(container_m);
00380     if (was_full) begin_m = end_m;
00381 
00382     is_empty_m = false;
00383 }
00384 
00385 /*************************************************************************************************/
00386 
00387 template <typename T>
00388 void circular_queue<T>::pop_front() ADOBE_NOTHROW
00389 {
00390     assert(!empty());
00391     if (++begin_m == boost::end(container_m))
00392         begin_m = boost::begin(container_m);
00393     is_empty_m = begin_m == end_m;
00394 }
00395 
00396 /*************************************************************************************************/
00397 
00398 template <typename T>
00399 void circular_queue<T>::putback() ADOBE_NOTHROW
00400 {
00401     assert(!full());
00402     if (begin_m == boost::begin(container_m))
00403         begin_m = boost::end(container_m);
00404     --begin_m;
00405     is_empty_m = false;
00406 }
00407 
00408 /*************************************************************************************************/
00409 
00410 template <typename T>
00411 typename circular_queue<T>::size_type circular_queue<T>::size() const ADOBE_NOTHROW
00412 {
00413     if (begin_m < end_m) return std::distance(begin_m, end_m);
00414 
00415     return is_empty_m ? 0 : capacity() - std::distance(end_m, begin_m);
00416 }
00417 
00418 /*************************************************************************************************/
00419 
00420 template <typename T>
00421 bool operator == (  const circular_queue<T>& x,
00422                     const circular_queue<T>& y)
00423 {
00424 /*
00425     REVISIT (sparent) : I'm trying to move the code towards equality of containers to mean "the
00426     size is the same and all the parts are the same." By making the segmented iterators part of
00427     a public begin, end interface this would simply be a generic. "equal_containers()" function.
00428 */
00429     typedef typename circular_queue<T>::const_range const_range;
00430 
00431     if (x.size() != y.size()) return false;
00432 
00433     const_range sequence1[] = { x.first_range(), x.second_range() };
00434     const_range sequence2[] = { y.first_range(), y.second_range() };
00435 
00436     return equal(make_segmented_range(sequence1),
00437                  make_segmented_iterator(sequence2));
00438 }
00439 
00440 /*************************************************************************************************/
00441 
00442 #undef ADOBE_NOTHROW
00443 
00444 /*************************************************************************************************/
00445 
00446 } // namespace adobe
00447 
00448 /*************************************************************************************************/
00449 
00450 #endif // ADOBE_CIRCULAR_QUEUE_HPP
00451 
00452 /*************************************************************************************************/

Copyright © 2006-2007 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google