User:Andrecaldas/SharedPtr

= Introduction: sharing document objects all over! = Each FreeCAD document (App::Document) is composed of document objects (DocumentObject). Each document object should be an autonomous structure that is functional even if it is not inserted in a document. It's behaviour cannot be unexpected just because it is not attached to a document.

Many functions deal with document objects. They are usually passed a pointer to the object. But the more FreeCAD becomes multithreaded, the more we need warranties that a certain object is still functional, even if while processing takes place, the object is concurrently removed from the document, for example.

Today, assuring that a certain object will not be destroyed or removed from the document it belongs to is a complicated task that relies on verifying its internal status (usually in thread-unsafe ways). For example:
 * Afraid of removing an object because of its status.
 * Others need to know that an object is about to be deleted.
 * Variable pcNameInDocument is set to nullptr to indicate some internal status change.
 * Document object is destructed only if it does not belong to a document.

Things can become much simpler and much safer if we use shared_ptr. As long as someone is holding a shared_ptr to an object, the object is (almost) guaranteed to be valid. If we design things in such a way that the document is functional even without belonging to a document, everything shall simply work without giving unexpected results (crash).

Pointer management
Instances of Document and DocumentObject should be managed by shared_ptr.

Data inside a DocumentObject can be:
 * Part of the object;
 * Managed by unique_ptr; or
 * Managed by shared_ptr.

Downward reference
Downward reference means ownership. The owning object shall hold a unique_ptr or shared_ptr to the downward reference.

Preferably, once set, those smart pointers should not change. This way, functions that are called in a context where a valid unique_ptr or shared_ptr are assured to exist during the function call can take raw pointers. In particular, functions called by methods in the class that owns a resource can take raw pointers.

Upward reference
Since objects can be detached from their owners in threads different from ours, upward references should be weak_ptr.

Methods that use this weak_ptr shall deal gracefully with weak_ptr::lock returning an invalid lock (shared_ptr). Those methods can either: 1. Return a reasonable default (preferable); or 2. Throw an exception.