DataMap.hpp
A DataMap links names to arbitrary object types.
A DataMap links data names to arbitrary object types. Each data map is composed of a MemoryImage (that holds a set of values) and a DataLayout (that maps names and other info to those values.)
AddVar<type>(“name”, value, [“desc”], [“notes”]) Includes a new data entry into the DataMap and returns its uniquq ID.
Get<type>(“name”) - retrieve a reference to a value in the DataMap slowly. Get<type>(ID) - retrieve a reference more quickly. GetID(“name”) - convert a name into a unique ID. Set(name|id, value) - change a value in the DataMap (you may also use Get() followed by an assignment.)
New data entries can be added to a DataMap, but never removed (for efficiency purposes). When a DataMap is copied, all data entries are also copied (relatively fast). As long as a DataMaps layout doesn’t change, all copied maps will share the same layout (fast).
A layout can also be locked with LockLayout(), which will throw an error if there is an attempt to modify that layout again. A lock can be checked with IsLocked().
Specialty versions of Get and Set exist if you don’t want to use templates for simple types. They are GetValue(*), SetValue(*), GetString(*), and SetString(*). Values are all represented as doubles.
DEVELOPER NOTES:
Each entry can have a one-byte control block immediately proceeding it in memory. Each bit would be associated with additional information about the entry. Options include:
The memory is a POINTER not an instance. This would allow entries to behave like references, potentially eliminating the need to copy larger data structures into the memory image.
The entry has a non-trivial (or user-provided) COPY/MOVE CONSTRUCTOR or DESTRUCTOR
The entry has a function to call for a Get instead of a value in memory. The space reserved is used for the function pointer (incompatible with bit 1…)
The entry has a function to call when it is set. Effectively this can implement SIGNAL monitoring it that should be notified whenever it changes. The signal itself would need to be stored elsewhere (presumably in the memory image, but possibly in the layout.)
The memory is a LOG of values, not a single value. This allows for quick identification of when something special needs to be done. 6-8. Limited type information (7 types that can be handled more effectively?)
We should be able to keep a series of values, not just a single one. This can be done with a series of new functions: AddLog() instead of AddVar() when new variable is created. Get() should still work for latest value. Ideally keep latest in first position. Change non-const Get() to GetRef() which cannot be used for a log. Add GetAve() function for logs as well as GetLog() for the full series (as std::span?).
Settings for all entries should have more information on how they are dealt with, such as if they should be included in output and how. Perhaps a system of tags for dynamic use?
After everything else is working, build a LocalDataMap<size_t> that locks in the size at compile time, providing more localized memory. Otherwise DataMap as a whole can be built on a templated class that takes an IMAGE_T as an argument.
Default values should be saved in the layout allowing any MemoryImage to be easily reset to factory settings.
A user should be able to override copy constructors (though probably not move constructors or destructors?). Then the copy process can be more customizable, for example having some settings return to the default value or be further processed. It’s also possible to have multiple types of copies, so if we indicate a “Copy birth” we get the above, but if we indicate a “Copy clone” or “Copy inject” we do something different. We also probably need to allow for multiple parents…
An OptimizeLayout() function that can reorder entries so that they are somehow more sensible? Does DataMap need to worry about memory alignment?
A MemoryImage factory to speed up allocation and deallocation if we’re using the same size images repeatedly.
Some way of grouping memory across DataMaps so that a particular entry for many maps has all of its instances consecutive in memory? This seems really tricky to pull off, but if we can do it, the improvement in cache performance could be dramatic.
Rename DataLayout and MemoryImage to DataMap_Layout and DataMap_Memory?
Note
Status: ALPHA
-
class DataMap
- #include <DataMap.hpp>
Public Functions
-
inline DataMap()
-
inline ~DataMap()
-
inline size_t GetSize() const
Determine how many Bytes large this image is.
-
inline bool HasID(size_t id) const
Test if this map has a setting ID.
-
inline bool HasName(const std::string &name) const
Test is this map has a variable by a given name.
-
template<typename T>
inline bool IsType(size_t id) const Test if a variable is of a given type.
-
template<typename T>
inline const T &Get(size_t id) const Retrieve a const variable by its type and position.
-
template<typename T>
inline T &Get(const std::string &name) Retrieve a variable by its type and name. (Slower!)
-
template<typename T>
inline const T &Get(const std::string &name) const Retrieve a const variable by its type and name. (Slower!)
-
inline bool IsNumeric(size_t id) const
-
inline double GetAsDouble(size_t id, TypeID type_id) const
Get the memory at the target position, assume it is the provided type, and convert the value found there to double.
-
inline double GetAsDouble(size_t id) const
Get the memory at the target position, lookup it’s type, and convert the value to double.
-
inline std::string GetAsString(size_t id, TypeID type_id, size_t count = 1) const
Get the memory at the target position, assume it is the provided type, and convert the value found there to string.
-
inline std::string GetAsString(size_t id) const
Get the memory at the target position, lookup it’s type, and convert the value to string.
-
template<typename T>
inline size_t AddVar(const std::string &name, const T &default_value, const std::string &desc = "", const std::string ¬es = "", size_t count = 1) Add a new variable with a specified type, name and value.
-
template<typename T>
inline size_t AddVar(const std::string &name) Add a new variable with just a specified type and name; must be able to default.
-
inline bool HasLayout(const DataLayout &in_layout) const
Test if this DataMap uses the specified layout.
-
inline bool HasLayout() const
Test if this DataMap has ANY layout.
-
inline bool SameLayout(const DataMap &in_dm) const
Test if this DataMap is using the identical layout as another DataMap.
-
inline DataLayout &GetLayout()
Get the DataLayout so that it can be used elsewhere.
-
inline const DataLayout &GetLayout() const
Get the DataLayout so that it can be used elsewhere.
-
inline bool IsLocked() const
Test if this layout is locked (i.e., it cannot be changed.)
-
inline void LockLayout()
Prevent this DataMap’s layout from having any additional changed made to it.
Public Static Functions
-
static inline std::function<Datum(const DataMap&)> MakeDatumAccessor(const DataLayout &layout, size_t id)
Return a function that takes in a data map and (efficiently) returns a Datum using the specified entry.
-
static inline auto MakeDatumAccessor(const DataLayout &layout, const std::string &name)
Return a function that takes in a data map and (efficiently) returns a Datum using the specified name.
Protected Functions
-
inline DataMap(Ptr<DataLayout> in_layout_ptr, size_t in_size)
-
inline void MakeLayoutUnique()
If the current layout is shared, make a copy of it.
Protected Attributes
-
MemoryImage memory
Memory contents for this Map.
-
Ptr<DataLayout> layout_ptr
Layout we are using (shared across maps w/ same format)
-
inline DataMap()