dlvhex
2.5.0
|
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: