参考
References are used to manage allocated objects and to reference-count these objects. For example, when all references to a given object are deleted, the object itself will be deleted. References are based on the maxon::BaseRef template.
The following reference types are available:
Using these reference templates, non-intrusive reference counting can be applied to any allocated object. A reference based alias implements a "Create()" function that allows the easy allocation of a new, reference counted instance.
For safe access to a reference from multiple threads see maxon::ThreadSafeRef .
maxon::Pointer is handling an ordinary C++ pointer.
A maxon::UniqueRef stores a pointer to a given object. It will delete the object when itself is destroyed. Only one maxon::UniqueRef can have the ownership of a given object at a time.
// define alias using ElementRef = maxon::UniqueRef<SimpleElement> ;
// set data ref->_data = 123; // read data DiagnosticOutput ("Data: @", ref->_data); // when the scope is left, UniqueRef and the allocated element are destroyed }
// This example shows how a UniqueRef is used to manage a newly created object. // If the function fails, the UniqueRef will destroy the allocated object. // If the ownership could be transferred successfully, UniqueRef will release it.
//---------------------------------------------------------------------------------------- // Creates a SimpleElement object and adds it to the given PointerArray // @param[in] elements The array to store the new object. // @return maxon::OK on success. //---------------------------------------------------------------------------------------- static maxon::Result<void> AddElement( maxon::PointerArray<SimpleElement> & elements) { iferr_scope ;
// allocate new element // UniqueRef takes ownership maxon::UniqueRef<SimpleElement> ref = NewObj (SimpleElement) iferr_return ;
// element is handed over to the PointerArray which will take ownership // if this operations fails, UniqueRef makes sure the allocated element is freed 元素。 AppendPtr (ref) iferr_return ;
// the PointerArray has taken ownership // UniqueRef must release ownership ref. Disconnect ();
maxon::AutoMem is an alias for maxon::UniqueRef handling raw memory maxon::RawMem . See also Memory Allocation .
// This example uses AutoMem to manage the allocated memory. MAXON_SCOPE { // new elements are allocated, AutoMem takes ownership maxon::AutoMem<SimpleElement> data = NewMemClear (SimpleElement, count) iferr_return ;// data is filled for ( maxon::Int i = 0; i < count; ++i) data[i]._data = i;
// when the scope is left, AutoMem will delete the allocated memory }
One or many maxon::StrongRef objects can reference a given object in memory. When all strong references to that object are destroyed, the object will be deleted.
// This example stores the newly created object in a StrongRef. // The StrongRef takes ownership and deletes the object when itself is destroyed.// allocate object SimpleElement* const obj = NewObj (SimpleElement) iferr_return ; // set data obj->_data = 123; MAXON_SCOPE { // strong reference takes ownership const maxon::StrongRef<SimpleElement> ref(obj);
// print data DiagnosticOutput ( "Data: @" , ref->_data);
// when the scope is left, the StrongRef is destroyed // and with it the referenced object }
// now "obj" has been freed
// This example defines an alias for a StrongRef managing a SimpleElement. // This alias can be used to create a new instance of that SimpleElement that // is owned by a StrongRef. A copy of the original StrongRef is then created. // The copy is pointing to the same data as the original.
// defining an alias using SimpleRef = maxon::StrongRef<SimpleElement> ; MAXON_SCOPE { // allocate the object const SimpleRef original = SimpleRef::Create() iferr_return ; original->_data = 123; MAXON_SCOPE { // create a copy of the StrongRef const SimpleRef copy = original; // edit original data original->_data = 456; // "original" and "copy" are pointing to the same data DiagnosticOutput ( "@ : @" , original->_data, copy->_data);
// when the scope is left, SimpleRef "copy" is destroyed }
// when the scope is left, SimpleRef "original" is destroyed // and the allocated object with it }
A maxon::StrongRef can also manage raw memory:
// This example manages the newly allocated memory // with a StrongRef that frees the memory at the end. MAXON_SCOPE { // allocate memory maxon::StrongRef<maxon::RawMem<SimpleElement> > data = NewMem (SimpleElement, count) iferr_return ;// data is filled for ( maxon::Int i = 0; i < count; ++i) data[i]._data = i;
// when the scope is left, the allocated memory is deleted }
A maxon::StrongCOWRef is the same as maxon::StrongRef but it supports copy-on-write techniques. As long as no reference is trying to modify the referenced object, all references point to the same object. When a reference wants to modify the object, the object is copied and the reference used for modification has ownership of that new object.
// This example shows how a StrongCOWRef is used to manage objects. // The StrongCOWRef takes ownership of a newly created object. // Then a copy of the original StrongCOWRef is created. As long // as the data does not change, both the original and the copy // point to the same data. Only when the copy should be changed // using MakeWritable() will a new object be created.// defining an alias using SimpleCOWRef = maxon::StrongCOWRef<SimpleElement> ; MAXON_SCOPE { // allocates the object SimpleElement* const data = NewObj (SimpleElement) iferr_return ; // set data data->_data = 100;
// StrongCOWRef takes ownership const SimpleCOWRef original(data); MAXON_SCOPE { // create a copy of the StrongCOWRef SimpleCOWRef copy = original;
// edit original data data->_data = 200;
// "original" and "copy" are pointing to the same data DiagnosticOutput ( "@ : @" , original->_data, copy->_data);
// make copy writeable; a new instance will be allocated, owned by "copy" SimpleElement& copyData = copy.MakeWritable() iferr_return ; copyData._data = 300;
// original and copy will now store different data DiagnosticOutput ( "@ : @" , original->_data, copy->_data);
// when the scope is left, StrongCOWRef "copy" is destroyed }
// when the scope is left, StrongCOWRef "original" is destroyed // and the allocated object with it }
A maxon::WeakRef points to an object owned by a maxon::StrongRef . When there are no more strong references, the object is deleted and the maxon::WeakRef returns a null reference.
// This example uses WeakRefs to access data managed with a StrongRef.// define alias using SimpleRef = maxon::StrongRef<SimpleElement> ;
// allocate an element SimpleElement* const element = NewObj (SimpleElement) iferr_return ; element->_data = 123;
// prepare WeakRef maxon::WeakRef<SimpleRef> weakRef; MAXON_SCOPE { // StrongRef takes ownership const SimpleRef strongRef(element);
// set WeakRef weakRef = strongRef;
// WeakRef is valid if (weakRef) { // use WeakRef to access data const SimpleRef data = weakRef; DiagnosticOutput ( "Data: @" , data->_data); }
// when the scope is left, SimpleRef gets destroyed // and the allocated element will be freed }
// now WeakRef points to nothing if (!weakRef) DiagnosticOutput ( "WeakRef invalid" );
Instances of custom classes can be managed with maxon::BaseRef based reference types. If it is needed to modify the reference-counting behaviour one can implement the following functions in the custom class:
AddReference()
: Is called when a reference to the object is added.
RemoveReference()
: Is called when a reference to the object is removed.
CreateStrongReference()
: Is called when a strong reference is added.
AddWeakReference()
: Is called when a weak reference to the object is added.
InitialReference()
: Sets the initial reference to a newly allocated object.
This is typically used for:
//---------------------------------------------------------------------------------------- // A simple, reference counted object. //---------------------------------------------------------------------------------------- class ReferencedElement { public : //---------------------------------------------------------------------------------------- // Constructor. //---------------------------------------------------------------------------------------- MAXON_IMPLICIT ReferencedElement() { _data = 0; }
//---------------------------------------------------------------------------------------- // Destructor. //---------------------------------------------------------------------------------------- ~ReferencedElement() { _data = 0; }
//---------------------------------------------------------------------------------------- // Adds a reference to this instance. //---------------------------------------------------------------------------------------- void AddReference() const { DiagnosticOutput ( "Add reference" ); // increase reference count maxon::System::GetReferenceCounter ( this ). Inc (); }
//---------------------------------------------------------------------------------------- // Removes a reference pointing to this instance. // The object will be deleted if this was the last reference. //---------------------------------------------------------------------------------------- void RemoveReference() const { DiagnosticOutput ( "Remove reference" ); // decrease reference count if ( maxon::System::GetReferenceCounter ( this ).Dec()) { // if the last strong reference was released, // delete the object maxon::DeleteConstPtrObj ( this ); } } maxon::Int _data; };
// This example uses the class ReferencedElement that manages its own reference counting. ReferencedElement* const element = NewObj (ReferencedElement) iferr_return ; element->_data = 123; MAXON_SCOPE { // store in StrongRef, AddReference() will be called const maxon::StrongRef<ReferencedElement> firstRef(element); MAXON_SCOPE { // store in second StrongRef, AddReference() will be called const maxon::StrongRef<ReferencedElement> secondRef = firstRef;
// when the scope is left, "secondRef" is deleted and // RemoveReference() is called } // when the scope is left, "firstRef" is deleted, // RemoveReference() is called and the element freed }