added custom allocator support for pointer like objects.

This commit is contained in:
Mindaugas Vinkelis
2019-03-13 11:06:55 +02:00
committed by Mindaugas Vinkelis
parent 03f2c3c8b5
commit 57dd028b7a
14 changed files with 1047 additions and 287 deletions

40
doc/design/pointers.md Normal file
View File

@@ -0,0 +1,40 @@
*document in progress*
## Extensions
Raw pointers are managed by three extensions:
* **PointerOwner** - manages a lifetime of the pointer, creates or destroys if required.
* **PointerObserver** - doesn't own pointer so it doesn't create or destroy anything.
* **ReferencedByPointer** - when a non-owning pointer (*PointerObserver*) points to reference type, this extension marks this object as a valid target for PointerObserver.
"Smart" pointers, from c++ standard lib (std), are managed by:
* **StdSmartPtr** - can accept unique_ptr, shared_ptr and weak_ptr
## Implementation details
All aforementioned extensions derive from single base class `PointerObjectExtensionBase`.
This base class accepts three template parameters that customise its behaviour.
* `TPtrManager\<T\>` - describes how particular pointer type should be handled:
pointer creation/destruction describes a type of pointer (e.g. owning, shared, observer), and how to actually get value for pointer object.
This is the place to start if you want to implement pointer support for your custom type. \<T\> is type of pointer object, e.g. `std::unique_ptr<MyType>`, `MyType*`
* `TPolymorphicContext\<RTTI\>` - provides the functionality to register class hierarchies for your types with serializer, and deserializer, in order to polymorphically serialize/deserialize objects.
\<RTTI\> template parameter provides runtime information about a type that is used to construct class hierarchies and save them to read/write them to buffer.
* `RTTI` - this template parameter provides information if a type is polymorphic, and if it is, then it is used in `TPolymorphicContext\<RTTI\>`.
Some pointer managers, like `PointerObserver` and `ReferencedByPointer` never requires polymorphic context. In these cases, you need to provide RTTI that will return `isPolymorphic`=false for all types.
By default all pointers extensions use `StandardRTTI` from "/ext/utils/rtti_utils.h" that internally uses `typeid` and `dynamic_cast`.
If your environment doesn't allow RTTI, you can provide your own RTTI for your types.
## Allocators
Allocation is implemented using dynamic type for allocator (similar to `std::pmr::memory_resource` from c++17),
and it is called `MemResourceBase` from "ext/utils/memory_allocator.h". The core difference between standard one and this allocator
is that it has additional `size_t typeId` field for `allocate` and `deallocate` methods, this value is returned from `RTTI`.
There are few options to customise pointer allocation for your pointers:
* provide default allocator in `PointerLinkingContext` by calling `setMemResource`.
* provide an instance of `MemResourceBase*` to pointer manager constructor, along with boolean parameter that specifies if this memory resource should propagate when deserializing child objects.
If no memory resource is provided, then `MemResourceNewDelete` is used, which calls `::operator new(bytes)` and `::operator delete(ptr)`.
**IMPORTANT**: there are few things that you should know to correctly use custom allocations with `StdSmartPtr`:
* Memory resource must live as long as the last object, that was allocated with it (this is required by std::shared_ptr, custom deleter is provided, that will be able to deallocate correctly when a shared pointer is destroyed).
* std::unique_ptr acts differently with resources that it owns, depending on what deleter is used.
* if default deleter is used, then a pointer is *released* and deallocated using provided memory resource.
* if custom deleter is used, then a pointer is deallocated using this custom deleter.