dlvhex  2.5.0
include/dlvhex2/OrdinaryAtomTable.h
Go to the documentation of this file.
00001 /* dlvhex -- Answer-Set Programming with external interfaces.
00002  * Copyright (C) 2005-2007 Roman Schindlauer
00003  * Copyright (C) 2006-2015 Thomas Krennwallner
00004  * Copyright (C) 2009-2016 Peter Schüller
00005  * Copyright (C) 2011-2016 Christoph Redl
00006  * Copyright (C) 2015-2016 Tobias Kaminski
00007  * Copyright (C) 2015-2016 Antonius Weinzierl
00008  *
00009  * This file is part of dlvhex.
00010  *
00011  * dlvhex is free software; you can redistribute it and/or modify it
00012  * under the terms of the GNU Lesser General Public License as
00013  * published by the Free Software Foundation; either version 2.1 of
00014  * the License, or (at your option) any later version.
00015  *
00016  * dlvhex is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with dlvhex; if not, write to the Free Software
00023  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
00024  * 02110-1301 USA.
00025  */
00026 
00034 #ifndef ORDINARYATOMTABLE_HPP_INCLUDED__12102010
00035 #define ORDINARYATOMTABLE_HPP_INCLUDED__12102010
00036 
00037 #include "dlvhex2/PlatformDefinitions.h"
00038 #include "dlvhex2/Atoms.h"
00039 #include "dlvhex2/Table.h"
00040 
00041 #include <boost/multi_index/member.hpp>
00042 #include <boost/multi_index/mem_fun.hpp>
00043 #include <boost/multi_index/hashed_index.hpp>
00044 #include <boost/multi_index/random_access_index.hpp>
00045 
00046 DLVHEX_NAMESPACE_BEGIN
00047 
00049 class OrdinaryAtomTable:
00050 public Table<
00051 // value type is symbol struct
00052 OrdinaryAtom,
00053 // index is
00054 boost::multi_index::indexed_by<
00055 // address = running ID for constant access
00056 boost::multi_index::random_access<
00057 boost::multi_index::tag<impl::AddressTag>
00058 >,
00059 // (unique) textual representation (parsing index, see TODO above)
00060 boost::multi_index::hashed_unique<
00061 boost::multi_index::tag<impl::TextTag>,
00062 BOOST_MULTI_INDEX_MEMBER(OrdinaryAtom,std::string,text)
00063 >,
00064 // unique IDs for unique tuples
00065 boost::multi_index::hashed_unique<
00066 boost::multi_index::tag<impl::TupleTag>,
00067 BOOST_MULTI_INDEX_MEMBER(OrdinaryAtom::Atom,Tuple,tuple)
00068 >,
00069 boost::multi_index::hashed_non_unique<
00070 boost::multi_index::tag<impl::PredicateTag>,
00071 // we cannot use BOOST_MULTI_INDEX_CONST_MEM_FUN here, it required MemberFunName to be in Class
00072 //BOOST_MULTI_INDEX_CONST_MEM_FUN(OrdinaryAtom,ID,front)
00073 boost::multi_index::const_mem_fun_explicit<OrdinaryAtom,ID,
00074 ID (Atom::*)() const,&Atom::front>
00075 >
00076 >
00077 >
00078 {
00079     // types
00080     public:
00081         typedef Container::index<impl::AddressTag>::type AddressIndex;
00082         //typedef Container::index<impl::KindTag>::type KindIndex;
00083         typedef Container::index<impl::TextTag>::type TextIndex;
00084         typedef Container::index<impl::TupleTag>::type TupleIndex;
00085         typedef Container::index<impl::PredicateTag>::type PredicateIndex;
00086         typedef AddressIndex::iterator AddressIterator;
00087         typedef PredicateIndex::iterator PredicateIterator;
00088 
00089         // methods
00090     public:
00098         inline const OrdinaryAtom& getByID(ID id) const throw ();
00099 
00106         inline const OrdinaryAtom& getByAddress(IDAddress addr) const throw ();
00107 
00114         inline ID getIDByAddress(IDAddress addr) const throw ();
00115 
00119         inline ID getIDByString(const std::string& text) const throw();
00120 
00125         inline ID getIDByTuple(const Tuple& tuple) const throw();
00126 
00132         inline ID getIDByStorage(const OrdinaryAtom& atom) const throw ();
00133 
00139         inline IDAddress getIDAddressByStorage(const OrdinaryAtom& atom) const throw ();
00140 
00146         inline ID storeAndGetID(const OrdinaryAtom& atom) throw();
00147 
00154         inline std::pair<PredicateIterator, PredicateIterator>
00155             getRangeByPredicateID(ID id) const throw();
00156 
00162         inline std::pair<AddressIterator, AddressIterator>
00163             getAllByAddress() const throw();
00164 };
00165 
00166 // retrieve by ID
00167 // assert that id.kind is correct for Term
00168 // assert that ID exists
00169 const OrdinaryAtom&
00170 OrdinaryAtomTable::getByID(
00171 ID id) const throw ()
00172 {
00173     assert(id.isAtom() || id.isLiteral());
00174     assert(id.isOrdinaryAtom());
00175     ReadLock lock(mutex);
00176     const AddressIndex& idx = container.get<impl::AddressTag>();
00177     // the following check only works for random access indices, but here it is ok
00178     assert( id.address < idx.size() );
00179     return idx.at(id.address);
00180 }
00181 
00182 
00183 // retrieve by address (ignore kind)
00184 // assert that address exists in table
00185 const OrdinaryAtom&
00186 OrdinaryAtomTable::getByAddress(
00187 IDAddress addr) const throw ()
00188 {
00189     ReadLock lock(mutex);
00190     const AddressIndex& idx(container.get<impl::AddressTag>());
00191     // the following check only works for random access indices, but here it is ok
00192     assert( addr < idx.size() );
00193     return idx.at(addr);
00194 }
00195 
00196 
00197 // retrieve ID by address
00198 // assert that address exists in table
00199 ID
00200 OrdinaryAtomTable::getIDByAddress(
00201 IDAddress addr) const throw ()
00202 {
00203     const OrdinaryAtom& atom = getByAddress(addr);
00204     return ID(atom.kind, addr);
00205 }
00206 
00207 
00208 // given string, look if already stored
00209 // if no, return ID_FAIL, otherwise return ID
00210 ID OrdinaryAtomTable::getIDByString(
00211 const std::string& str) const throw()
00212 {
00213     typedef Container::index<impl::TextTag>::type OrdinaryAtomIndex;
00214     ReadLock lock(mutex);
00215     const TextIndex& sidx(container.get<impl::TextTag>());
00216     TextIndex::const_iterator it(sidx.find(str));
00217     if( it == sidx.end() )
00218         return ID_FAIL;
00219     else {
00220         const AddressIndex& aidx(container.get<impl::AddressTag>());
00221         return ID(
00222             it->kind,            // kind
00223                                  // address
00224             container.project<impl::AddressTag>(it) - aidx.begin()
00225             );
00226     }
00227 }
00228 
00229 
00230 // given tuple, look if already stored
00231 // if no, return ID_FAIL, otherwise return ID
00232 ID OrdinaryAtomTable::getIDByTuple(
00233 const Tuple& tuple) const throw()
00234 {
00235     typedef Container::index<impl::TupleTag>::type TupleIndex;
00236     ReadLock lock(mutex);
00237     const TupleIndex& sidx(container.get<impl::TupleTag>());
00238     TupleIndex::const_iterator it(sidx.find(tuple));
00239     if( it == sidx.end() )
00240         return ID_FAIL;
00241     else {
00242         const AddressIndex& aidx(container.get<impl::AddressTag>());
00243         return ID(
00244             it->kind,            // kind
00245                                  // address
00246             container.project<impl::AddressTag>(it) - aidx.begin()
00247             );
00248     }
00249 }
00250 
00251 
00252 // get ID given storage retrieved by other means
00253 // (storage must have originated from iterator from here)
00254 ID OrdinaryAtomTable::getIDByStorage(
00255 const OrdinaryAtom& atom) const throw ()
00256 {
00257     // we cannot assert anything really useful here!
00258     // (if the user specifies another storage, iterator_to will segfault
00259     //  anyway as there is no associated internal multi_index storage node)
00260     ReadLock lock(mutex);
00261     const AddressIndex& aidx(container.get<impl::AddressTag>());
00262     AddressIndex::const_iterator it(aidx.iterator_to(atom));
00263     assert(atom.kind == it->kind);
00264     return ID(
00265         atom.kind,               // kind
00266         it - aidx.begin()        // address
00267         );
00268 }
00269 
00270 
00271 // get IDAddress of given storage retrieved by other means
00272 // (storage must have originated from iterator from here)
00273 IDAddress OrdinaryAtomTable::getIDAddressByStorage(
00274 const OrdinaryAtom& atom) const throw ()
00275 {
00276     // we cannot assert anything really useful here!
00277     // (if the user specifies another storage, iterator_to will segfault
00278     //  anyway as there is no associated internal multi_index storage node)
00279     ReadLock lock(mutex);
00280     const AddressIndex& aidx(container.get<impl::AddressTag>());
00281     AddressIndex::const_iterator it(aidx.iterator_to(atom));
00282     assert(atom.kind == it->kind);
00283     return it - aidx.begin();
00284 }
00285 
00286 
00287 // store symbol, assuming it does not exist (this is only asserted)
00288 ID OrdinaryAtomTable::storeAndGetID(
00289 const OrdinaryAtom& atm) throw()
00290 {
00291     assert(ID(atm.kind,0).isAtom());
00292     assert(ID(atm.kind,0).isOrdinaryAtom());
00293     assert(!atm.text.empty());
00294     assert(!(
00295         (atm.tuple.front().kind & ID::PROPERTY_AUX) != 0 &&
00296         (atm.kind & ID::PROPERTY_AUX) == 0 ) &&
00297         "atom must be auxiliary if predicate term is auxiliary");
00298 
00299     AddressIndex::const_iterator it;
00300     bool success;
00301 
00302     WriteLock lock(mutex);
00303     AddressIndex& idx(container.get<impl::AddressTag>());
00304     boost::tie(it, success) = idx.push_back(atm);
00305     (void)success;
00306     assert(success);
00307 
00308     return ID(
00309         atm.kind,                // kind
00310                                  // address
00311         container.project<impl::AddressTag>(it) - idx.begin()
00312         );
00313 }
00314 
00315 
00316 // get all ordinary atoms with certain predicate id
00317 // NOTE: you may need to lock the mutex also while iterating!
00318 // if you intend to use this method frequently, consider to use a PredicateMask instead for better efficiency (iteration is slow)
00319 std::pair<OrdinaryAtomTable::PredicateIterator, OrdinaryAtomTable::PredicateIterator>
00320 OrdinaryAtomTable::getRangeByPredicateID(ID id) const throw()
00321 {
00322     assert(id.isTerm());
00323     ReadLock lock(mutex);
00324     const PredicateIndex& idx = container.get<impl::PredicateTag>();
00325     return idx.equal_range(id);
00326 }
00327 
00328 
00329 // get range over all atoms sorted by address
00330 // NOTE: you may need to lock the mutex also while iterating!
00331 std::pair<OrdinaryAtomTable::AddressIterator, OrdinaryAtomTable::AddressIterator>
00332 OrdinaryAtomTable::getAllByAddress() const throw()
00333 {
00334     ReadLock lock(mutex);
00335     const AddressIndex& idx = container.get<impl::AddressTag>();
00336     return std::make_pair(idx.begin(), idx.end());
00337 }
00338 
00339 
00340 DLVHEX_NAMESPACE_END
00341 #endif                           // ORDINARYATOMTABLE_HPP_INCLUDED__12102010
00342 
00343 // vim:expandtab:ts=4:sw=4:
00344 // mode: C++
00345 // End: