Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F386642
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
21 KB
Referenced Files
None
Subscribers
None
View Options
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
Details
Attached
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)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment