dlvhex  2.5.0
include/dlvhex2/ExternalAtomTable.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 EXTERNALATOMTABLE_HPP_INCLUDED__18102010
00035 #define EXTERNALATOMTABLE_HPP_INCLUDED__18102010
00036 
00037 #include "dlvhex2/PlatformDefinitions.h"
00038 #include "dlvhex2/fwd.h"
00039 #include "dlvhex2/Atoms.h"
00040 #include "dlvhex2/Table.h"
00041 
00042 #include <boost/multi_index/member.hpp>
00043 #include <boost/multi_index/ordered_index.hpp>
00044 
00045 DLVHEX_NAMESPACE_BEGIN
00046 
00048 class ExternalAtomTable:
00049 public Table<
00050 // value type is symbol struct
00051 ExternalAtom,
00052 // index is
00053 boost::multi_index::indexed_by<
00054 // address = running ID for constant access
00055 boost::multi_index::random_access<
00056 boost::multi_index::tag<impl::AddressTag>
00057 >,
00058 boost::multi_index::ordered_non_unique<
00059 boost::multi_index::tag<impl::PredicateTag>,
00060 BOOST_MULTI_INDEX_MEMBER(ExternalAtom,ID,predicate)
00061 >
00062 >
00063 >
00064 {
00065     // types
00066     public:
00067         typedef Container::index<impl::AddressTag>::type AddressIndex;
00068         typedef Container::index<impl::PredicateTag>::type PredicateIndex;
00069         typedef PredicateIndex::iterator PredicateIterator;
00070 
00071         // methods
00072     public:
00079         inline const ExternalAtom& getByID(ID id) const throw ();
00080 
00084         // NOTE: you may need to lock the mutex also while iterating!
00085         // if you intend to use this method frequently, consider to use a PredicateMask instead for better efficiency (iteration is slow)
00086         inline std::pair<PredicateIterator, PredicateIterator>
00087             getRangeByPredicateID(ID id) const throw();
00088 
00092         inline ID storeAndGetID(const ExternalAtom& atom) throw();
00093 
00099         inline void update(
00100             const ExternalAtom& oldStorage, ExternalAtom& newStorage) throw();
00101 
00109         std::ostream& print(std::ostream& o, RegistryPtr reg) const throw();
00110 };
00111 
00112 // retrieve by ID
00113 // assert that id.kind is correct for Term
00114 // assert that ID exists
00115 const ExternalAtom&
00116 ExternalAtomTable::getByID(ID id) const throw ()
00117 {
00118     assert(id.isAtom() || id.isLiteral());
00119     assert(id.isExternalAtom());
00120 
00121     ReadLock lock(mutex);
00122     const AddressIndex& idx = container.get<impl::AddressTag>();
00123     // the following check only works for random access indices, but here it is ok
00124     assert( id.address < idx.size() );
00125     return idx.at(id.address);
00126 }
00127 
00128 
00129 // get all external atoms with certain predicate id
00130 // NOTE: you may need to lock the mutex also while iterating!
00131 // if you intend to use this method frequently, consider to use a PredicateMask instead for better efficiency (iteration is slow)
00132 std::pair<ExternalAtomTable::PredicateIterator, ExternalAtomTable::PredicateIterator>
00133 ExternalAtomTable::getRangeByPredicateID(ID id) const throw()
00134 {
00135     assert(id.isTerm() && id.isConstantTerm());
00136     ReadLock lock(mutex);
00137     const PredicateIndex& idx = container.get<impl::PredicateTag>();
00138     return idx.equal_range(id);
00139 }
00140 
00141 
00142 // store symbol, assuming it does not exist (this is only asserted)
00143 ID ExternalAtomTable::storeAndGetID(
00144 const ExternalAtom& atm) throw()
00145 {
00146     assert(ID(atm.kind,0).isAtom());
00147     assert(ID(atm.kind,0).isExternalAtom());
00148 
00149     AddressIndex::const_iterator it;
00150     bool success;
00151 
00152     WriteLock lock(mutex);
00153     AddressIndex& idx = container.get<impl::AddressTag>();
00154     boost::tie(it, success) = idx.push_back(atm);
00155     (void)success;
00156     assert(success);
00157 
00158     return ID(
00159         atm.kind,                // kind
00160                                  // address
00161         container.project<impl::AddressTag>(it) - idx.begin()
00162         );
00163 }
00164 
00165 
00166 void ExternalAtomTable::update(
00167 const ExternalAtom& oldStorage, ExternalAtom& newStorage) throw()
00168 {
00169     bool success;
00170 
00171     WriteLock lock(mutex);
00172     AddressIndex& idx = container.get<impl::AddressTag>();
00173     AddressIndex::iterator it(idx.iterator_to(oldStorage));
00174     assert(it != idx.end());
00175     success = idx.replace(it, newStorage);
00176     (void)success;
00177     assert(success);
00178 }
00179 
00180 
00181 DLVHEX_NAMESPACE_END
00182 #endif                           // BUILTINATOMTABLE_HPP_INCLUDED__12102010
00183 
00184 // vim:expandtab:ts=4:sw=4:
00185 // mode: C++
00186 // End: