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
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
/**
 * @file ReferencesExample1.cpp
 * @brief Source file for class ReferencesExample1
 * @date 14/03/2018
 * @author Andre' Neto
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing, 
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.

 * @details This source file contains the definition of all the methods for
 * the class ReferencesExample1 (public, protected, and private). Be aware that some
 * methods, such as those inline could be defined on the header file, instead.
 */

#define DLL_API

/*---------------------------------------------------------------------------*/
/*                         Standard header includes                          */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                         Project header includes                           */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "ClassRegistryDatabase.h"
#include "ErrorLoggerExample.h"
#include "Object.h"
#include "Reference.h"
#include "StreamString.h"

/*---------------------------------------------------------------------------*/
/*                           Static definitions                              */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                           Method definitions                              */
/*---------------------------------------------------------------------------*/
namespace MARTe2Tutorial {
/**
 * @brief A MARTe::Object class will be automatically
 * registered into the ClassRegistryDatabase.
 */
class ControllerEx1: public MARTe::Object {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief NOOP.
     */
ControllerEx1    () {
        gain = 0u;
    }

    /**
     * A property.
     */
    MARTe::uint32 gain;
};

CLASS_REGISTER(ControllerEx1, "")
}

int main(int argc, char **argv) {
    using namespace MARTe;
    SetErrorProcessFunction(&ErrorProcessExampleFunction);

    CCString className = "ControllerEx1";
    //Automatically generate a new object instance based on the class name and on the correct Heap
    Reference ref1(className, GlobalObjectsDatabase::Instance()->GetStandardHeap());
    Reference ref2(className, GlobalObjectsDatabase::Instance()->GetStandardHeap());
    Reference ref3;

    //ref3 is not initialised and thus should not be valid
    if (ref1.IsValid() && ref2.IsValid() && !ref3.IsValid()) {
        ref1->SetName("ControllerInstance1");
        ref2->SetName("ControllerInstance2");
        //ref1 and ref2 are referencing two different object instances of the same class
        Object *referencedObj1 = ref1.operator ->();
        Object *referencedObj2 = ref2.operator ->();

        if (referencedObj1 != referencedObj2) {
            REPORT_ERROR_STATIC(ErrorManagement::Information, "As expected ref1 "
            		"and ref2 are NOT pointing at the "
            		"same instance (%s != %s).", ref1->GetName(), ref2->GetName());
        }

        ref3 = ref1;
        //ref3 is now valid and should point at the same object as ref1
        Object *referencedObj3 = ref3.operator ->();
        if (referencedObj1 == referencedObj3) {
            REPORT_ERROR_STATIC(ErrorManagement::Information, "As expected ref1 "
            		"and ref3 are pointing at the "
            		"same instance (%s == %s).", ref1->GetName(), ref3->GetName());
        }
    }
    else {
        REPORT_ERROR_STATIC(ErrorManagement::FatalError, "One of the references is not correct.");
    }

    return 0;
}

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

Reference counting (ReferencesExample2)
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
 * @file ReferencesExample2.cpp
 * @brief Source file for class ReferencesExample2
 * @date 14/03/2018
 * @author Andre' Neto
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing, 
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.

 * @details This source file contains the definition of all the methods for
 * the class ReferencesExample2 (public, protected, and private). Be aware that some
 * methods, such as those inline could be defined on the header file, instead.
 */

#define DLL_API

/*---------------------------------------------------------------------------*/
/*                         Standard header includes                          */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                         Project header includes                           */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "ClassRegistryDatabase.h"
#include "ErrorLoggerExample.h"
#include "Object.h"
#include "Reference.h"
#include "StreamString.h"

/*---------------------------------------------------------------------------*/
/*                           Static definitions                              */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                           Method definitions                              */
/*---------------------------------------------------------------------------*/
namespace MARTe2Tutorial {
/**
 * @brief A MARTe::Object class will be automatically registered
 * into the ClassRegistryDatabase.
 */
class ControllerEx1: public MARTe::Object {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief NOOP.
     */
    ControllerEx1() {
        gain = 0u;
    }

    virtual ~ControllerEx1() {
        using namespace MARTe;
        if (GetName() != NULL) {
            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more "
            		"references pointing at %s [%s]. The Object will be "
            		"safely deleted.", GetName(), GetClassProperties()->GetName());
        }
    }

    /**
     * A property.
     */
    MARTe::uint32 gain;
};

CLASS_REGISTER(ControllerEx1, "")
}

void Function (MARTe::Reference ref) {
    using namespace MARTe;
    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
    		"pointing at %s is %d", ref->GetName(), ref.NumberOfReferences());

    CCString className = "ControllerEx1";
    //Automatically generate a new object instance based on the class name and on the correct Heap
    Reference ref2(className, GlobalObjectsDatabase::Instance()->GetStandardHeap());
    ref2->SetName("ControllerInstance2(FunctionMember)");
    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
    		"pointing at %s is %d", ref2->GetName(), ref2.NumberOfReferences());
}

int main(int argc, char **argv) {
    using namespace MARTe;
    SetErrorProcessFunction(&ErrorProcessExampleFunction);

    CCString className = "ControllerEx1";
    //Automatically generate a new object instance based on the class name and on the correct Heap
    Reference ref1(className, GlobalObjectsDatabase::Instance()->GetStandardHeap());
    ref1->SetName("ControllerInstance1");
    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
    		"pointing at %s is %d", ref1->GetName(), ref1.NumberOfReferences());
    Reference ref2 = ref1;
    Reference ref3 = ref1;
    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
    		"pointing at %s is %d", ref1->GetName(), ref1.NumberOfReferences());
    Function(ref3);
    REPORT_ERROR_STATIC(ErrorManagement::Information, "Number of references "
    		"pointing at %s is %d", ref1->GetName(), ref1.NumberOfReferences());

    return 0;
}

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
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/**
 * @file ReferencesExample3.cpp
 * @brief Source file for class ReferencesExample3
 * @date 14/03/2018
 * @author Andre' Neto
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing, 
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.

 * @details This source file contains the definition of all the methods for
 * the class ReferencesExample3 (public, protected, and private). Be aware that some
 * methods, such as those inline could be defined on the header file, instead.
 */

#define DLL_API

/*---------------------------------------------------------------------------*/
/*                         Standard header includes                          */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                         Project header includes                           */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "ClassRegistryDatabase.h"
#include "ErrorLoggerExample.h"
#include "Object.h"
#include "Reference.h"
#include "ReferenceT.h"
#include "StreamString.h"

/*---------------------------------------------------------------------------*/
/*                           Static definitions                              */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                           Method definitions                              */
/*---------------------------------------------------------------------------*/
namespace MARTe2Tutorial {
/**
 * @brief A MARTe::Object class will be automatically registered into the ClassRegistryDatabase.
 */
class MotorEx1: public MARTe::Object {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief NOOP.
     */
MotorEx1    () {
        property = 0u;
    }

    virtual ~MotorEx1() {
        using namespace MARTe;
        if (GetName() != NULL) {
            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references "
            		"pointing at %s [%s]. "
            		"The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
        }
    }

    /**
     * A property.
     */
    MARTe::uint32 property;
};

CLASS_REGISTER(MotorEx1, "")

class ControllerEx1: public MARTe::Object {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief NOOP.
     */
ControllerEx1    () {
        property2 = 0u;
    }

    virtual ~ControllerEx1() {
        using namespace MARTe;
        if (GetName() != NULL) {
            REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references "
            		"pointing at %s [%s]. The Object "
            		"will be safely deleted.", GetName(), GetClassProperties()->GetName());
        }
    }

    virtual void AFunction () {
        using namespace MARTe;
        REPORT_ERROR_STATIC(ErrorManagement::Information, "AFunction called @ %s.", GetName());
    }

    /**
     * A property.
     */
    MARTe::uint32 property2;
};

CLASS_REGISTER(ControllerEx1, "")

class PIDEx1: public ControllerEx1 {
public:
    CLASS_REGISTER_DECLARATION()

    /**
     * @brief NOOP.
     */
PIDEx1    () {
        property3 = 0u;
    }

    virtual ~PIDEx1() {
        using namespace MARTe;
        REPORT_ERROR_STATIC(ErrorManagement::Information, "No more references pointing "
        		"at %s [%s]. The Object will be safely deleted.", GetName(), GetClassProperties()->GetName());
    }

    virtual void AFunction () {
        using namespace MARTe;
        REPORT_ERROR_STATIC(ErrorManagement::Information, "AFunction called @ %s.", GetName());
    }
    /**
     * A property.
     */
    MARTe::uint32 property3;
};

CLASS_REGISTER(PIDEx1, "")
}

int main(int argc, char **argv) {
    using namespace MARTe;
    using namespace MARTe2Tutorial;
    SetErrorProcessFunction(&ErrorProcessExampleFunction);

    CCString className1 = "MotorEx1";
    CCString className2 = "ControllerEx1";
    CCString className3 = "PIDEx1";

    //Automatically generate a new object instance based on the class name and on the
    //correct Heap and with the template reference.
    ReferenceT<MotorEx1> ref1(className1, GlobalObjectsDatabase::Instance()->GetStandardHeap());
    if (ref1.IsValid()) {
        ref1->SetName("MotorInstance1");
        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully created an "
        		"instance of %s", className1.GetList());
    }

    //This should fail because className2 is not of type MotorEx1
    ReferenceT<MotorEx1> ref2(className2, GlobalObjectsDatabase::Instance()->GetStandardHeap());
    if (!ref2.IsValid()) {
        REPORT_ERROR_STATIC(ErrorManagement::Information, "As expected, could not create an "
        		"instance of %s", className2.GetList());
    }

    //Now it should work as the requested class name of is of the expected type (.
    ReferenceT<ControllerEx1> ref3(className2, GlobalObjectsDatabase::Instance()->GetStandardHeap());
    if (ref3.IsValid()) {
        ref3->SetName("ControllerInstance1");
        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully created an "
        		"instance of %s", className2.GetList());
    }

    //This mechanism also works with compatible subclasses PIDEx1->ControllerEx1
    ReferenceT<ControllerEx1> ref4(className3, GlobalObjectsDatabase::Instance()->GetStandardHeap());
    if (ref4.IsValid()) {
        ref4->SetName("PIDInstance1");
        REPORT_ERROR_STATIC(ErrorManagement::Information, "Successfully created an "
        		"instance of %s using the ReferenceT<ControllerEx1>", className3.GetList());
        ref4->AFunction();
    }

    return 0;
}

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