node.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 __NODE_HH
00019 # define __NODE_HH
00020 
00021 # include <aurelia-config.hh>
00022 
00023 # include <map>
00024 # include <unordered_set>
00025 # include <forward_list>
00026 # include "../max_shared/max_shared_ptr.hh"
00027 # include "../streams/buf_stream.hh"
00028 # include "../memory/pool_allocator.hh"
00029 # include "label.hh"
00030 # include "frame.hh"
00031 # ifndef NDEBUG
00032 #  ifdef HAVE_CXXABI_H
00033 #   include <cxxabi.h>
00034 #   define DEMANGLE(X...) abi::__cxa_demangle(X,0,0,&status)
00035 #  else
00036 #   define DEMANGLE(X...) X
00037 #  endif
00038 # endif
00039 
00040 namespace aurelia {
00041   namespace llstack {
00042 
00043 struct r_t;
00044 struct node;
00045 
00046   }
00047 }
00048 
00049 namespace std {
00050   template <>
00051   struct hash<aurelia::llstack::node> {
00052     unsigned operator()(const aurelia::llstack::node& a) const;
00053   };
00054 }
00055 
00056 namespace aurelia {
00057   namespace llstack {
00058 
00059 struct node_core {
00060 public:
00061   typedef std::forward_list<frame, pool_allocator<frame> > frame_list_t;
00062   typedef std::unordered_set<node, std::hash<node>, std::equal_to<node>, pool_allocator<node> > node_set_t;
00063   typedef std::map<stream, frame_list_t, std::less<stream>, pool_allocator<std::pair<stream, frame_list_t> > > p_t;
00064 private:
00065   label L;
00066   frame f;
00067   int pos;
00068   p_t P;
00069   node_set_t parents;
00070   unsigned _hash;
00071 
00072 public:
00073   void update_hash();
00074   node_core(const label& L, const frame& f, int pos): L(L), f(f), pos(pos) {
00075     update_hash();
00076   }
00077 
00078   node_core(const node_core& other): L(other.L), f(other.f), pos(other.pos) {
00079     _hash = other._hash;
00080   }
00081 
00082   node_core(node_core&& other): L(std::move(other.L)),
00083                                 f(std::move(other.f)),
00084                                 pos(other.pos),
00085                                 _hash(other._hash) {
00086   }
00087 
00088   node_core& operator=(const node_core& other) {
00089     return *this = node_core(other);
00090   }
00091 
00092   node_core& operator=(node_core&& other) {
00093     std::swap(L, other.L);
00094     std::swap(f, other.f);
00095     std::swap(pos, other.pos);
00096     std::swap(P, other.P);
00097     std::swap(parents, other.parents);
00098     std::swap(_hash, other._hash);
00099     return *this;
00100   }
00101 
00102   node_core() {
00103     _hash = 0;
00104   }
00105 
00106   unsigned hash() const {
00107     return _hash;
00108   }
00109 
00110   bool operator==(const node_core& other) const;
00111 
00112   const node_set_t& get_parents() const {
00113     return parents;
00114   }
00115 
00116   node_set_t& get_parents() {
00117     return parents;
00118   }
00119 
00120   const p_t& get_P() const {
00121     return P;
00122   }
00123 
00124   p_t& get_P() {
00125     return P;
00126   }
00127 
00128   int get_pos() const {
00129     return pos;
00130   }
00131 
00132   const label& get_label() const {
00133     return L;
00134   }
00135 
00136   const frame& get_frame() const {
00137     return f;
00138   }
00139 
00140   void drop(const stream& s) {
00141     for (p_t::iterator i = P.begin();
00142          i != P.end();) {
00143       if ((*i).first.get_pos() <= s.get_pos()) {
00144         P.erase(i);
00145         i = P.begin();
00146       } else break ;
00147     }
00148   }
00149 };
00150 
00151 struct node: public max_shared_ptr<node_core> {
00152 private:
00153   typedef max_shared_ptr<node_core> super;
00154 
00155   explicit node(const typename super::set_t::iterator& other): super(other) {
00156   }
00157 
00158   node(const label& l, const frame& f, int s): super(l, f, s) {
00159   }
00160   node(const label& l, frame&& f, int s): super(l, std::move(f), s) {
00161   }
00162 public:
00163   node() = default;
00164 
00165   node(const node& other): super(other) {
00166   }
00167 
00168   node(node&& other): super(std::move(other)) {
00169   }
00170 
00171   const node_core::node_set_t& parents() const {
00172     return (*this)->get_parents();
00173   }
00174 
00175   node_core::node_set_t& parents() {
00176     return const_cast<node_core*>(&**this)->get_parents();
00177   }
00178 
00179   const node_core::p_t& P() const {
00180     return (*this)->get_P();
00181   }
00182 
00183   node_core::p_t& P() {
00184     return const_cast<node_core*>(&**this)->get_P();
00185   }
00186 
00187   static node create(r_t& R, const label& l, const frame& f, const node& u,
00188                      const stream& j);
00189 
00190   static node boundary(const label&, const stream& s);
00191 
00192   unsigned hash() const {
00193     return (*this)->hash();
00194   }
00195 
00196   const label& get_label() const {
00197     return (*this)->get_label();
00198   }
00199 
00200   int pos() const {
00201     return (*this)->get_pos();
00202   }
00203 
00204   node& operator=(const node& other) {
00205     return *this = node(other);
00206   }
00207 
00208   node& operator=(node&& other) {
00209     super::operator=(std::move(other));
00210     return *this;
00211   }
00212 
00213   static void drop(const stream& s) {
00214     super::set_t::iterator i = super::set().begin();
00215     while (i != super::set().end()) {
00216       super::ptr& ro = *const_cast<super::ptr*>(&*i);
00217       ++ro.count();
00218       const_cast<node_core*>(&*ro)->drop(s);
00219       ++i;
00220       if (0 == --ro.count())
00221         set().erase(ro);
00222     }
00223   }
00224 
00225   void mark(std::unordered_set<node, std::hash<node>, std::equal_to<node>, pool_allocator<node> >& marks) const {
00226     std::pair<std::unordered_set<node, std::hash<node>, std::equal_to<node>, pool_allocator<node> >::iterator, bool> j =
00227       marks.insert(*this);
00228     if (j.second) {
00229       for (node_core::node_set_t::const_iterator i =
00230              parents().begin();
00231            i != parents().end(); ++i) {
00232         (*i).mark(marks);
00233       }
00234     }
00235   }
00236 
00237   static int nbnode() {
00238     return super::set().size();
00239   }
00240 
00241 # ifndef NDEBUG
00242   static void printnodes(std::ostream& o) {
00243     //int status;
00244     super::set_t::iterator i = super::set().begin();
00245     o << "digraph g {" << std::endl;
00246     while (i != super::set().end()) {
00247       super::ptr& ro = *const_cast<super::ptr*>(&*i);
00248 
00249       o << "n_" << (*ro).get_label().hash()
00250         << "_" << (*ro).get_pos() << " [label=\""
00251         << (*ro).get_label().hash()
00252         << ", " << (*ro).get_pos() << "\"];" << std::endl;
00253 
00254       ++i;
00255     }
00256     i = super::set().begin();
00257     while (i != super::set().end()) {
00258       super::ptr& ro = *const_cast<super::ptr*>(&*i);
00259       for (node_core::node_set_t::const_iterator j =
00260              (*ro).get_parents().begin();
00261            j != (*ro).get_parents().end(); ++j) {
00262         o << "n_" << ((*ro).get_label().hash())
00263           << "_" << (*ro).get_pos() << " -> " << "n_"
00264           << ((*j).get_label()).hash() << "_"
00265           << (*j).pos() << ";" << std::endl;
00266       }
00267       i++;
00268     }
00269     o << "}" << std::endl;
00270   }
00271 # endif
00272 
00273   static void clear(std::unordered_set<node, std::hash<node>, std::equal_to<node>, pool_allocator<node> > marks
00274                     = std::unordered_set<node, std::hash<node>, std::equal_to<node>, pool_allocator<node> >()) {
00275     super::set_t::iterator i = super::set().begin();
00276     while (i != super::set().end()) {
00277       if (marks.find(node(i))
00278           == marks.end()) {
00279         super::ptr& ro = *const_cast<super::ptr*>(&*i);
00280         const_cast<node_core*>(&*ro)->get_P().clear();
00281         if (!((*ro).get_parents().empty())) {
00282           ++ro.count();
00283           const_cast<node_core*>(&*ro)->get_parents().clear();
00284           --ro.count();
00285           set().erase(ro);
00286           i = super::set().begin();
00287         }
00288         else {
00289           i++;
00290         }
00291       } else {
00292         i++;
00293       }
00294     }
00295   }
00296 
00297   template <typename Ret>
00298   void pop(r_t& queue, const Ret& ret_value, stream& j);
00299 
00300   void pop(r_t& queue, const void_return&, stream& j);
00301 
00302   template <typename Ret>
00303   void pop(r_t& queue, const Ret& ret_value, stream& j) const {
00304     node(*this).pop(queue, ret_value, j);
00305   }
00306 };
00307 
00308   }
00309 }
00310 
00311 #endif
00312