dlvhex  2.5.0
include/dlvhex2/ModuleAtomTable.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 MODULEATOMTABLE_HPP_INCLUDED__27112010
00035 #define MODULEATOMTABLE_HPP_INCLUDED__27112010
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/hashed_index.hpp>
00043 #include <boost/multi_index/composite_key.hpp>
00044 #include <boost/multi_index/random_access_index.hpp>
00045 
00046 DLVHEX_NAMESPACE_BEGIN
00047 
00049 class ModuleAtomTable:
00050 public Table<
00051 // value type is symbol struct
00052 ModuleAtom,
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 boost::multi_index::hashed_non_unique<
00060 boost::multi_index::tag<impl::PredicateTag>,
00061 BOOST_MULTI_INDEX_MEMBER(ModuleAtom,ID,predicate)
00062 >,
00063 boost::multi_index::hashed_unique<
00064 boost::multi_index::tag<impl::ElementTag>,
00065 boost::multi_index::composite_key<
00066 ModuleAtom,
00067 BOOST_MULTI_INDEX_MEMBER(ModuleAtom,ID,predicate),
00068 BOOST_MULTI_INDEX_MEMBER(ModuleAtom,Tuple,inputs),
00069 BOOST_MULTI_INDEX_MEMBER(ModuleAtom,ID,outputAtom)
00070 >
00071 >
00072 >
00073 >
00074 {
00075     // types
00076     public:
00077         typedef Container::index<impl::AddressTag>::type AddressIndex;
00078         typedef AddressIndex::iterator AddressIterator;
00079         typedef Container::index<impl::PredicateTag>::type PredicateIndex;
00080         typedef PredicateIndex::iterator PredicateIterator;
00081         typedef Container::index<impl::ElementTag>::type ElementIndex;
00082         typedef ElementIndex::iterator ElementIterator;
00083 
00084         // methods
00085     public:
00089         inline const ModuleAtom& getByID(ID id) const throw ();
00090 
00096         inline ID getIDByElement(ID predicate1, const Tuple& inputs1, ID outputAtom1) const throw();
00097 
00103         // if you intend to use this method frequently, consider to use a PredicateMask instead for better efficiency (iteration is slow)
00104         inline std::pair<PredicateIterator, PredicateIterator>
00105             getRangeByPredicateID(ID id) const throw();
00106 
00111         inline std::pair<AddressIterator, AddressIterator>
00112             getAllByAddress() const throw();
00113 
00117         inline ID storeAndGetID(const ModuleAtom& atom) throw();
00118 
00124         inline void update(
00125             const ModuleAtom& oldStorage, ModuleAtom& newStorage) throw();
00126 };
00127 
00128 // retrieve by ID
00129 // assert that id.kind is correct for Term
00130 // assert that ID exists
00131 const ModuleAtom&
00132 ModuleAtomTable::getByID(ID id) const throw ()
00133 {
00134     assert(id.isAtom() || id.isLiteral());
00135     assert(id.isModuleAtom());
00136 
00137     ReadLock lock(mutex);
00138     const AddressIndex& idx = container.get<impl::AddressTag>();
00139     // the following check only works for random access indices, but here it is ok
00140     assert( id.address < idx.size() );
00141     return idx.at(id.address);
00142 }
00143 
00144 
00145 // @p2[q1,q2]::r(a)
00146 // predicate = p2
00147 // inputs = <q1, q2> = tuple
00148 // outputAtom = r(a)
00149 ID ModuleAtomTable::getIDByElement(ID predicate1, const Tuple& inputs1, ID outputAtom1) const throw()
00150 {
00151     ReadLock lock(mutex);
00152     const ElementIndex& sidx = container.get<impl::ElementTag>();
00153     ElementIndex::const_iterator it = sidx.find( boost::make_tuple(predicate1, inputs1, outputAtom1) );
00154     if( it == sidx.end() )
00155         return ID_FAIL;
00156     else {
00157         const AddressIndex& aidx = container.get<impl::AddressTag>();
00158         return ID(
00159             it->kind,            // kind
00160                                  // address
00161             container.project<impl::AddressTag>(it) - aidx.begin()
00162             );
00163     }
00164 }
00165 
00166 
00167 // get all external atoms with certain predicate id
00168 // NOTE: you may need to lock the mutex also while iterating!
00169 // if you intend to use this method frequently, consider to use a PredicateMask instead for better efficiency (iteration is slow)
00170 std::pair<ModuleAtomTable::PredicateIterator, ModuleAtomTable::PredicateIterator>
00171 ModuleAtomTable::getRangeByPredicateID(ID id) const throw()
00172 {
00173     assert(id.isTerm() && id.isConstantTerm());
00174     ReadLock lock(mutex);
00175     const PredicateIndex& idx = container.get<impl::PredicateTag>();
00176     return idx.equal_range(id);
00177 }
00178 
00179 
00180 // get range over all atoms sorted by address
00181 // NOTE: you may need to lock the mutex also while iterating!
00182 std::pair<ModuleAtomTable::AddressIterator, ModuleAtomTable::AddressIterator>
00183 ModuleAtomTable::getAllByAddress() const throw()
00184 {
00185     ReadLock lock(mutex);
00186     const AddressIndex& idx = container.get<impl::AddressTag>();
00187     return std::make_pair(idx.begin(), idx.end());
00188 }
00189 
00190 
00191 // store symbol, assuming it does not exist (this is only asserted)
00192 ID ModuleAtomTable::storeAndGetID(
00193 const ModuleAtom& atm) throw()
00194 {
00195     assert(ID(atm.kind,0).isAtom());
00196     assert(ID(atm.kind,0).isModuleAtom());
00197 
00198     AddressIndex::const_iterator it;
00199     bool success;
00200 
00201     ReadLock lock(mutex);
00202     AddressIndex& idx = container.get<impl::AddressTag>();
00203     boost::tie(it, success) = idx.push_back(atm);
00204     (void)success;
00205     assert(success);
00206 
00207     return ID(
00208         atm.kind,                // kind
00209                                  // address
00210         container.project<impl::AddressTag>(it) - idx.begin()
00211         );
00212 }
00213 
00214 
00215 void ModuleAtomTable::update(
00216 const ModuleAtom& oldStorage, ModuleAtom& newStorage) throw()
00217 {
00218     bool success;
00219 
00220     WriteLock lock(mutex);
00221     AddressIndex& idx(container.get<impl::AddressTag>());
00222     AddressIndex::iterator it(idx.iterator_to(oldStorage));
00223     assert(it != idx.end());
00224     success = idx.replace(it, newStorage);
00225     (void)success;
00226     assert(success);
00227 }
00228 
00229 
00230 DLVHEX_NAMESPACE_END
00231 #endif
00232 
00233 // vim:expandtab:ts=4:sw=4:
00234 // mode: C++
00235 // End: