Page MenuHomePhorge

No OneTemporary

Size
21 KB
Referenced Files
None
Subscribers
None
diff --git a/include/rosa/support/tokenized_storages.hpp b/include/rosa/support/tokenized_storages.hpp
index 0f5bdbf..36d10fb 100755
--- a/include/rosa/support/tokenized_storages.hpp
+++ b/include/rosa/support/tokenized_storages.hpp
@@ -1,510 +1,500 @@
//===-- rosa/support/tokenized_storages.hpp ---------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file rosa/support/tokenized_storages.hpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
-/// \date 2017
+/// \date 2017-2019
///
/// \brief Definition of storage helper template for storing values in a
/// type-safe way based on type tokens.
///
//===----------------------------------------------------------------------===//
#ifndef ROSA_SUPPORT_TOKENIZED_STORAGES_HPP
#define ROSA_SUPPORT_TOKENIZED_STORAGES_HPP
#include "rosa/support/type_token.hpp"
#include <memory>
#include <vector>
namespace rosa {
/// Defines a simple interface for storing and accessing values of different
/// types.
///
/// While the interface provides features to access values and know their
/// types, it is the users responsibility to use particular values according to
/// their actual types. No facilities for type-safe access of values is
/// provided by the class.
///
/// \see \c rosa::TokenizedStorage for a type-safe specialization of the
/// interface.
class AbstractTokenizedStorage {
protected:
/// Protected constructor restricts instantiation for derived classes.
AbstractTokenizedStorage(void) noexcept = default;
public:
/// No copying and moving of \c rosa::AbstractTokenizedStorage instances.
///@{
AbstractTokenizedStorage(const AbstractTokenizedStorage&) = delete;
AbstractTokenizedStorage &operator=(const AbstractTokenizedStorage&) = delete;
AbstractTokenizedStorage(AbstractTokenizedStorage&& Other) = delete;
AbstractTokenizedStorage &operator=(AbstractTokenizedStorage&&) = delete;
///@}
/// Destroys \p this object.
virtual ~AbstractTokenizedStorage(void) noexcept = default;
/// Tells how many values are stored in \p this object.
///
/// \return number of values stored in \p this object
virtual size_t size(void) const noexcept = 0;
/// Tells the type of the value stored at a position.
///
/// \param Pos the index of the value whose type is to returned
///
/// \return \c rosa::TypeNumber for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < size()
/// \endcode
virtual TypeNumber typeAt(const size_t Pos) const noexcept = 0;
/// Provides an untyped pointer for the value stored at a position.
///
/// \param Pos the index of the value to return an untyped pointer for
///
/// \return untyped pointer for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < size()
/// \endcode
virtual void *pointerTo(const size_t Pos) noexcept = 0;
/// Provides a constant untyped pointer for the value stored at a position.
///
/// \param Pos the index of the value to return an untyped pointer for
///
/// \return constant untyped pointer for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < Offsets.size()
/// \endcode
virtual const void *pointerTo(const size_t Pos) const noexcept = 0;
};
/// Template class storing values and providing dynamic type-safe access to
/// them in a lightweight way based on type tokens.
///
/// \see rosa/support/type_token.hpp
///
/// \tparam Types types whose values are to be stored
template <typename... Types> class TokenizedStorage;
/// Nested namespace with implementation for \c rosa::TokenizedStorage, consider
/// it private.
namespace {
/// Initializes a pre-allocated memory area with values from constant lvalue
/// references.
///
/// \tparam Types types whose values are to be stored
///
/// \param Arena pre-allocated memory area to store values to
/// \param Ts the values to store in \p Arena
///
/// \note \p Arena needs to be a valid pointer to a memory area big enough for
/// values of \p Types.
template <typename... Types>
inline void createArenaElements(void *const Arena,
const Types &... Ts) noexcept;
/// \defgroup createLvalueArenaElement Implementation of creating lvalue arena elements
///
/// Stores values from constant lvalue references into a pre-allocated memory
/// area.
///
/// \note To be used by the implementation of \c createArenaElements.
///
/// \todo Document these functions.
///@{
/// \note This terminal case is used for both constant lvalue references and
/// value references.
template <size_t Pos>
inline void createArenaElement(void *const,
const std::vector<size_t> &Offsets) {
ASSERT(Pos == Offsets.size());
}
template <size_t Pos, typename Type, typename... Types>
inline void createArenaElement(void *const Arena,
const std::vector<size_t> &Offsets,
const Type &T, const Types &... Ts) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
new (static_cast<Type *>(static_cast<void *>(static_cast<uint8_t *>(Arena) +
Offsets[Pos]))) Type(T);
createArenaElement<Pos + 1>(Arena, Offsets, Ts...);
}
template <size_t Pos, AtomValue V, typename... Types>
inline void
createArenaElement(void *const Arena, const std::vector<size_t> &Offsets,
const AtomConstant<V> &, const Types &... Ts) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
*static_cast<AtomValue *>(
static_cast<void *>(static_cast<uint8_t *>(Arena) + Offsets[Pos])) = V;
createArenaElement<Pos + 1>(Arena, Offsets, Ts...);
}
///@}
/// Implementation of the template.
///
-/// \tparam Type the type of the mandatory first value to store
-/// \tparam Types types of any further values to store
+/// \tparam Types types of values to store
///
/// \param Arena pre-allocated memory area to store values to
-/// \param T the first value to store in \p Arena˛
-/// \param Ts optional further values to store in \p Arena
+/// \param Ts values to store in \p Arena
///
/// \pre \p Arena is not \p nullptr.
-template <typename Type, typename... Types>
-inline void createArenaElements(void *const Arena, const Type &T,
+template <typename... Types>
+inline void createArenaElements(void *const Arena,
const Types &... Ts) noexcept {
ASSERT(Arena != nullptr);
- createArenaElement<0>(Arena, TokenizedStorage<Type, Types...>::Offsets, T,
- Ts...);
+ createArenaElement<0>(Arena, TokenizedStorage<Types...>::Offsets, Ts...);
}
/// Initializes a pre-allocated memory area with values from rvalue references.
///
/// \tparam Types types whose values are to be stored
///
/// \param Arena pre-allocated memory area to store values to
/// \param Ts the values to store in \p Arena
///
/// \note \p Arena needs to be a valid pointer to a memory area big enough for
/// values of \p Types.
template <typename... Types>
inline void createArenaElements(void *const Arena, Types &&... Ts) noexcept;
/// \defgroup createRvalueArenaElement Implementation of creating rvalue arena elements
///
/// Stores values from rvalue references into a pre-allocated memory area.
///
/// \note To be used by the implementation of \c createArenaElements.
///
/// \todo Document these functions.
///@{
template <size_t Pos, typename Type, typename... Types>
inline void createArenaElement(void *const Arena,
const std::vector<size_t> &Offsets, Type &&T,
Types &&... Ts) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
new (static_cast<Type *>(static_cast<void *>(
static_cast<uint8_t *>(Arena) + Offsets[Pos]))) Type(std::move(T));
createArenaElement<Pos + 1>(Arena, Offsets, std::move(Ts)...);
}
template <size_t Pos, AtomValue V, typename... Types>
inline void createArenaElement(void *const Arena,
const std::vector<size_t> &Offsets,
AtomConstant<V> &&, Types &&... Ts) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
*static_cast<AtomValue *>(
static_cast<void *>(static_cast<uint8_t *>(Arena) + Offsets[Pos])) = V;
createArenaElement<Pos + 1>(Arena, Offsets, std::move(Ts)...);
}
///@}
/// Implementation of the template.
///
-/// \tparam Type the type of the mandatory first value to store
-/// \tparam Types types of any further values to store
+/// \tparam Types types of values to store
///
/// \param Arena pre-allocated memory area to store values to
-/// \param T the first value to store in \p Arena
-/// \param Ts optional further values to store in \p Arena
+/// \param Ts values to store in \p Arena
///
/// \pre \p Arena is not \c nullptr.
-template <typename Type, typename... Types>
-inline void createArenaElements(void *const Arena, Type &&T,
- Types &&... Ts) noexcept {
+template <typename... Types>
+inline void createArenaElements(void *const Arena, Types &&... Ts) noexcept {
ASSERT(Arena != nullptr);
- createArenaElement<0>(Arena, TokenizedStorage<Type, Types...>::Offsets,
- std::move(T), std::move(Ts)...);
+ createArenaElement<0>(Arena, TokenizedStorage<Types...>::Offsets,
+ std::move(Ts)...);
}
/// Destroys values allocated by \c createArenaElements.
///
-/// \tparam Type type of the mandatory first value stored in \p Arena
-/// \tparam Types futher types whose values are stored in \p Arena
+/// \tparam Types types whose values are stored in \p Arena
///
/// \param Arena the memory area to destroy values from
///
/// \note \p Arena needs to be a valid pointer to a memory area where values of
/// \p Types are stored.
-template <typename Type, typename... Types>
+template <typename... Types>
inline void destroyArenaElements(void *const Arena) noexcept;
/// \defgroup destroyArenaElement Implementation of destroying arena elements
///
/// Destroys values from a memory area.
///
/// \note To be used by the implementation of \c destroyArenaElements.
///
/// \todo Document these functions.
///@{
template <size_t Pos>
inline void destroyArenaElement(void *const,
const std::vector<size_t> &Offsets) noexcept {
ASSERT(Pos == Offsets.size());
}
template <size_t Pos, typename Type, typename... Types>
inline void destroyArenaElement(void *const Arena,
const std::vector<size_t> &Offsets) noexcept {
ASSERT(Arena != nullptr && Pos < Offsets.size());
static_cast<Type *>(
static_cast<void *>(static_cast<uint8_t *>(Arena) + Offsets[Pos]))
->~Type();
destroyArenaElement<Pos + 1, Types...>(Arena, Offsets);
}
///@}
/// Implementation of the template.
///
-/// \tparam Type the type of the mandatory first value to destroy
-/// \tparam Types types of any further values to destroy
+/// \tparam Types types of values to destroy
///
/// \param Arena the memory area to destroy values from
///
/// \pre \p Arena is not \c nullptr.
-template <typename Type, typename... Types>
+template <typename... Types>
inline void destroyArenaElements(void *const Arena) noexcept {
ASSERT(Arena != nullptr);
- destroyArenaElement<0, Type, Types...>(
- Arena, TokenizedStorage<Type, Types...>::Offsets);
+ destroyArenaElement<0, Types...>(Arena, TokenizedStorage<Types...>::Offsets);
}
} // End namespace
/// Implementation of the template \c rosa::TokenizedStorage as a
/// specialization of \c rosa::AbstractTokenizedStorage.
///
/// The class provides facilities for storing values and providing type-safe
/// access to them.
///
-/// \tparam Type type of the first mandatory value to store
-/// \tparam Types of any further values to store
-template <typename Type, typename... Types>
-class TokenizedStorage<Type, Types...> : public AbstractTokenizedStorage {
+/// \tparam Types types of values to store
+template <typename... Types>
+class TokenizedStorage : public AbstractTokenizedStorage {
public:
/// \c rosa::Token for the stored values.
static constexpr Token ST =
- TypeToken<typename std::decay<Type>::type,
- typename std::decay<Types>::type...>::Value;
+ TypeToken<typename std::decay<Types>::type...>::Value;
/// Byte offsets to access stored values in \c rosa::TokenizedStorage::Arena.
static const std::vector<size_t> Offsets;
private:
/// A BLOB storing all the values one after the other.
void *const Arena;
/// Generates byte offsets for accessing values stored in
/// \c rosa::TokenizedStorage::Arena.
///
/// \return \c std::vector containing byte offsets for accessing values stored
/// in \c rosa::TokenizedStorage::Arena
static std::vector<size_t> offsets(void) noexcept {
Token T = ST; // Need a mutable copy.
const size_t N = lengthOfToken(T); // Number of types encoded in \c T.
- size_t I = 0; // Start indexing from position \c 0.
std::vector<size_t> O(N); // Allocate vector of proper size.
- O[0] = 0; // First offset is always \c 0.
- while (I < N - 1) {
- ASSERT(I + 1 < O.size() && lengthOfToken(T) == N - I);
- // Calculate next offset based on the previous one.
- // \note The offset of the last value is stored at `O[N - 1]`, which is
- // set when `I == N - 2`. Hence the limit of the loop.
- O[I + 1] = O[I] + sizeOfHeadOfToken(T);
- dropHeadOfToken(T), ++I;
+ // Do nothing for 0 elements.
+ if (N > 0) {
+ size_t I = 0; // Start indexing from position \c 0.
+ O[0] = 0; // First offset is always \c 0.
+ while (I < N - 1) {
+ ASSERT(I + 1 < O.size() && lengthOfToken(T) == N - I);
+ // Calculate next offset based on the previous one.
+ // \note The offset of the last value is stored at `O[N - 1]`, which is
+ // set when `I == N - 2`. Hence the limit of the loop.
+ O[I + 1] = O[I] + sizeOfHeadOfToken(T);
+ dropHeadOfToken(T), ++I;
+ }
+ ASSERT(I + 1 == O.size() && lengthOfToken(T) == 1);
}
- ASSERT(I + 1 == O.size() && lengthOfToken(T) == 1);
return O;
}
public:
/// Creates an instance with default values.
///
- /// \note This constructor requires that all actual template arguments \c Type
- /// and \c Types... are default constructible.
+ /// \note This constructor requires that all actual template arguments \p
+ /// Types... are default constructible.
TokenizedStorage(void) noexcept
: Arena(::operator new(sizeOfValuesOfToken(ST))) {
ASSERT(Arena != nullptr); // Sanity check.
- createArenaElements(Arena, Type(), Types()...);
+ createArenaElements(Arena, Types()...);
}
/// Creates an instance from constant lvalue references.
///
- /// \param T the mandatory first value to store
- /// \param Ts optional further values to store
- TokenizedStorage(const Type &T, const Types &... Ts) noexcept
+ /// \param Ts values to store
+ TokenizedStorage(const Types &... Ts) noexcept
: Arena(::operator new(sizeOfValuesOfToken(ST))) {
ASSERT(Arena != nullptr); // Sanity check.
- createArenaElements(Arena, T, Ts...);
+ createArenaElements(Arena, Ts...);
}
/// Creates an instance from rvalue references.
///
- /// \param T the mandatory first value to store
- /// \param Ts optional further values to store
- TokenizedStorage(Type &&T, Types &&... Ts) noexcept
+ /// \param Ts values to store
+ TokenizedStorage(Types &&... Ts) noexcept
: Arena(::operator new(sizeOfValuesOfToken(ST))) {
ASSERT(Arena != nullptr); // Sanity check.
- createArenaElements(Arena, std::move(T), std::move(Ts)...);
+ createArenaElements(Arena, std::move(Ts)...);
}
/// No copying and moving of \c rosa::TokenizedStorage instances.
///
/// \note This restriction may be relaxed as moving should be easy to
/// implement, only requires the possiblity to validate Arena pointer.
///@{
TokenizedStorage(const TokenizedStorage&) = delete;
TokenizedStorage &operator=(const TokenizedStorage&) = delete;
TokenizedStorage(TokenizedStorage&& Other) = delete;
TokenizedStorage &operator=(TokenizedStorage&&) = delete;
///@}
// Destroys \p this object.
~TokenizedStorage(void) {
- destroyArenaElements<Type, Types...>(Arena);
+ destroyArenaElements<Types...>(Arena);
::operator delete(Arena);
}
/// Tells how many values are stored in \p this object.
///
/// \return number of values stored in \p this object
size_t size(void) const noexcept override {
return Offsets.size();
}
/// Tells the type of the value stored at a position.
///
/// \param Pos the index of the value whose type is to returned
///
/// \return \c rosa::TypeNumber for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < size()
/// \endcode
TypeNumber typeAt(const size_t Pos) const noexcept override {
ASSERT(Pos < size());
Token TT = ST;
dropNOfToken(TT, Pos);
return headOfToken(TT);
}
/// Provides an untyped pointer for the value stored at a position.
///
/// \param Pos the index of the value to return an untyped pointer for
///
/// \return untyped pointer for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < size()
/// \endcode
void *pointerTo(const size_t Pos) noexcept override {
ASSERT(Pos < size());
return static_cast<uint8_t *>(Arena) + Offsets[Pos];
}
/// Provides a constant untyped pointer for the value stored at a position.
///
/// \param Pos the index of the value to return an untyped pointer for
///
/// \return constant untyped pointer for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index:\code
/// Pos < Offsets.size()
/// \endcode
const void *pointerTo(const size_t Pos) const noexcept override {
ASSERT(Pos < size());
return static_cast<const uint8_t *>(Arena) + Offsets[Pos];
}
/// Tells if the value stored at a given index is of a given type.
///
/// \note Any \c rosa::AtomConstant is encoded in \c rosa::Token as
/// the \c rosa::AtomValue wrapped into it.
///
/// \tparam T type to match against
///
/// \param Pos index the type of the value at is to be matched against \p Type
///
/// \return if the value at index \p Pos of type \p T
///
/// \pre \p Pos is a valid index:\code
/// Pos < Offsets.size()
/// \endcode
template <typename T> bool isTypeAt(const size_t Pos) const noexcept {
ASSERT(Pos < size());
Token TT = ST;
dropNOfToken(TT, Pos);
return isHeadOfTokenTheSameType<T>(TT);
}
/// Gives a reference of a value of a given type stored at a given index.
///
/// \note The constant variant of the function relies on this implementation,
/// the function may not modify \p this object!
///
/// \tparam T type to give a reference of
///
/// \param Pos index to set the reference for
///
- /// \return reference of \p Type for the value stored at index \p Pos
+ /// \return reference of \p T for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index and the value at index \p Pos is of type
/// \p T:
/// \code
/// Pos < Size && isTypeAt<T>(Pos)
/// \endcode
- template <typename T> Type &valueAt(const size_t Pos) noexcept {
- ASSERT(Pos < size() && isTypeAt<Type>(Pos));
- return *static_cast<Type *>(pointerTo(Pos));
+ template <typename T> T &valueAt(const size_t Pos) noexcept {
+ ASSERT(Pos < size() && isTypeAt<T>(Pos));
+ return *static_cast<T *>(pointerTo(Pos));
}
/// Gives a constant reference of a value of a given type stored at a given
/// index.
///
/// \tparam T type to give a reference of
///
/// \param Pos index to set the reference for
///
- /// \return constant reference of \p Type for the value stored at index \p Pos
+ /// \return constant reference of \p T for the value stored at index \p Pos
///
/// \pre \p Pos is a valid index and the value at index \p Pos is of type
/// \p T:
/// \code
/// Pos < Size && isTypeAt<T>(Pos)
/// \endcode
- template <typename T> const Type &valueAt(const size_t Pos) const noexcept {
+ template <typename T> const T &valueAt(const size_t Pos) const noexcept {
// \note Just use the non-const implementation as that does not modify
// \p this object.
return const_cast<TokenizedStorage *>(this)->valueAt<T>(Pos);
}
};
// Implementation of the static member field \c rosa::TokenizedStorage::Offsets.
-template <typename Type, typename... Types>
-const std::vector<size_t> TokenizedStorage<Type, Types...>::Offsets =
- TokenizedStorage<Type, Types...>::offsets();
+template <typename... Types>
+const std::vector<size_t>
+ TokenizedStorage<Types...>::Offsets = TokenizedStorage<Types...>::offsets();
} // End namespace rosa
#endif // ROSA_SUPPORT_TOKENIZED_STORAGES_HPP

File Metadata

Mime Type
text/x-diff
Expires
Fri, Jul 4, 2:21 AM (6 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
157427
Default Alt Text
(21 KB)

Event Timeline