queue.hh

00001 // This file is a part of Aurelia.
00002 // Copyright (C) 2010  Valentin David
00003 // Copyright (C) 2010  University of Bergen
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 #ifndef __QUEUE_HH
00019 # define __QUEUE_HH
00020 # include "node.hh"
00021 # include "label.hh"
00022 # include "frame.hh"
00023 # include "../memory/pool_allocator.hh"
00024 # include <unordered_map>
00025 
00026 namespace aurelia {
00027   namespace llstack {
00028 
00029 struct rj_t {
00030   struct ln: public std::pair<label, node> {
00031   private:
00032     unsigned _hash;
00033   public:
00034     typedef std::pair<label, node> super;
00035     ln(const label& l, const node& n): super(l, n) {
00036       _hash = this->first.hash();
00037       _hash = (_hash << 11) | (_hash >> 21);
00038       _hash ^= this->second.hash();
00039     }
00040     unsigned hash() const {
00041       return _hash;
00042     }
00043 
00044     ln(const ln& other): super(other.first, other.second),
00045                          _hash(other._hash) {
00046 
00047     }
00048 
00049     ln& operator=(const ln& other) {
00050       return *this = ln(other);
00051     }
00052 
00053     ln& operator=(ln&& other) {
00054       std::swap(this->first, other.first);
00055       std::swap(this->second, other.second);
00056       std::swap(_hash, other._hash);
00057       return *this;
00058     }
00059   };
00060 
00061   struct hash {
00062     unsigned operator()(const ln& a) const {
00063       return a.hash();
00064     }
00065   };
00066 
00067   struct eq {
00068     unsigned operator()(const ln& a, const ln& b) const {
00069       return ((a.first) == (b.first)) && (a.second == b.second);
00070     }
00071   };
00072 
00073   typedef std::unordered_set<frame, frame::hash_op, frame::eq, pool_allocator<frame> > frame_set_t;
00074   typedef std::unordered_map<ln, frame_set_t, hash, eq, pool_allocator<std::pair<ln, frame_set_t> > > set_t;
00075   set_t done;
00076   set_t pending;
00077 };
00078 
00079 struct descriptor {
00080   label L;
00081   frame f;
00082   node n;
00083   stream s;
00084 
00085   descriptor(const label& L, const frame& f, const node& n, const stream& s):
00086     L(L), f(f), n(n), s(s) {}
00087   descriptor(const descriptor& other): L(other.L),
00088                                        f(other.f), n(other.n), s(other.s) {
00089   }
00090 };
00091 
00092 struct r_t {
00093   struct eof {};
00094   typedef std::map<stream, rj_t, std::less<stream>, pool_allocator<std::pair<stream, rj_t> > > map_t;
00095   map_t m;
00096 
00097   descriptor pop() {
00098     map_t::iterator i = m.begin();
00099     if (i == m.end()) {
00100       throw eof();
00101     }
00102     while ((*i).second.pending.empty()) {
00103       stream s = (*i).first;
00104       m.erase(i);
00105       node::drop(s);
00106       //collect_nodes();
00107       i = m.begin();
00108       if (i == m.end())
00109         throw eof();
00110     }
00111     rj_t::set_t::iterator j = (*i).second.pending.begin();
00112     rj_t::frame_set_t::iterator f = (*j).second.begin();
00113     frame fr = *f;
00114     rj_t::ln p = (*j).first;
00115     (*i).second.done[(*j).first].insert(*f);
00116     (*j).second.erase(*f);
00117     if ((*j).second.empty()) {
00118       (*i).second.pending.erase(j);
00119     }
00120     return descriptor(p.first, fr, p.second, (*i).first);
00121   }
00122 
00123   void collect_nodes() const {
00124     std::unordered_set<node, std::hash<node>, std::equal_to<node>, pool_allocator<node> > marks;
00125     for (map_t::const_iterator i = m.begin();
00126          i != m.end(); ++i) {
00127       for (rj_t::set_t::const_iterator j = (*i).second.pending.begin();
00128            j != (*i).second.pending.end(); ++j) {
00129         (*j).first.second.mark(marks);
00130       }
00131       for (rj_t::set_t::const_iterator j = (*i).second.done.begin();
00132            j != (*i).second.done.end(); ++j) {
00133         (*j).first.second.mark(marks);
00134       }
00135     }
00136     node::clear(marks);
00137   }
00138 
00139   void add(const label& L, const frame& data, const node& u, const stream& j) {
00140     rj_t::ln p(L, u);
00141     if (m[j].done[p].find(data) == m[j].done[p].end()) {
00142       m[j].pending[p].insert(data);
00143     }
00144   }
00145 };
00146 
00147   }
00148 }
00149 
00150 #endif