dlvhex  2.5.0
include/dlvhex2/ModuleTable.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 MODULETABLE_HPP_INCLUDED__20122010
00035 #define MODULETABLE_HPP_INCLUDED__20102010
00036 
00037 #include "dlvhex2/PlatformDefinitions.h"
00038 #include "dlvhex2/Logger.h"
00039 #include "dlvhex2/ID.h"
00040 #include "dlvhex2/Module.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 ModuleTable:
00051 public Table<
00052 // value type is symbol struct
00053 Module,
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::ModuleNameTag>,
00063 BOOST_MULTI_INDEX_MEMBER(Module,std::string,moduleName)
00064 >
00065 >
00066 >
00067 {
00068     public:
00069         // types
00070         typedef Container::index<impl::AddressTag>::type AddressIndex;
00071         typedef AddressIndex::iterator AddressIterator;
00072         typedef Container::index<impl::ModuleNameTag>::type ModuleNameIndex;
00073 
00074         // methods
00075     public:
00076 
00080         inline const Module& getByAddress(int address) const throw ();
00081 
00085         inline const std::string& getModuleName(int address) const throw ();
00086 
00091         inline std::pair<AddressIterator, AddressIterator> getAllByAddress() const throw();
00092 
00095         inline const Module& getModuleByName(const std::string& moduleName) const throw();
00096 
00100         inline int getAddressByName(const std::string& moduleName) const throw();
00101 
00107         inline int storeAndGetAddress(const Module& mod) throw();
00108 
00115         inline virtual std::ostream& print(std::ostream& o) const;
00116 
00117 };
00118 
00119 // get range over all atoms sorted by address
00120 // NOTE: you may need to lock the mutex also while iterating!
00121 std::pair<ModuleTable::AddressIterator, ModuleTable::AddressIterator>
00122 ModuleTable::getAllByAddress() const throw()
00123 {
00124     ReadLock lock(mutex);
00125     const AddressIndex& idx = container.get<impl::AddressTag>();
00126     return std::make_pair(idx.begin(), idx.end());
00127 }
00128 
00129 
00130 std::ostream& ModuleTable::print(std::ostream& o) const
00131 {
00132     ReadLock lock(mutex);
00133     const AddressIndex& idx = container.get<impl::AddressTag>();
00134     AddressIndex::const_iterator it = idx.begin();
00135     int address = 0;
00136     while ( it != idx.end() ) {
00137         o << "[" << address << "]" << ": " << *it << std::endl;
00138         it++;
00139         address++;
00140     }
00141     return o;
00142 }
00143 
00144 
00145 // retrieve by address
00146 const Module& ModuleTable::getByAddress(int address) const throw ()
00147 {
00148     ReadLock lock(mutex);
00149     const AddressIndex& idx = container.get<impl::AddressTag>();
00150     // the following check only works for random access indices, but here it is ok
00151     const uint32_t& uaddress = address;
00152     assert( uaddress < idx.size() );
00153     return idx.at(address);
00154 }
00155 
00156 
00157 // retrieve by address
00158 const std::string& ModuleTable::getModuleName(int address) const throw ()
00159 {
00160     ReadLock lock(mutex);
00161     const AddressIndex& idx = container.get<impl::AddressTag>();
00162     // the following check only works for random access indices, but here it is ok
00163     const uint32_t& uaddress = address;
00164     assert( uaddress < idx.size() );
00165     return idx.at(address).moduleName;
00166 }
00167 
00168 
00169 // given a module name, look if already stored
00170 // if no, return MODULE_FAIL, otherwise return the module struct
00171 const Module& ModuleTable::getModuleByName(const std::string& moduleName) const throw()
00172 {
00173     ReadLock lock(mutex);
00174     const ModuleNameIndex& sidx = container.get<impl::ModuleNameTag>();
00175     ModuleNameIndex::const_iterator it = sidx.find(moduleName);
00176     if( it == sidx.end() ) {
00177         return MODULE_FAIL;
00178     }
00179     else {
00180         return *it;
00181     }
00182 }
00183 
00184 
00185 // given a module name, look if already stored
00186 // if no, return -1, otherwise return the address
00187 int ModuleTable::getAddressByName(const std::string& moduleName) const throw()
00188 {
00189     ReadLock lock(mutex);
00190     const ModuleNameIndex& sidx = container.get<impl::ModuleNameTag>();
00191     ModuleNameIndex::const_iterator it = sidx.find(moduleName);
00192     if( it == sidx.end() ) {
00193         return -1;
00194     }
00195     else {
00196         return container.project<impl::AddressTag>( it ) - container.get<impl::AddressTag>().begin();
00197     }
00198 }
00199 
00200 
00201 // store module, assuming it does not exist
00202 // assert that symbol did not exist
00203 int ModuleTable::storeAndGetAddress(const Module& mod) throw()
00204 {
00205     assert(!mod.moduleName.empty());
00206 
00207     AddressIndex::const_iterator it;
00208     bool success;
00209 
00210     WriteLock lock(mutex);
00211     AddressIndex& idx = container.get<impl::AddressTag>();
00212     boost::tie(it, success) = idx.push_back(mod);
00213     (void)success;
00214     assert(success);
00215 
00216     return ( container.project<impl::AddressTag>(it) - idx.begin() );
00217 
00218 }
00219 
00220 
00221 DLVHEX_NAMESPACE_END
00222 #endif                           // MODULETABLE_HPP_INCLUDED__20122010
00223 
00224 // vim:expandtab:ts=4:sw=4:
00225 // mode: C++
00226 // End: