dlvhex  2.5.0
include/dlvhex2/PredicateTable.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 PREDICATETABLE_HPP_INCLUDED__20122010
00035 #define PREDICATETABLE_HPP_INCLUDED__20102010
00036 
00037 #include "dlvhex2/PlatformDefinitions.h"
00038 #include "dlvhex2/Logger.h"
00039 #include "dlvhex2/ID.h"
00040 #include "dlvhex2/Predicate.h"
00041 #include "dlvhex2/Table.h"
00042 
00043 #include <boost/multi_index/member.hpp>
00044 #include <boost/multi_index/hashed_index.hpp>
00045 #include <boost/multi_index/random_access_index.hpp>
00046 
00047 DLVHEX_NAMESPACE_BEGIN
00048 
00050 class PredicateTable:
00051 public Table<
00052 // value type is symbol struct
00053 Predicate,
00054 // index is
00055 boost::multi_index::indexed_by<
00056 // address = running ID for constant access
00057 boost::multi_index::random_access<
00058 boost::multi_index::tag<impl::AddressTag>
00059 >,
00060 // unique IDs for unique symbol strings
00061 boost::multi_index::hashed_unique<
00062 boost::multi_index::tag<impl::PredicateNameTag>,
00063 BOOST_MULTI_INDEX_MEMBER(Predicate,std::string,symbol)
00064 >
00065 >
00066 // WARNING: do not put an index on arity, it might be changed (see below)
00067 >
00068 {
00069     public:
00070         // types
00071         typedef Container::index<impl::AddressTag>::type AddressIndex;
00072         typedef AddressIndex::iterator AddressIterator;
00073         typedef Container::index<impl::PredicateNameTag>::type PredicateNameIndex;
00074 
00075         // methods
00076     public:
00083         inline const Predicate& getByID(ID id) const throw ();
00084 
00088         inline void setArity(ID id, int arity);
00089 
00093         inline ID getIDByString(const std::string& str) const throw();
00094 
00098         inline const Predicate& getByString(const std::string& str) const throw();
00099 
00105         inline ID storeAndGetID(const Predicate& symb) throw();
00106 
00111         inline std::pair<AddressIterator, AddressIterator>
00112             getAllByAddress() const throw();
00113 
00114 };
00115 
00116 // retrieve by ID
00117 // assert that id.kind is correct for Term
00118 // assert that ID exists
00119 const Predicate& PredicateTable::getByID(ID id) const throw ()
00120 {
00121     assert(id.isTerm());
00122     assert(id.isPredicateTerm() );
00123     ReadLock lock(mutex);
00124     const AddressIndex& idx = container.get<impl::AddressTag>();
00125     // the following check only works for random access indices, but here it is ok
00126     assert( id.address < idx.size() );
00127     return idx.at(id.address);
00128 }
00129 
00130 
00131 // retrieve by ID
00132 // assert that id.kind is correct for Term
00133 // assert that ID exists
00134 // change the arity
00135 void PredicateTable::setArity(ID id, int arity)
00136 {
00137     assert(id.isTerm());
00138     assert(id.isPredicateTerm() );
00139     assert(arity >= 0);
00140 
00141     WriteLock lock(mutex);
00142     const AddressIndex& idx = container.get<impl::AddressTag>();
00143     // the following check only works for random access indices, but here it is ok
00144     assert( id.address < idx.size() );
00145     AddressIterator it = idx.begin()+id.address;
00146     Predicate newPred((*it).kind, (*it).symbol, arity);
00147     container.replace(it, newPred);
00148     DBGLOG(DBG, "Change arity of " << (*it).symbol << " to " << arity);
00149 }
00150 
00151 
00152 // given string, look if already stored
00153 // if no, return ID_FAIL, otherwise return ID
00154 ID PredicateTable::getIDByString(const std::string& str) const throw()
00155 {
00156     ReadLock lock(mutex);
00157     const PredicateNameIndex& sidx = container.get<impl::PredicateNameTag>();
00158     PredicateNameIndex::const_iterator it = sidx.find(str);
00159     if( it == sidx.end() )
00160         return ID_FAIL;
00161     else {
00162         const AddressIndex& aidx = container.get<impl::AddressTag>();
00163         return ID(it->kind,      // kind
00164                                  // address
00165             container.project<impl::AddressTag>(it) - aidx.begin()
00166             );
00167     }
00168 }
00169 
00170 
00171 const Predicate& PredicateTable::getByString(const std::string& str) const throw()
00172 {
00173     ReadLock lock(mutex);
00174     const PredicateNameIndex& sidx = container.get<impl::PredicateNameTag>();
00175     PredicateNameIndex::const_iterator it = sidx.find(str);
00176     WARNING("this looks fishy, and PREDICATE_FAIL is not used anywhere else, when can this happen and if it is intended to fail, why don't we return a pointer or throw an exception?")
00177         if( it == sidx.end() )
00178         return PREDICATE_FAIL;
00179     else {
00180         return *it;
00181     }
00182 }
00183 
00184 
00185 // store symbol, assuming it does not exist
00186 // assert that symbol did not exist
00187 ID PredicateTable::storeAndGetID(const Predicate& symb) throw()
00188 {
00189     assert(ID(symb.kind,0).isTerm());
00190     assert(ID(symb.kind,0).isPredicateTerm() );
00191     assert(!symb.symbol.empty());
00192 
00193     AddressIndex::const_iterator it;
00194     bool success;
00195 
00196     WriteLock lock(mutex);
00197     AddressIndex& idx = container.get<impl::AddressTag>();
00198     boost::tie(it, success) = idx.push_back(symb);
00199     (void)success;
00200     assert(success);
00201 
00202     return ID(symb.kind,         // kind
00203                                  // address
00204         container.project<impl::AddressTag>(it) - idx.begin()
00205         );
00206 }
00207 
00208 
00209 // get range over all atoms sorted by address
00210 // NOTE: you may need to lock the mutex also while iterating!
00211 std::pair<PredicateTable::AddressIterator, PredicateTable::AddressIterator>
00212 PredicateTable::getAllByAddress() const throw()
00213 {
00214     ReadLock lock(mutex);
00215     const AddressIndex& idx = container.get<impl::AddressTag>();
00216     return std::make_pair(idx.begin(), idx.end());
00217 }
00218 
00219 
00220 DLVHEX_NAMESPACE_END
00221 #endif                           // PREDICATETABLE_HPP_INCLUDED__20122010
00222 
00223 // vim:expandtab:ts=4:sw=4:
00224 // mode: C++
00225 // End: