CnC
|
Modules | |
Serialization of std::shared_ptr |
A common optimization used by CnC programs targeting the shared-memory runtime is to store pointers to large objects inside of item collections instead of copies of the objects. This is done to minimize the overhead of copying into and out of the item collection. Programs written in this style can be sued with distCnC, but special care needs to be taken.
Distributed CnC requires that data stored in item collections be serializable in order to communicate data between different processes. Consequently, the programmer must modify such pointer-using CnC programs in two ways in order to use the distributed-memory runtime. First, the programmer must provide a specialization of CnC::serialize for the pointer type pointing to T:
void CnC::serialize( CnC::serializer & ser, T *& ptr ) { ser & CnC::chunk< Your_class[, allocator] >( ptr, 1 ); }
Please refer to CnC::chunk to learn about appropriate memory management.
If the pointer represents a single object and not a C-style array, then the programmer may the use convenience macro:
CNC_POINTER_SERIALIZABLE( T );
This macro implements the above method for the case when the pointer refers to only a single object (length == 1). Note that if T is a type that contains template parameters, the programmer should create a typedef of the specific type being serialized and use this type as the argument for the macro.
Next, programmers must ensure that type T itself implements a default constructor and is serializable by itself. The latter as achieved as described above. It is the same method that programmers must provide if storing copies of objects instead of pointers to objects.
Reading from and writing to item collections is not different in this style of writing CnC programs. However, there are a few things to note:
When an object is communicated from one process to another, an item must be allocated on the receiving end. By default, CnC::chunk uses the default allocator for this and so requires the default constructor of T. After object creation, any fields are updated by the provided serialize methods. Thios default behavior simplifies the object allocation/deallocation: most of it is done automatically behind the scenes. The programmer should just pass an unitialized pointer to get(). The pointer will then point to the allocated object/array after the get completes.
In advanced and potentially dangerous setups, the programmer might wish to store the object into memory that has been previously allocated. This can be done by an explicit copy and explicit object lifetime control. Please note that such a scenario can easily lead to uses of CnC which do not comply with CnC's methodology, e.g. no side effects in steps and dynamic single assigments.