Wednesday, April 27, 2016

C++ template and singleton

It is just annoying to see tons of singletons with their member variable _instance and their get member function manually typed.

Here is what I did.

So far, a singleton depends on its own class <T> and a response message <X>.  For messages without sophisticated structure, DummyResponseBody can be used as <X>.

1. The singleton header.
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
/*

 * ControlReqSingleton.h

 *

 *  Created on: Apr 26, 2016

 *      Author: Technoboundary

 */


#ifndef CONTROLREQSINGLETON_H_

#define CONTROLREQSINGLETON_H_


#include "ControlReq.h"


//Lang: For many ASN.1 request, the response does not have a body.

//      In order to use this framework, a dummy response body structure is used.

struct DummyResponseBody

{

    uint32_t dummy;

};


template <typename ...> class ControlReqSingleton;


template <class T, typename X>

class ControlReqSingleton<T, X> : public ControlReq {

public:

    ControlReqSingleton() {};

    virtual ~ControlReqSingleton() {};


    //ToDo: should be reference instead of pointer.

    static T* getControlReq()

    {

        if (NULL == _instance)

        {

            _instance = new T();

        }


        return _instance;

    }


    virtual void reInitialize()

    {

        ControlReq::reInitialize();

    }


    virtual void handleReq(ICD_ControlRequest* pMsg, eIntfcId intfcId_) = 0;

    virtual uint32_t getMessageTag() = 0;

    virtual X* fillResponseBody() = 0;


    virtual void genResp()

    {

        // put inquiry in control response body

        ControlReq::pControlResponse->body.t         = getMessageTag();

        // u is a union.

        ControlReq::pControlResponse->body.u.inquiry = (InquiryResponseBody*) fillResponseBody();


        // add common response

        ControlReq::addCommonResp();

    }


private:

    static T* _instance;

};


//initiate singleton instance here

template <class T, typename X>

T* ControlReqSingleton<T, X>::_instance = NULL;


#endif /* CONTROLREQSINGLETON_H_ */

2. derived class header
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
/*

 * AntennaRangeInquiry.h

 *

 *  Created on: Apr 26, 2016

 *      Author: Technoboundary

 */


#ifndef ANTENNARANGEINQUIRY_H_

#define ANTENNARANGEINQUIRY_H_


#include "ControlReqSingleton.h"


class AntennaRangeInquiry;


class AntennaRangeInquiry: public ControlReqSingleton<AntennaRangeInquiry, AntennaRangeInquiryResponse>{

public:

    AntennaRangeInquiry();

    virtual ~AntennaRangeInquiry();


    virtual void handleReq(ICD_ControlRequest* pMsg, eIntfcId intfcId_);

    virtual uint32_t getMessageTag();

    virtual AntennaRangeInquiryResponse* fillResponseBody();


    void fillAntennaRange();

};


#endif /* ANTENNARANGEINQUIRY_H_ */

3. derived class cpp
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
/*
 * AntennaRangeInquiry.cpp
 *
 *  Created on: Apr 26, 2016
 *      Author: Technoboundary
 */
#include "AntennaRangeInquiry.h"

AntennaRangeInquiry::AntennaRangeInquiry() {
    // TODO Auto-generated constructor stub
}

AntennaRangeInquiry::~AntennaRangeInquiry() {
    // TODO Auto-generated destructor stub
}

void AntennaRangeInquiry::handleReq(ICD_ControlRequest* pMsg, eIntfcId intfcId_)
{
    //reInitialize();

    //bind(pMsg);

    //status = checkAndParseMsgBody();
}

uint32_t AntennaRangeInquiry::getMessageTag()
{
    return T_ControlResponseBody_antennaRangeInquiry;
}

AntennaRangeInquiryResponse* AntennaRangeInquiry::fillResponseBody()
{
    // First allocate memory for Inquiry and initialize it
    AntennaRangeInquiryResponse* pResp = rtxMemAllocType(pWCtxt, AntennaRangeInquiryResponse); //Lang: this is globally available.  do not know who will free yet.
    InitIncExtElem1(AntennaRangeInquiryResponse, pResp);

    return pResp;
}

void AntennaRangeInquiry::fillAntennaRange()
{

}