// Copyright (C) 2018 Ford Motor Company
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page qtremoteobjects-replica.html
\title Qt Remote Objects Replica
\brief Describes the concept of a replica and how it works as a surrogate object.
\target Replica

A QRemoteObjectReplica ("replica") is a surrogate object that has approximately
the same API as the \l {Source} QObject it replicates. Additionally, there are
a few properties and signals to make it possible to detect when the replica is
initialized or if it loses its connection to the source object. There
are a few other differences, notably, a constant property on the source cannot
be constant on the replica. The value will not be known at the time when the
replica is instantiated; it will only be known once the replica is initialized.
For more information, see \l {Remote Object Interaction}.

A compiled replica is a \l {QRemoteObjectReplica} based type, where the derived
class definition is automatically generated by the \l {repc} compiler. When you
use \l {CMake functions} or \l {qmake variables} for running the \l repc compiler,
this makes the generation part of the build process. Although only a header is
generated, it's a complete type. There is no public constructor, so you need to
use the \l {QRemoteObjectNode::acquire} template function to create the Replica
instance.

A \l {QRemoteObjectDynamicReplica} can be generated at runtime. To do so, you
call \l {QRemoteObjectNode::acquireDynamic()}, passing in the source name
(a QString) as an argument. Dynamic replicas are a bit more verbose to use from
C++, but they do not require compilation. Dynamic replicas do not support
initial property values, or introspection until they have been initialized.

An important difference between these two ways of creating replicas is the
behavior before the replica is initialized. Since a dynamic replica only gets
a metaObject after initialization, it has basically no API before
initialization -- no properties, and no signals to connect slots to.

Because metaObjects for compiled replicas are created at compile-time, their
API is available when the replica is instantiated. You can even provide default
values for properties in the template file, which are used until the replica is
initialized with current values from the source.

\section1 Replica Initialization

A host node will share the list of sources that it hosts with every other node
that connects to it. This host sends updates when sources are added to or
removed from the list. In this way, a connected node will always know what
sources it can attach itself to. Changes to a specific source are only
propagated to nodes that have a replica of that source. Consequently, this
avoids any unnecessary network traffic.

When a node acquires a replica for a known source, it sends a request for that
source to the host node. Upon receiving this request, the host creates a reply
packet with the current values for all properties of that source. If the
requested replica is \l{QRemoteObjectDynamicReplica}{dynamic}, the reply packet
includes the API definition for the source. From then on, the replica's node
will be included in the list of connections that receive changes to that
source.

If a replica is instantiated but its node is not connected to the node that
hosts the requested source -- or that object lives in a host node process, but
sharing/remoting has not been enabled for the QObject -- the Replica will still
be created, but remain uninitialized.

If, at a later time, the replica's node gets notified that the requested source
is available from a connected node, at that point it will request the source
and start the initialization process.

If the connection to a host node is lost, the replica will transition to the
invalid state. It will attempt to reconnect and will re-initialize if the
connection is restored; this makes sure all properties are current.

\section1 Replica Ownership

The acquire methods return a pointer to the replica QObject instantiated by the
node. The node has no way of knowing the replica's intended lifetime.
Consequently, when the replica is not longer needed, it is the calling
program's responsibility to delete it.

You can instantiate multiple copies of the same replica. All replicas of the
same source from a single node will share a private data member which handles
the network communication. This means multiple instances of a replica do not
introduce additional network traffic, although there will be some additional
processing overhead. Failing to delete replicas will prevent the reference
count on this private object from reaching 0, and cause unnecessary network
communication until the calling process exits. For this reason, it is
recommended to use \l {QScopedPointer} or \l {QSharedPointer} to help track
the lifetime of replicas.

*/
