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     template <typename U>
00275     void push_back(const U& x,  typename copy_sink<U, T>::type = 0);
00276     template <typename U>
00277     void push_back(U x, typename move_sink<U, T>::type = 0);
00278     
00279     void pop_front() ADOBE_NOTHROW;
00280     
00281     void putback() ADOBE_NOTHROW;
00282 
00283 #if !defined(ADOBE_NO_DOCUMENTATION)
00284 private:
00285     friend inline void swap(circular_queue& x, circular_queue& y)
00286     {
00287         swap(x.container_m, y.container_m);
00288         std::swap(x.begin_m, y.begin_m);
00289         std::swap(x.end_m, y.end_m);
00290         swap(x.is_empty_m, y.is_empty_m);
00291     }
00292 
00293     friend bool operator == <> (const circular_queue& x,
00294                                 const circular_queue& y);
00295     
00296     typedef typename std::vector<value_type>        container_t;
00297     typedef typename container_t::iterator          iterator;
00298     typedef typename container_t::const_iterator    const_iterator;
00299 
00300     /* WARNING (sparent) : Order of members is important to initialization */
00301     container_t container_m;
00302     iterator    begin_m;
00303     iterator    end_m;
00304     bool        is_empty_m;
00305     /* WARNING (sparent) : Order of members is important to initialization */
00306     
00307     // Note that these ranges assume non-empty.
00308     
00309     typedef std::pair<const_iterator, const_iterator> const_range;
00310     
00311     const_range first_range() const
00312     { return const_range(begin_m, begin_m < end_m ? const_iterator(end_m) : boost::end(container_m)); }
00313     
00314     const_range second_range() const
00315     { return const_range(begin_m < end_m ? const_iterator(end_m) : boost::begin(container_m), end_m); }
00316     
00317 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00318 };
00319 
00320 /*************************************************************************************************/
00321 
00322 template <typename T>
00323 circular_queue<T>::circular_queue(std::size_t capacity) :
00324     container_m(capacity),
00325     begin_m(boost::begin(container_m)),
00326     end_m(boost::begin(container_m)),
00327     is_empty_m(true)
00328 { }
00329 
00330 #if !defined(ADOBE_NO_DOCUMENTATION)
00331 
00332 /*************************************************************************************************/
00333 
00334 template <typename T>
00335 circular_queue<T>::circular_queue(const circular_queue& rhs) :
00336     container_m (rhs.capacity()),
00337     begin_m     (boost::begin(container_m)),
00338     end_m       (boost::begin(container_m)),
00339     is_empty_m  (rhs.is_empty_m)
00340 {
00341     if (is_empty_m) return;
00342     
00343     end_m = copy(rhs.first_range(), end_m);
00344     end_m = copy(rhs.second_range(), end_m);
00345 }
00346 
00347 /*************************************************************************************************/
00348 
00349 template <typename T>
00350 inline circular_queue<T>& circular_queue<T>::operator = (circular_queue rhs)
00351 {  swap(*this, rhs); return *this; }
00352 
00353 #endif // !defined(ADOBE_NO_DOCUMENTATION)
00354 /*************************************************************************************************/
00355 
00356 template <typename T>
00357 typename circular_queue<T>::reference circular_queue<T>::front() ADOBE_NOTHROW
00358 {
00359     assert(!empty());
00360     return *begin_m;
00361 }
00362 
00363 /*************************************************************************************************/
00364 
00365 template <typename T>
00366 typename circular_queue<T>::const_reference circular_queue<T>::front() const
00367         ADOBE_NOTHROW
00368 {
00369     assert(!empty());
00370     return *begin_m;
00371 }
00372 
00373 /*************************************************************************************************/
00374 
00375 template <typename T>
00376 template <typename U>
00377 void circular_queue<T>::push_back(const U& x, typename copy_sink<U, T>::type)
00378 {
00379     *end_m = x;
00380     
00381     bool was_full (full());
00382     
00383     if (++end_m == boost::end(container_m)) end_m = boost::begin(container_m);
00384     if (was_full) begin_m = end_m;
00385     
00386     is_empty_m = false;
00387 }
00388 
00389 /*************************************************************************************************/
00390 
00391 template <typename T>
00392 template <typename U>
00393 void circular_queue<T>::push_back(U x, typename move_sink<U, T>::type)
00394 {
00395     *end_m = move(x);
00396     
00397     bool was_full (full());
00398     
00399     if (++end_m == boost::end(container_m)) end_m = boost::begin(container_m);
00400     if (was_full) begin_m = end_m;
00401     
00402     is_empty_m = false;
00403 }
00404 
00405 /*************************************************************************************************/
00406 
00407 template <typename T>
00408 void circular_queue<T>::pop_front() ADOBE_NOTHROW
00409 {
00410     assert(!empty());
00411     if (++begin_m == boost::end(container_m))
00412         begin_m = boost::begin(container_m);
00413     is_empty_m = begin_m == end_m;
00414 }
00415 
00416 /*************************************************************************************************/
00417 
00418 template <typename T>
00419 void circular_queue<T>::putback() ADOBE_NOTHROW
00420 {
00421     assert(!full());
00422     if (begin_m == boost::begin(container_m))
00423         begin_m = boost::end(container_m);
00424     --begin_m;
00425     is_empty_m = false;
00426 }
00427 
00428 /*************************************************************************************************/
00429 
00430 template <typename T>
00431 typename circular_queue<T>::size_type circular_queue<T>::size() const ADOBE_NOTHROW
00432 {
00433     if (begin_m < end_m) return std::distance(begin_m, end_m);
00434 
00435     return is_empty_m ? 0 : capacity() - std::distance(end_m, begin_m);
00436 }
00437 
00438 /*************************************************************************************************/
00439 
00440 template <typename T>
00441 bool operator == (  const circular_queue<T>& x,
00442                     const circular_queue<T>& y)
00443 {
00444 /*
00445     REVISIT (sparent) : I'm trying to move the code towards equality of containers to mean "the
00446     size is the same and all the parts are the same." By making the segmented iterators part of
00447     a public begin, end interface this would simply be a generic. "equal_containers()" function.
00448 */
00449     typedef typename circular_queue<T>::const_range const_range;
00450 
00451     if (x.size() != y.size()) return false;
00452     
00453     const_range sequence1[] = { x.first_range(), x.second_range() };
00454     const_range sequence2[] = { y.first_range(), y.second_range() };
00455     
00456     return equal(make_segmented_range(sequence1),
00457                  make_segmented_iterator(sequence2));
00458 }
00459 
00460 /*************************************************************************************************/
00461 
00462 #undef ADOBE_NOTHROW
00463 
00464 /*************************************************************************************************/
00465 
00466 } // namespace adobe
00467 
00468 /*************************************************************************************************/
00469 
00470 #endif // ADOBE_CIRCULAR_QUEUE_HPP
00471 
00472 /*************************************************************************************************/

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