References

Objects are managed using Reference components.

References offer a smart pointer mechanism which guarantees that any MARTe Object can be safely shared (thread and interrupt safe) among different execution units. A different name can also be assigned to each object instance.

../../_images/References-1.png

Important

The new and delete operators shall not be used to manage the life cycle of any of the framework objects. The framework offers an object creation mechanism that returns a reference.

Each time a new Reference points at a given object, the Object number of references is incremented. Conversely, when a new reference no longer points at an Object, e.g. because it lost scope, the number of reference is decremented. When the number of references pointing at any given object is equal to zero, the object is destroyed.

The Reference constructor allows to create a new object using the class name.

Reference ref1("AClassName", GlobalObjectsDatabase::Instance()->GetStandardHeap());

Using the templated version, ReferenceT, the class type (or any of its polymorphic interfaces) is also constrained to be compatible with the class name. This is the basic mechanism that allows to verify that classes are compatible with a given implementation (e.g. to verify what references are pointing to objects whose class inherit from GAM).

Reference ref1("AClassName", GlobalObjectsDatabase::Instance()->GetStandardHeap());
Reference<ADerivedClass> ref2 = ref1;

Attention

Always check that a Reference IsValid before using it! There are many reasons why a Reference may not be valid: - It was not initialised; - The reference class type is not compatible with the class name; - When assigning a reference to an existent reference (ref1 = ref2), the classes are not compatible (e.g. because they do not share the same interface);

Examples

This example shows how to instantiate an Object by class name and how to assign a name to the instance.

Create by name example (ReferencesExample1)
  1/**
  2 * @file ReferencesExample1.cpp
  3 * @brief Source file for class ReferencesExample1
  4 * @date 14/03/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class ReferencesExample1 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ClassRegistryDatabase.h"
 35#include "ErrorLoggerExample.h"
 36#include "Object.h"
 37#include "Reference.h"
 38#include "StreamString.h"
 39
 40/*---------------------------------------------------------------------------*/
 41/*                           Static definitions                              */
 42/*---------------------------------------------------------------------------*/
 43
 44/*---------------------------------------------------------------------------*/
 45/*                           Method definitions                              */
 46/*---------------------------------------------------------------------------*/
 47namespace MARTe2Tutorial {
 48/**
 49 * @brief A MARTe::Object class will be automatically
 50 * registered into the ClassRegistryDatabase.
 51 */
 52class ControllerEx1: public MARTe::Object {
 53public:
 54    CLASS_REGISTER_DECLARATION()
 55
 56    /**
 57     * @brief NOOP.
 58     */
 59ControllerEx1    () {
 60        gain = 0u;
 61    }
 62
 63    /**
 64     * A property.
 65     */
 66    MARTe::uint32 gain;
 67};
 68
 69CLASS_REGISTER(ControllerEx1, "")
 70}
 71
 72int main(int argc, char **argv) {
 73    using namespace MARTe;
 74    SetErrorProcessFunction(&ErrorProcessExampleFunction);
 75
 76    CCString className = "ControllerEx1";
 77    //Automatically generate a new object instance based on the class name and on the correct Heap
 78    Reference ref1(className, GlobalObjectsDatabase::Instance()->GetStandardHeap());
 79    Reference ref2(className, GlobalObjectsDatabase::Instance()->GetStandardHeap());
 80    Reference ref3;
 81
 82    //ref3 is not initialised and thus should not be valid
 83    if (ref1.IsValid() && ref2.IsValid() && !ref3.IsValid()) {
 84        ref1->SetName("ControllerInstance1");
 85        ref2->SetName("ControllerInstance2");
 86        //ref1 and ref2 are referencing two different object instances of the same class
 87        Object *referencedObj1 = ref1.operator ->();
 88        Object *referencedObj2 = ref2.operator ->();
 89
 90        if (referencedObj1 != referencedObj2) {
 91            REPORT_ERROR_STATIC(ErrorManagement::Information, "As expected ref1 "
 92            		"and ref2 are NOT pointing at the "
 93            		"same instance (%s != %s).", ref1->GetName(), ref2->GetName());
 94        }
 95
 96        ref3 = ref1;
 97        //ref3 is now valid and should point at the same object as ref1
 98        Object *referencedObj3 = ref3.operator ->();
 99        if (referencedObj1 == referencedObj3) {
100            REPORT_ERROR_STATIC(ErrorManagement::Information, "As expected ref1 "
101            		"and ref3 are pointing at the "
102            		"same instance (%s == %s).", ref1->GetName(), ref3->GetName());
103        }
104    }
105    else {
106        REPORT_ERROR_STATIC(ErrorManagement::FatalError, "One of the references is not correct.");
107    }
108
109    return 0;
110}

This example highlights how the number of references change during the life cycle of a program.

Reference counting (ReferencesExample2)
  1/**
  2 * @file ReferencesExample2.cpp
  3 * @brief Source file for class ReferencesExample2
  4 * @date 14/03/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class ReferencesExample2 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ClassRegistryDatabase.h"
 35#include "ErrorLoggerExample.h"
 36#include "Object.h"
 37#include "Reference.h"
 38#include "StreamString.h"
 39
 40/*---------------------------------------------------------------------------*/
 41/*                           Static definitions                              */
 42/*---------------------------------------------------------------------------*/
 43
 44/*---------------------------------------------------------------------------*/
 45/*                           Method definitions                              */
 46/*---------------------------------------------------------------------------*/
 47namespace MARTe2Tutorial {
 48/**
 49 * @brief A MARTe::Object class will be automatically registered
 50 * into the ClassRegistryDatabase.
 51 */
 52class ControllerEx1: public MARTe::Object {
 53public:
 54    CLASS_REGISTER_DECLARATION()
 55
 56    /**
 57     * @brief NOOP.
 58     */
 59    ControllerEx1() {
 60        gain = 0u;
 61    }
 62
 63    virtual ~ControllerEx1() {
 64        using namespace MARTe;
 65        if (GetName() != NULL) {
 66            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more "
 67            		"references pointing at %s [%s]. The Object will be "
 68            		"safely deleted.", GetName(), GetClassProperties()->GetName());
 69        }
 70    }
 71
 72    /**
 73     * A property.
 74     */
 75    MARTe::uint32 gain;
 76};
 77
 78CLASS_REGISTER(ControllerEx1, "")
 79}
 80
 81void Function (MARTe::Reference ref) {
 82    using namespace MARTe;
 83    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
 84    		"pointing at %s is %d", ref->GetName(), ref.NumberOfReferences());
 85
 86    CCString className = "ControllerEx1";
 87    //Automatically generate a new object instance based on the class name and on the correct Heap
 88    Reference ref2(className, GlobalObjectsDatabase::Instance()->GetStandardHeap());
 89    ref2->SetName("ControllerInstance2(FunctionMember)");
 90    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
 91    		"pointing at %s is %d", ref2->GetName(), ref2.NumberOfReferences());
 92}
 93
 94int main(int argc, char **argv) {
 95    using namespace MARTe;
 96    SetErrorProcessFunction(&ErrorProcessExampleFunction);
 97
 98    CCString className = "ControllerEx1";
 99    //Automatically generate a new object instance based on the class name and on the correct Heap
100    Reference ref1(className, GlobalObjectsDatabase::Instance()->GetStandardHeap());
101    ref1->SetName("ControllerInstance1");
102    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
103    		"pointing at %s is %d", ref1->GetName(), ref1.NumberOfReferences());
104    Reference ref2 = ref1;
105    Reference ref3 = ref1;
106    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
107    		"pointing at %s is %d", ref1->GetName(), ref1.NumberOfReferences());
108    Function(ref3);
109    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
110    		"pointing at %s is %d", ref1->GetName(), ref1.NumberOfReferences());
111
112    return 0;
113}

This example shows how the ReferenceT can be used to verify compliance of the class name against the expected class type (or derived interface). Note that the class name “PIDEx1”’ is compatible with ControllerEx1.

ReferenceT (ReferencesExample3)
  1/**
  2 * @file ReferencesExample3.cpp
  3 * @brief Source file for class ReferencesExample3
  4 * @date 14/03/2018
  5 * @author Andre' Neto
  6 *
  7 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
  8 * the Development of Fusion Energy ('Fusion for Energy').
  9 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 10 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 11 * You may not use this work except in compliance with the Licence.
 12 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 13 *
 14 * @warning Unless required by applicable law or agreed to in writing, 
 15 * software distributed under the Licence is distributed on an "AS IS"
 16 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 17 * or implied. See the Licence permissions and limitations under the Licence.
 18
 19 * @details This source file contains the definition of all the methods for
 20 * the class ReferencesExample3 (public, protected, and private). Be aware that some
 21 * methods, such as those inline could be defined on the header file, instead.
 22 */
 23
 24#define DLL_API
 25
 26/*---------------------------------------------------------------------------*/
 27/*                         Standard header includes                          */
 28/*---------------------------------------------------------------------------*/
 29
 30/*---------------------------------------------------------------------------*/
 31/*                         Project header includes                           */
 32/*---------------------------------------------------------------------------*/
 33#include "AdvancedErrorManagement.h"
 34#include "ClassRegistryDatabase.h"
 35#include "ErrorLoggerExample.h"
 36#include "Object.h"
 37#include "Reference.h"
 38#include "ReferenceT.h"
 39#include "StreamString.h"
 40
 41/*---------------------------------------------------------------------------*/
 42/*                           Static definitions                              */
 43/*---------------------------------------------------------------------------*/
 44
 45/*---------------------------------------------------------------------------*/
 46/*                           Method definitions                              */
 47/*---------------------------------------------------------------------------*/
 48namespace MARTe2Tutorial {
 49/**
 50 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
 51 */
 52class MotorEx1: public MARTe::Object {
 53public:
 54    CLASS_REGISTER_DECLARATION()
 55
 56    /**
 57     * @brief NOOP.
 58     */
 59MotorEx1    () {
 60        property = 0u;
 61    }
 62
 63    virtual ~MotorEx1() {
 64        using namespace MARTe;
 65        if (GetName() != NULL) {
 66            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references "
 67            		"pointing at %s [%s]. "
 68            		"The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
 69        }
 70    }
 71
 72    /**
 73     * A property.
 74     */
 75    MARTe::uint32 property;
 76};
 77
 78CLASS_REGISTER(MotorEx1, "")
 79
 80class ControllerEx1: public MARTe::Object {
 81public:
 82    CLASS_REGISTER_DECLARATION()
 83
 84    /**
 85     * @brief NOOP.
 86     */
 87ControllerEx1    () {
 88        property2 = 0u;
 89    }
 90
 91    virtual ~ControllerEx1() {
 92        using namespace MARTe;
 93        if (GetName() != NULL) {
 94            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references "
 95            		"pointing at %s [%s]. The Object "
 96            		"will be safely deleted.", GetName(), GetClassProperties()->GetName());
 97        }
 98    }
 99
100    virtual void AFunction () {
101        using namespace MARTe;
102        REPORT_ERROR_STATIC(ErrorManagement::Information, "AFunction called @ %s.", GetName());
103    }
104
105    /**
106     * A property.
107     */
108    MARTe::uint32 property2;
109};
110
111CLASS_REGISTER(ControllerEx1, "")
112
113class PIDEx1: public ControllerEx1 {
114public:
115    CLASS_REGISTER_DECLARATION()
116
117    /**
118     * @brief NOOP.
119     */
120PIDEx1    () {
121        property3 = 0u;
122    }
123
124    virtual ~PIDEx1() {
125        using namespace MARTe;
126        REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references pointing "
127        		"at %s [%s]. The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
128    }
129
130    virtual void AFunction () {
131        using namespace MARTe;
132        REPORT_ERROR_STATIC(ErrorManagement::Information, "AFunction called @ %s.", GetName());
133    }
134    /**
135     * A property.
136     */
137    MARTe::uint32 property3;
138};
139
140CLASS_REGISTER(PIDEx1, "")
141}
142
143int main(int argc, char **argv) {
144    using namespace MARTe;
145    using namespace MARTe2Tutorial;
146    SetErrorProcessFunction(&ErrorProcessExampleFunction);
147
148    CCString className1 = "MotorEx1";
149    CCString className2 = "ControllerEx1";
150    CCString className3 = "PIDEx1";
151
152    //Automatically generate a new object instance based on the class name and on the
153    //correct Heap and with the template reference.
154    ReferenceT<MotorEx1> ref1(className1, GlobalObjectsDatabase::Instance()->GetStandardHeap());
155    if (ref1.IsValid()) {
156        ref1->SetName("MotorInstance1");
157        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully created an "
158        		"instance of %s", className1.GetList());
159    }
160
161    //This should fail because className2 is not of type MotorEx1
162    ReferenceT<MotorEx1> ref2(className2, GlobalObjectsDatabase::Instance()->GetStandardHeap());
163    if (!ref2.IsValid()) {
164        REPORT_ERROR_STATIC(ErrorManagement::Information, "As expected, could not create an "
165        		"instance of %s", className2.GetList());
166    }
167
168    //Now it should work as the requested class name of is of the expected type (.
169    ReferenceT<ControllerEx1> ref3(className2, GlobalObjectsDatabase::Instance()->GetStandardHeap());
170    if (ref3.IsValid()) {
171        ref3->SetName("ControllerInstance1");
172        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully created an "
173        		"instance of %s", className2.GetList());
174    }
175
176    //This mechanism also works with compatible subclasses PIDEx1->ControllerEx1
177    ReferenceT<ControllerEx1> ref4(className3, GlobalObjectsDatabase::Instance()->GetStandardHeap());
178    if (ref4.IsValid()) {
179        ref4->SetName("PIDInstance1");
180        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully created an "
181        		"instance of %s using the ReferenceT<ControllerEx1>", className3.GetList());
182        ref4->AFunction();
183    }
184
185    return 0;
186}

Instructions on how to compile and execute the examples can be found here.