Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F360701
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Size
22 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 63cf40f..32b73b2 100755
--- a/include/rosa/support/tokenized_storages.hpp
+++ b/include/rosa/support/tokenized_storages.hpp
@@ -1,501 +1,620 @@
//===-- 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-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 token_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 token_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 token_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;
+/// \defgroup TokenizedStorageForTypeList Implementation of
+/// rosa::TokenizedStorageForTypeList
+///
+/// \brief Transforms a \c rosa::TypeList instance to the corresponding
+/// \c rosa::TokenizedStorage instance.
+///
+/// A \c rosa::TypeList \c List instance can be turned into a corresponding \c
+/// rosa::TokenizedStorage instance as \code
+/// typename TokenizedStorageForTypeList<List>::Type
+/// \endcode
+///
+/// For example, the following expression evaluates to `true`: \code
+/// std::is_same_v<typename TokenizedStorageForTypeList<TypeList<T1, T2>>::Type,
+/// TokenizedStorage<T1, T2>>
+/// \endcode
+///@{
+
+/// Declaration of the template.
+///
+/// \tparam List \c rosa::TypeList to transform
+template <typename List> struct TokenizedStorageForTypeList;
+
+/// Implementation of the template for \c rosa::TypeList instances.
+template <typename... Ts>
+struct TokenizedStorageForTypeList<TypeList<Ts...>> {
+ using Type = TokenizedStorage<Ts...>;
+};
+
+///@}
+
/// 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 Types types of values to store
///
/// \param Arena pre-allocated memory area to store values to
/// \param Ts values to store in \p Arena
///
/// \pre \p Arena is not \p nullptr.
template <typename... Types>
inline void createArenaElements(void *const Arena,
const Types &... Ts) noexcept {
ASSERT(Arena != nullptr);
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 Types types of values to store
///
/// \param Arena pre-allocated memory area to store values to
/// \param Ts values to store in \p Arena
///
/// \pre \p Arena is not \c nullptr.
template <typename... Types>
inline void createArenaElements(void *const Arena, Types &&... Ts) noexcept {
ASSERT(Arena != nullptr);
createArenaElement<0>(Arena, TokenizedStorage<Types...>::Offsets,
std::move(Ts)...);
}
/// Destroys values allocated by \c createArenaElements.
///
/// \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... 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 Types types of values to destroy
///
/// \param Arena the memory area to destroy values from
///
/// \pre \p Arena is not \c nullptr.
template <typename... Types>
inline void destroyArenaElements(void *const Arena) noexcept {
ASSERT(Arena != nullptr);
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 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<Types>::type...>::Value;
+ static constexpr Token ST = TypeToken<std::decay_t<Types>...>::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 token_size_t N = lengthOfToken(T); // Number of types encoded in \c T.
std::vector<size_t> O(N); // Allocate vector of proper size.
// Do nothing for 0 elements.
if (N > 0) {
token_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);
}
return O;
}
public:
/// Creates an instance with default values.
///
/// \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, Types()...);
}
/// Creates an instance from constant lvalue references.
///
/// \param Ts values to store
- TokenizedStorage(const Types &... Ts) noexcept
+ TokenizedStorage(const std::decay_t<Types> &... Ts) noexcept
: Arena(::operator new(sizeOfValuesOfToken(ST))) {
ASSERT(Arena != nullptr); // Sanity check.
createArenaElements(Arena, Ts...);
}
/// Creates an instance from rvalue references.
///
/// \param Ts values to store
- TokenizedStorage(Types &&... Ts) noexcept
+ TokenizedStorage(std::decay_t<Types> &&... Ts) noexcept
: Arena(::operator new(sizeOfValuesOfToken(ST))) {
ASSERT(Arena != nullptr); // Sanity check.
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<Types...>(Arena);
+ destroyArenaElements<std::decay_t<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 token_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 token_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 token_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 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> T &valueAt(const token_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 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 T &valueAt(const token_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... Types>
const std::vector<size_t>
TokenizedStorage<Types...>::Offsets = TokenizedStorage<Types...>::offsets();
+/// Specialization of the template \c rosa::TokenizedStorage for storing
+/// nothing.
+///
+/// \note The specialization implements the interface defined by \c
+/// rosa::AbstractTokenizedStorage but most of the functions cannot be called
+/// because nothing is stored in instances of the class.
+template <> class TokenizedStorage<> : public AbstractTokenizedStorage {
+public:
+ /// \c rosa::Token for the stored values.
+ static constexpr Token ST = TypeToken<>::Value;
+
+ /// Byte offsets to access stored values in \c rosa::TokenizedStorage::Arena.
+ static const std::vector<size_t> Offsets;
+
+ /// Creates an instance.
+ TokenizedStorage(void) noexcept {}
+
+ /// 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) {}
+
+ /// Tells how many values are stored in \p this object.
+ ///
+ /// \return `0`
+ size_t size(void) const noexcept override { return 0; }
+
+ /// Tells the type of the value stored at a position.
+ ///
+ /// \pre Do not call.
+ TypeNumber typeAt(const token_size_t) const noexcept override {
+ ASSERT(false);
+ return TypeNumber(0);
+ }
+
+ /// Provides an untyped pointer for the value stored at a position.
+ ///
+ /// \pre Do not call.
+ void *pointerTo(const token_size_t) noexcept override {
+ ASSERT(false);
+ return nullptr;
+ }
+
+ /// Provides a constant untyped pointer for the value stored at a position.
+ ///
+ /// \pre Do not call.
+ const void *pointerTo(const token_size_t) const noexcept override {
+ ASSERT(false);
+ return nullptr;
+ }
+
+ /// Tells if the value stored at a given index is of a given type.
+ ///
+ /// \pre Do not call.
+ template <typename> bool isTypeAt(const size_t) const noexcept {
+ ASSERT(false);
+ return false;
+ }
+
+ /// Gives a reference of a value of a given type stored at a given index.
+ ///
+ /// \tparam T type to give a reference of
+ /// \pre Do not call.
+ template <typename T> T &valueAt(const token_size_t) noexcept {
+ ASSERT(false);
+ return *static_cast<T *>(nullptr);
+ }
+
+ /// Gives a constant reference of a value of a given type stored at a given
+ /// index.
+ ///
+ /// \tparam T type to give a reference of
+ ///
+ /// \pre Do not call.
+ template <typename T> const T &valueAt(const token_size_t) const noexcept {
+ // \note Just use the non-const implementation as that does not modify
+ // \p this object.
+ return *static_cast<T *>(nullptr);
+ }
+};
+
} // End namespace rosa
#endif // ROSA_SUPPORT_TOKENIZED_STORAGES_HPP
diff --git a/lib/support/tokenized_storages.cpp b/lib/support/tokenized_storages.cpp
index ceb8a47..59d8eb6 100755
--- a/lib/support/tokenized_storages.cpp
+++ b/lib/support/tokenized_storages.cpp
@@ -1,20 +1,25 @@
//===-- support/tokenized_storages.cpp --------------------------*- C++ -*-===//
//
// The RoSA Framework
//
//===----------------------------------------------------------------------===//
///
/// \file support/tokenized_storages.cpp
///
/// \author David Juhasz (david.juhasz@tuwien.ac.at)
///
-/// \date 2017
+/// \date 2017-2019
///
/// \brief Implementation of rosa/support/tokenized_storages.hpp.
///
-/// \note Empty implementation, source file here to have a compile database
-/// entry for rosa/support/tokenized_storages.hpp.
-///
//===----------------------------------------------------------------------===//
#include "rosa/support/tokenized_storages.hpp"
+
+namespace rosa {
+
+// Implementation of the static member field \c
+// rosa::TokenizedStorage<>::Offsets.
+const std::vector<size_t> TokenizedStorage<>::Offsets = std::vector<size_t>(0);
+
+} // End namespace rosa
\ No newline at end of file
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Fri, May 16, 2:34 PM (6 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
141457
Default Alt Text
(22 KB)
Attached To
Mode
R20 SoC_Rosa_repo
Attached
Detach File
Event Timeline
Log In to Comment