Stxxl  1.4.0
include/stxxl/bits/common/addressable_queues.h
Go to the documentation of this file.
00001 /***************************************************************************
00002  *  include/stxxl/bits/common/addressable_queues.h
00003  *
00004  *  Part of the STXXL. See http://stxxl.sourceforge.net
00005  *
00006  *  Copyright (C) 2010-2011 Raoul Steffen <R-Steffen@gmx.de>
00007  *
00008  *  Distributed under the Boost Software License, Version 1.0.
00009  *  (See accompanying file LICENSE_1_0.txt or copy at
00010  *  http://www.boost.org/LICENSE_1_0.txt)
00011  **************************************************************************/
00012 
00013 #ifndef STXXL_ADDRESSABLE_QUEUES_HEADER
00014 #define STXXL_ADDRESSABLE_QUEUES_HEADER
00015 
00016 #include <set>
00017 #include <list>
00018 #include <map>
00019 
00020 #include <stxxl/bits/namespace.h>
00021 
00022 __STXXL_BEGIN_NAMESPACE
00023 
00024 //! \brief An internal fifo queue that allows removing elements addressed with (a copy of) themselves.
00025 //! \tparam KeyType Type of contained elements.
00026 template <typename KeyType>
00027 class addressable_fifo_queue
00028 {
00029     typedef std::list<KeyType> container_t;
00030     typedef typename container_t::iterator container_iter_t;
00031     typedef std::map<KeyType, container_iter_t> meta_t;
00032     typedef typename meta_t::iterator meta_iter_t;
00033 
00034     container_t vals;
00035     meta_t meta;
00036 
00037 public:
00038     //! \brief Type of handle to an entry. For use with insert and remove.
00039     typedef meta_iter_t handle;
00040 
00041     //! \brief Create an empty queue.
00042     addressable_fifo_queue() {}
00043     ~addressable_fifo_queue() {}
00044 
00045     //! \brief Check if queue is empty.
00046     //! \return If queue is empty.
00047     bool empty() const
00048     { return vals.empty(); }
00049 
00050     //! \brief Insert new element. If the element is already in, it is moved to the back.
00051     //! \param e Element to insert.
00052     //! \return pair<handle, bool> Iterator to element; if element was newly inserted.
00053     std::pair<handle, bool> insert(const KeyType & e)
00054     {
00055         container_iter_t ei = vals.insert(vals.end(), e);
00056         std::pair<handle, bool> r = meta.insert(std::make_pair(e, ei));
00057         if (! r.second)
00058         {
00059             // element was already in
00060             vals.erase(r.first->second);
00061             r.first->second = ei;
00062         }
00063         return r;
00064     }
00065 
00066     //! \brief Erase element from the queue.
00067     //! \param e Element to remove.
00068     //! \return If element was in.
00069     bool erase(const KeyType & e)
00070     {
00071         handle mi = meta.find(e);
00072         if (mi == meta.end())
00073             return false;
00074         vals.erase(mi->second);
00075         meta.erase(mi);
00076         return true;
00077     }
00078 
00079     //! \brief Erase element from the queue.
00080     //! \param i Iterator to element to remove.
00081     void erase(handle i)
00082     {
00083         vals.erase(i->second);
00084         meta.erase(i);
00085     }
00086 
00087     //! \brief Access top element in the queue.
00088     //! \return Const reference to top element.
00089     const KeyType & top() const
00090     { return vals.front(); }
00091 
00092     //! \brief Remove top element from the queue.
00093     //! \return Top element.
00094     KeyType pop()
00095     {
00096         assert(! empty());
00097         const KeyType e = top();
00098         meta.erase(e);
00099         vals.pop_front();
00100         return e;
00101     }
00102 };
00103 
00104 //! \brief An internal priority queue that allows removing elements addressed with (a copy of) themselves.
00105 //! \tparam KeyType Type of contained elements.
00106 //! \tparam PriorityType Type of Priority.
00107 template < typename KeyType, typename PriorityType, class Cmp = std::less<PriorityType> >
00108 class addressable_priority_queue
00109 {
00110     struct cmp // like < for pair, but uses Cmp for < on first
00111     {
00112       bool operator()(const std::pair<PriorityType, KeyType> & left,
00113               const std::pair<PriorityType, KeyType> & right) const
00114       {
00115           Cmp c;
00116           return c(left.first, right.first) ||
00117                   ((! c(right.first, left.first)) && left.second < right.second);
00118       }
00119     };
00120 
00121     typedef std::set<std::pair<PriorityType, KeyType>, cmp> container_t;
00122     typedef typename container_t::iterator container_iter_t;
00123     typedef std::map<KeyType, container_iter_t> meta_t;
00124     typedef typename meta_t::iterator meta_iter_t;
00125 
00126     container_t vals;
00127     meta_t meta;
00128 
00129 public:
00130     //! \brief Type of handle to an entry. For use with insert and remove.
00131     typedef meta_iter_t handle;
00132 
00133     //! \brief Create an empty queue.
00134     addressable_priority_queue() {}
00135     ~addressable_priority_queue() {}
00136 
00137     //! \brief Check if queue is empty.
00138     //! \return If queue is empty.
00139     bool empty() const
00140     { return vals.empty(); }
00141 
00142     //! \brief Insert new element. If the element is already in, it's priority is updated.
00143     //! \param e Element to insert.
00144     //! \param o Priority of element.
00145     //! \return pair<handle, bool> Iterator to element; if element was newly inserted.
00146     std::pair<handle, bool> insert(const KeyType & e, const PriorityType o)
00147     {
00148         std::pair<container_iter_t ,bool> s = vals.insert(std::make_pair(o, e));
00149         std::pair<handle, bool> r = meta.insert(std::make_pair(e, s.first));
00150         if (! r.second && s.second)
00151         {
00152             // was already in with different priority
00153             vals.erase(r.first->second);
00154             r.first->second = s.first;
00155         }
00156         return r;
00157     }
00158 
00159     //! \brief Erase element from the queue.
00160     //! \param e Element to remove.
00161     //! \return If element was in.
00162     bool erase(const KeyType & e)
00163     {
00164         handle mi = meta.find(e);
00165         if (mi == meta.end())
00166             return false;
00167         vals.erase(mi->second);
00168         meta.erase(mi);
00169         return true;
00170     }
00171 
00172     //! \brief Erase element from the queue.
00173     //! \param i Iterator to element to remove.
00174     void erase(handle i)
00175     {
00176         vals.erase(i->second);
00177         meta.erase(i);
00178     }
00179 
00180     //! \brief Access top (= min) element in the queue.
00181     //! \return Const reference to top element.
00182     const KeyType & top() const
00183     { return vals.begin()->second; }
00184 
00185     //! \brief Remove top (= min) element from the queue.
00186     //! \return Top element.
00187     KeyType pop()
00188     {
00189         assert(! empty());
00190         const KeyType e = top();
00191         meta.erase(e);
00192         vals.erase(vals.begin());
00193         return e;
00194     }
00195 };
00196 
00197 __STXXL_END_NAMESPACE
00198 
00199 #endif /* STXXL_ADDRESSABLE_QUEUES_HEADER */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines