The managed objects should not work with classic C++ class members. The reason is that these don't implement the serialization interface that is needed for a functional support for class serialization that was mentioned in the previous section.
Instead, the Core proposes special data objects that fully conform to the principle that an user doesn't have to assist a class to become serializable, etc.
The Core distinguishes between two major types of managed data: properties and lightweight serializable types (we will simply call them STypes in the further text).
Whereas the latter implement only the serialization interface and don't provide any enhanced functionality, the former also contain some extra information about property ownership, etc. See Section 4.2.1, “Properties” for more information about the properties and Section 4.2.2, “Lightweight Serializable Types” for the STypes.
![]() | Note |
---|---|
The serialization process of properties doesn't consume more CPU time than the serialization of STypes, although some other operations on STypes may be more efficient. Also the format of binary or textual serialization of some variable is the same regardless on whether it is a property or a corresponding SType. |
![]() | Note |
---|---|
In fact the managed objects themselves are also managed data (specifically properties). It is perfectly legal to have managed objects as data members of another managed object. |
Properties are instances of classes derived (directly or indirectly) from the Massiv::Core::Property base class that, moreover, conform to some special implementation rules. Usually the relevant type names' first letter is P.
Properties have the following specific traits or features (see below for more detailed information):
Each property has a pointer to an owner property used to build hierarchies of properties. For example, if a property is simple member of property of class Foo, its owner is an object of type Foo. If a property is member of a container, the containter is its owner. Each property must be a member of some hierarchy - even those that are instantiated on the stack. A property that is not owned by another property is called root of the ownership hierarchy. Property hierachy information is maintained by the Core automatically.
Whenever a property is changed, the information about the change is propagated up the relevant property hierarchy. Finally the root of the hierarchy is informed. This is useful for making some part of the hierarchy dirty. During replication, only the dirty subhierarchy has to be transmitted over the network which saves the bandwidth.
Each property is able to enumerate all properties it owns - objects know about all properties, containers know about all contained properties.
Each property has its replication flags that determine what part of the property hierarchy would be replicated together with the object (see Chapter 7, Replication to learn more about the replication).
![]() | Note |
---|---|
Each property contains many auxiliary attributes. Thus, it consumes relatively large piece of memory. If you want a more efficient handling with the type and don't need the special features mentioned above, you should use STypes rather than properties. See also Section 4.2.2, “Lightweight Serializable Types”. |
The Core provides a reasonably wide set of property types available for the application. Properties can be either plain types such as integers, floating point numbers, pointers (in fact, pointers are also plain) or containers (the Core offers arrays, dictionaries and sets). Containers can hold instances of other properties by value (but always all the properties contained within must have the same type as the containers in Massiv are strongly typed), which includes even managed pointers and objects.
The odds are that the Core user will never need to write his own property (which wouldn't be as simple as just implementing the relevant class - you also would have to modify the IDL preprocessor). However we will still mention the implementation requirements, because
you will acquire a better confidence about what actions you can do safely with properties
managed objects are the only properties that will be implemented by an user
The following section describes the property implementation and usage issues. Any property implementation must be replicable and must contain:
Explicitly defined constructors. When a property is created, it should register to some existing property hierarchy or become a root of a new one. By default, properties are being registered to the hierarchy with root StackRootObject that primarily contains all properties instantiated on the stack.
If the property should be inside another hierarchy, it must be explicitly reinitialized. This can be done using several methods, for example initialize_from_owner() or initialize_object().
The assignment operator (operator=()). See the Massiv Core Reference Guide, module Properties for more information.
Serialization interface (see also Massiv Core Reference Guide, module Properties).
Enumeration interface to access owned properties. For example this interface contains the for_each_owned_property_do( ... ) method that enables to perform a specified operation on each property owned by the actual one. For more information see also Massiv Core Reference Guide, module Properties).
This chapter doesn't contain a list of specific property types available to the application. Instead, please refer to Section 10.13, “Property and Argument Types” for a somewhat brief information about the types usage and semantics. For the complete information see also the Massiv Core Reference Guide, module Properties.
Lightweight serializable types (also called STypes) are similar to the properties, but are much simplified. They only implement the serialization interface and some useful methods (see the Massiv Core Reference Guide, module Lightweight Serializable Types, to find out which ones), but don't contain the attributes such as the owner pointer, replication flags, etc.
In practice the STypes are useful only to be stored in containers or instantiated on stack more efficiently than properties.
![]() | Note |
---|---|
Unlike properties, the lightweight serializable type names are usually prefixed with the S letter. |
Note that STypes and property types are often defined in pairs. I.e. for each SType there exists a corresponding property and vice versa. There sometimes is also a native type (meaning C++-native) defined for each SType.
The property and native types for some specific SType can be obtained via the following type definitions nested into any SType class (where NATIVE and PROPERTY would be replaced by the relevant type name):
typedef NATIVE NativeType; // Native type corresponding to the SType. typedef PROPERTY PropertyType; // Property type corresponding to the SType. |
![]() | Note |
---|---|
If SType is not coupled with any native type, SType::NativeType should be set to the type that is returned by the read() method (see below). |
Each SType must have the following methods implemented (only those that might be interesting for the application have been enlisted):
read() returns the SType value that should be convertible to the native type.
to_string() returns object value as a string.
memory_size() returns a number of bytes occupied in the memory by the object.