How to define a well made message class in C++ - c++

At the moment I am working on a message class in C++ for data communication, e.g. over a serial port. For this question let's say I have two different messages (I do have more), e.g. a gyroscope- and a acceleration message both with calibration data and sensor values. Since I am an engineer who learned C++ for himself I had a look at my favorite C++ book and figured out that it might be useful to use a factory pattern for the message.
So a simplified version of my header file looks like this:
#ifndef MESSAGE_H
#define MESSAGE_H
#include <cstddef>
class message
{
public:
/**
* \brief ~message:
* Virtual destructor of the class message.
*/
virtual ~message();
/**
* \brief getMessage:
* Creates a message (with new).
*
* \param[in] size Size of the dataArray.
* \param[in] data Bytearray of the message.
*
* \return If messagetype in the Array data eqal to 0 => new GyroMessage.
* If messagetype in the Array data eqal to 1 => new AccelMessage.
* Else => new NotValidMessage.
*
*/
static message* getMessage(size_t size, char* data);
protected:
/**
* \brief message:
* Default konstructor of the class message.
*
* \param[in] size Size of the dataArray.
* \param[in] data Bytearray of the message.
*
*/
message(size_t size, char* data);
/// Size of the dataArray.
int size;
/// Bytearray of the message.
char* dataArray;
/// Type of message.
char messagetype;
};
#endif // MESSAGE_H
The clases GyroMessage, AccelMessage and NotValidMessage are child classes of message. There are two things I do not like about this pattern:
First: If I want to add a new message, it is now enough to add a new class which is inherited form message, you have to add another if statement is in the static function getMessage.
Second: If I want to use the data e.g. from the GyroMessage, I have to reinterpret_cast the message.
Is there a better pattern that I could use for this purpose?

I'm not sure my ideas are good but it costs nothing sharing.
I've done something similar few days ago for Arduino, and for my case I made this choices:
for me the data payload is a pod (plain old data) struct where the compiler is informed to pack it. To achieve so I used a define that handles the compiler directive to pack it (for g++ is __attribute__((packed)))
the class in my case handles almost everything, thus I written it with a template. The template is for the payload struct
for sending the message in byte array I used a templated union inside the class. You have to check the byte ordering of the sender and receiver if you use this method. Something like that:
template <class P>
union Packet {
P data;
unsigned char buff[sizeof(P)];
}
My toolchain supports template so I used them. But you can use more template to insert more packages inside the same union. You need only to remember to have a common field in all the struct that identifies the kind of package (see below).
my class does not handles reading and writing, but instead requires the user of the class to provide 2 callbacks for reading and writing that accepts as arguments the buffer itself, the dimension of the buffer and a void pointer for user data. I think this is a good way to make the class agnostic with respect to the transmission channel.
The example (I'm simplifying a lot):
template <class A, class B, std::size_t N>
union Packet {
A a;
B b;
unsigned char buffer[N];
};
#define PAYLOAD(X, Y) struct X \
Y __attribute__((packed)); \
typedef struct X X;
template <class A, class B, std::size_t N>
class Message {
union Packet<A, B, N> packet;
// [...]
}
// [...]
// Time to declare you messages
PAYLOAD(GyroMessage, { char type; float x; float y; })
PAYLOAD(AccelMessage, { char type; float x; float y; float z; })
// GyroMessage will always have type = 0x01 and
// AccelMessage will always have type = 0x02 for example
// you know that sizeof(AccelMessage) > sizeof(GyroMessage)
// there is for sure a way to automatize this thing at
// compilation time through macros.
// Time to declare the class
Message<GyroMessage, AccelMessage, sizeof(AccelMessage)> message;
To retrieve the correct value you can still (through the union) access the value that you want, without adding new particular functions. But at the moment I don't have a very nice way to access them programmatically.
Those are only some hints, I really don't know what you are doing or which are your priority. So take them with caution.

A factory function is an excellent solution when you want to work generically, with knowledge of which type to create either inferred or known only at the point of creation.
If you know what type you want to create, and you are planning to use the created class with a pointer to the specific, derived type (using its specific interface) then you do not need a factory function. Create what you need and use it! In that case, you need a base class only for common functionality and/or for passing to specific functions which work on all derived types generically.
Alternatively, if you do want to work generically, then you can use a factory function and not cast the result. Work with a pointer to the base class. Have a common interface and handle the differences internally. If you can not do this, then your scenario is not a candidate for this approach.

Related

Optimizing storage space for classes in C++ in an Arduino library

I'm writing an Arduino library to wrap the pin functions (digitalRead, digitalWrite, analogRead, etc.). For example, I have a RegularPin class which is a passthrough and an InvertedPin class which inverts the pin logic. This is useful when going from the breadbord with LEDs to a relay board which inverts the circuit logic. I just have to swap classes.
I also have a DebouncedPin class for buttons which checks the user presses or releases long enough for the button to be really pressed/released.
Example for analog pins:
// AnalogInPin ------------------------------
class AnalogInPin
{
public:
virtual int read()=0;
virtual int getNo()=0;
};
// AnalogRegInPin ---------------------------
template<int pinNo>
class AnalogRegInPin : public AnalogInPin
{
public:
AnalogRegInPin();
int read();
int getNo(){return pinNo;}
};
template<int pinNo>
int AnalogRegInPin<pinNo>::read()
{
return analogRead(pinNo);
}
template<int pinNo>
AnalogRegInPin<pinNo>::AnalogRegInPin()
{
pinMode(pinNo, INPUT);
}
As you can see, I put the pin number in the template declaration because it is not to be changed at run time and I do not want the pin number to use memory when I allocate a pin object, just like in vanilla arduino C code. I know classes can not be of size zero but read on. Next, I want to write an "AveragedPin" class which will automatically read the selected pin several times and I would like to stack my templated classes like this :
AveragedPin<cAnalogRegInPin<A0>, UPDATE_ON_READ|RESET_ON_READ> ava0;
or even :
RangeCorrectedPin<AveragedPin<cAnalogRegInPin<A0>,
UPDATE_ON_READ|RESET_ON_READ,RAW_MIN,RAW_MAX,TARGET_RANGE> rcava0;
For the time being, I declared the nested pin as a private member because it is not allowed to use a class object in the template declaration. But then, each layer of nesting uselessly eats several bytes on the stack.
I know I could use references in the template declaration, but I don't quite understand how that works/should be used. My problem looks like empty member optimization, but it doesn't seem to apply here.
I feel this is more a C++ question than an arduino one and I'm not a C++ expert. I guess this touches the more advanced parts of C++. Maybe what I want is not possible, or only with recent C++ (20?) revisions.
Below is the code for the FixedRangeCorrectedPin class.
template <class P, int rawMin, int rawMax, int targetRange>
class FixedRangeCorrectedPin : public AnalogInPin
{
public:
int read();
int getNo(){return pin.getNo();}
private:
P pin;
};
template <class P, int rawMin, int rawMax, int targetRange>
int FixedRangeCorrectedPin<P, rawMin, rawMax, targetRange>::read()
{
int rawRange = rawMax - rawMin;
long int result = pin.read() - rawMin;
if (result < 0) result = 0;
result = result * targetRange / rawRange;
if (result > targetRange) result = targetRange;
return result;
}
My problem is that I would like to remove the 'P pin' class member and replace it in the template declaration like in template <AnalogInPin pin,int rawMin,int rawMax,int targetRange> because which pin is involved here is completely known at compile time.
As you can see, I put the pin number in the template declaration because it is not to be changed at run time and I do not want the pin number to use memory when I allocate a pin object, just like in vanilla arduino C code.
OK, if the pin number is a compile-time constant as it usually is for Arduino, this bit is fine.
However, making the AnalogInPin base class abstract (ie, adding virtual methods) will in practice use at least as much space per object as you saved by not storing the pin as an integer.
The details are implementation-specific, but runtime polymorphism requires some way of figuring out, for a given derived-class object pointed to by an AnalogInPin*, which version of the virtual methods to call, and that requires storage in each object of derived type. (You can verify that this is true buy just checking sizeof(AnalogInPin) and comparing to sizeof an otherwise identical class with no virtual methods.
I know classes can not be of size zero but ...
There's an special case for base classes with no data members that allows them to take no extra size (an instance of the most-derived type must still occupy at least one byte). It's called the empty base class optimization.
For the time being, I declared the nested pin as a private member because it is not allowed to use a class object in the template declaration. But then, each layer of nesting uselessly eats several bytes on the stack.
We can flatten the whole thing (and ideally remove the abstract base too, unless you have non-templated code that needs it):
template <int PIN, template <int> class BASE>
struct AveragedPin: public BASE<PIN>
{
int read() override { /* call BASE<PIN>::read() several times */ }
int getNo() override { return PIN; }
};
However, note that we could just use the inherited getNo, and then don't really use PIN at all. So instead of declaring an averaged pin instance as AveragedPin<MY_PIN, AnalogInPin> myAveragedPin;, we could change the definition to
template <class BASE>
struct AveragedPin: public BASE
{
int read() override { /* call BASE::read() several times */ }
using BASE::getNo; // not really required unless it is hidden
};
and declare an instance as AveragedPin<AnalogInPin<MY_PIN>> myAveragedPin;.
The range-corrected pin can be similar but with extra template parameters for the flags and min/max bounds, if they're known at compile time.
Similarly, the FixedRangeCorrectPin added to your question, doesn't need to derive from AnalogInPin and then also store a different pin type. In fact, it can just inherit the base class
template <class P,int rawMin,int rawMax,int targetRange>
struct FixedRangeCorrectedPin : public P
{
int read(); // calls P::read()
// inherit getNo again
};
again, declaring an instance like FixedRangeCorrectPin<AnalogInPin<MY_PIN>, RMIN, RMAX, TARGET> myFixedPin;
Edit Example of an average over a variable number of pins, with no storage overhead, assuming we changed the virtual methods to static:
template <class... PINS>
struct AveragedPins
{
static int read()
{
return (PINS::read() + ...) / sizeof...(PINS);
}
};
This doesn't care what sort of pin the argument is, so long as it has a static read method. You can stack it however you like:
using a1 = FixedRangeCorrectedPin<A_1, 0, 255, 128>;
using a2 = AnalogInPin<A_2>;
using a3 = AnalogInPin<A_3>;
using a4 = AnalogInPin<A_4>;
using a34 = AveragedPins<a3, a4>;
using all = AveragedPins<a1, a2, a34>;
// now a34::read() = (a3::read() + a4::read())/2
// and all::read() = (a1::read() + a2::read() + a34::read())/3
and note that all of those are just type definitions: we're not allocating even one byte for any objects.
One more note: I noticed that I'm using the same CLASS::method() syntax in two slightly different ways.
in the first examples above, which use inheritance, BASE::read() is a de-virtualized instance method call.
That is, we're calling BASE's version of the read method on this object. You could also write this->BASE::read().
It's de-virtualized because although the base-class method is virtual, we know at compile time the right override to call, so virtual dispatch isn't necessary.
in the final examples, where we stopped using inheritance and made the methods static, PIN::read() has no this and there is no object at all.
This is the most similar in principle to calling a free C function, although we're getting the compiler to generate a new instance of it for each different PIN value (and then expecting it to inline the call anyway).

Calling different template function specialisations based on a run-time value

This is related to a previous question in that it's part of the same system, but it's a different problem.
I'm working on an in-house messaging system, which is designed to send messages (structs) to consumers.
When a project wants to use the messaging system, it will define a set of messages (enum class), the data types (struct), and the relationship between these entities:
template <MessageType E> struct expected_type;
template <> struct expected_type<MessageType::TypeA> { using type = Foo; };
template <> struct expected_type<MessageType::TypeB> { using type = Bar; };
template <> struct expected_type<MessageType::TypeM> { using type = Foo; };
Note that different types of message may use the same data type.
The code for sending these messages is discussed in my previous question. There's a single templated method that can send any message, and maintains type safety using the template definitions above. It works quite nicely.
My question regards the message receiver class. There is a base class, which implements methods like these:
ReceiveMessageTypeA(const Foo & data) { /* Some default action */ };
ReceiveMessageTypeB(const Bar & data) { /* Some default action */ };
ReceiveMessageTypeM(const Foo & data) { /* Some default action */ };
It then implements a single message processing function, like this:
bool ProcessMessage(MessageType msgType, void * data) {
switch (msgType) {
case TypeA:
ReceiveMessageTypeA(data);
break;
case TypeB:
ReceiveMessageTypeB(data);
break;
// Repeat for all supported message types
default:
// error handling
break;
}
}
When a message receiver is required, this base class is extended, and the desired ReceiveMessageTypeX methods are implemented. If that particular receiver doesn't care about a message type, the corresponding function is left unimplemented, and the default from the base class is used instead.
Side note: ignore the fact that I'm passing a void * rather than the specific type. There's some more code in between to handle all that, but it's not a relevant detail.
The problem with the approach is the addition of a new message type. As well as having to define the enum, struct, and expected_type<> specialisation, the base class has to be modified to add a new ReceiveMessageTypeX default method, and the switch statement in the ProcessMessage function must be updated.
I'd like to avoid manually modifying the base class. Specifically, I'd like to use the information stored in expected_type to do the heavy lifting, and to avoid repetition.
Here's my attempted solution:
In the base class, define a method:
template <MessageType msgType>
bool Receive(expected_type<msgType>::type data) {
// Default implementation. Print "Message not supported", or something
}
Then, the subclasses can just implement the specialisations they care about:
template<> Receive<MessageType::TypeA>(const Foo & data) { /* Some processing */ }
// Don't care about TypeB
template<> Receive<MessageType::TypeM>(const Foo & data) { /* Some processing */ }
I think that solves part of the problem; I don't need to define new methods in the base class.
But I can't figure out how to get rid of the switch statement. I'd like to be able to do this:
bool ProcessMessage(MessageType msgType, void * data) {
Receive<msgType>(data);
}
This won't do, of course, because templates don't work like that.
Things I've thought of:
Generating the switch statement from the expected_type structure. I have no idea how to do this.
Maintaining some sort of map of function pointers, and calling the desired one. The problem is that I don't know how to initialise the map without repeating the data from expected_type, which I don't want to do.
Defining expected_type using a macro, and then playing preprocessor games to massage that data into a switch statement as well. This may be viable, but I try to avoid macros if possible.
So, in summary, I'd like to be able to call a different template specialisation based on a run-time value. This seems like a contradiction to me, but I'm hoping someone can point me in a useful direction. Even if that is informing me that this is not a good idea.
I can change expected_type if needed, as long as it doesn't break my Send method (see my other question).
You had right idea with expected_type and Receive templates; there's just one step left to get it all working.
First, we need to give us some means to enumerate over MessageType:
enum class MessageType {
_FIRST = 0,
TypeA = _FIRST,
TypeB,
TypeM = 100,
_LAST
};
And then we can enumerate over MessageType at compile time and generate dispatch functions (using SFINAE to skip values not defined in expected_types):
// this overload works when expected_types has a specialization for this value of E
template<MessageType E> void processMessageHelper(MessageType msgType, void * data, typename expected_type<E>::type*) {
if (msgType == E) Receive<E>(*(expected_type<E>::type*)data);
else processMessageHelper<(MessageType)((int)E + 1)>(msgType, data, nullptr);
}
template<MessageType E> void processMessageHelper(MessageType msgType, void * data, bool) {
processMessageHelper<(MessageType)((int)E + 1)>(msgType, data, nullptr);
}
template<> void processMessageHelper<MessageType::_LAST>(MessageType msgType, void * data, bool) {
std::cout << "Unexpected message type\n";
}
void ProcessMessage(MessageType msgType, void * data) {
processMessageHelper<MessageType::_FIRST>(msgType, data, nullptr);
}
Your title says: "Calling different template function specialisations based on a run-time value"
That can only be done with some sort of manual switch statement, or with virtual functions.
On the one hand, it looks on the surface like you are doing object-oriented programming, but you don't yet have any virtual methods. If you find you are writing pseudo-objects everywhere, but you don't have any virtual functions, then it means you are not doing OOP. This is not a bad thing though. If you overuse OOP, then you might fail to appreciate the particular cases where it is useful and therefore it will just cause more confusion.
Simplify your code, and don't get distracted by OOP
You want the message type object to have some 'magic' associated with it, where it's MessageType controls how it is dispatched. This means you need a virtual function.
struct message {
virtual void Receive() = 0;
}
struct message_type_A : public message {
virtual void Receive() {
....
}
}
This allows you, where appropriate, to pass these objects as message&, and to call msg.process_me()

Best practices to implement a Payload-containing class in C++?

I have a question about hierarchy, references and pointers... The question comes to my mind when I had tried to do the following stuff:
class packet {
public:
int address;
int command; /**< Command select the type of Payload that I must decode */
Payload p; /**< Generic payload, first question:
Payload p or Payload * p or Payload &p ?
I have a background in C, for this reason I prefer
Payload p but I know that this is not recommended for C++ */
private:
/** All getter and setter for attributes */
/** Second question: What is the best way to implement a getter
and setter for Payload?... I prefer something
similar to Java if this is possible */
}
Now imagine that I have a lot of types of Payload, all these payloads are children of the super class (generic) Payload.
I want to read the header and switch o the command. For example, if command is 1 I create a PayloadReset : Payload and fill in all of its attributes, then I want to set on my packet this payload (up-casting). In other part of the program I want to read my current packet and then read the command field and down-cast to the appropriate type depending on the command field.
When I tried to do this, I could do the up-casting without problems but the problem comes when I tried to do the downcasting to the specific Payload, in our example PayloadReset.
To answer the first question (which was buried inside the comments in your first code example:
Payload *p;
The first thing you need to learn as part of your transition from Java to C++ is what pointers are and how they work. What will be confusing to you, for some time, is the fact that all objects in Java are really pointers. You never needed to know that, when working with Java. But you must know that now, in order to understand C++. So, declaring a C++ class as
Payload p;
Is not the same thing as making a similar declaration in Java. There is no equivalent to this declaration in Java. In Java you really have a pointer here, and you have to instantiate it using the new keyword. That part Java originally aped from C++. This is the same process as C++, except that you have to explicitly declare it as a pointer.
Payload *p;
Then, somewhere else, using your example of a PayloadReset subclass:
class PayloadReset : public Payload { /* Class declaration */ };
PayloadReset *r = new PayloadReset( /* Constructor argument */ };
p=r;
And the second thing you need to learn as part of your transaction from Java to C++ is when, and how, to delete all instantiated objects. You don't have Java's garbage collector here. This becomes your job, now.
Tagging onto Sam's answer.
Before you go any further, learn the difference between stack and heap allocation. In the example you posted, you're allocating your Payload p; object on the stack - implying that the size of the object is known at this point and said size will be allocated on the stack. If you wanted to assign an derived object to p, it wouldn't work, because said object will likely be of different size. This is why you instead declare a pointer to the object (8 bytes on 64-bit architecture, 4 bytes on 32 bit), and then when you know which type of derived object you want to allocate, you do it using the new operator, as such:
Payload *p;
p = new PayloadReset(...);
The above method would require manually managing memory, i.e. calling delete on the new allocated pointer. As of C++11, the recommendation is to use smart pointers from the <memory> header. These are essentially reference counted pointers that automatically call delete for you.
std::shared_ptr<Payload> p;
p = std::make_shared<PayloadReset>(...);
Your question is somewhat related to Java syntax, but mostly about Object Oriented Programming.
First of all, you should take a moment to get familiar with Java naming conventions. There are commonly used recommendations that you can find all over the web. Here is one example of Java Naming Conventions. I brought this up because single variable names is generally not a good idea and having descriptive variables names pays dividends as the program grows in size and especially if there are more than one person on a team. So, instead of Payload p use Payload payload.
Secondly, in OO (Object Oriented), it is best to always keep your Class instance variables private, not public. Give access to these variables only if necessary and shield access to them by providing public methods. So, in your example of class Packet, your public/private is backwards. Your class should look more like:
public class Packet{
//private fields
private int address;
private int command;
private Payload payload;
//Maybe provide a nice constructor to take in expected
//properties on instantiation
public Packet(Payload pay){
}
//public methods - as needed
public void getPayload(){
return this.payload;
}
public void setAddress(int addy){
this.address = addy;
}
public int getCommand(){
return this.command;
}
}
Also, to answer more of your question about the naming of Payload. Like i said earlier..use descriptive names. Java does not have pointer references like C and generally handles memory management for you, so the & is not required or supported.
Your last question/topic is really again about OO and Class heirarchy.
It seems that Payload would be a generic base class and you may have multiple, specific 'Payload types', like ResetPayload. If that is the case, you would then define Payload and create the ResetPayload class that extends Payload. I'm not sure exactly what you are trying to do, but think of Classes/objects ad nouns and methods as verbs. Also think about the 'is-a' and 'has-a' concept. From what I see, maybe all Payloads 'has-acommand and an address. Also, maybe eachPayloadalso has multiplePackets, whatever. Just as an example, you would then define yourPayload` class like this:
public class Payload{
private int address;
private int command;
private List<Packet> packets = new ArrayList<>();
public Payload(int addy, int comm){
this.address = addy;
this.command = comm;
}
public void addPacket(Packet p){
packets.add(p);
}
public List<Packet> getPackets(){
return this.packets;
}
public int getCommand(){
return this.command;
}
public int getAddress(){
return this.address;
}
}
Then if you had a type of Payload that is more specific, like Reset, you would create the class, extends Payload and provide the additional properties/operations specific to this type, something this like:
public class ResetPayload extends Payload{
public ResetPayload(int addy, int comm){
super(addy, comm);
}
public void reset(){
//Do stuff here to reset the payload
}
}
Hopefully, that answers your questions and moves you along further. Good luck.
Here is my take on the general problem, it extends the tagged union idea. Advantages are 1.) no inheritance/dynamic_cast 2.) no shared ptr 3.) POD 4.) rtti is used to generate unique tags:
using cleanup_fun_t = void(*)(msg*);
class msg
{
public:
template<typename T, typename... Args>
static msg make(Args&&... args);
private:
std::type_index tag_;
mutable std::atomic<cleanup_fun_t> del_fn_; // hell is waiting for me,
uint64_t meta_;
uint64_t data_;
};
Please fill in all the nice member functions. This class is move only. You are creating messages with payload by the static member function make:
template<typename T, typename... Args>
msg msg::make(Args&&... args)
{
msg m;
m.tag_ = typeid(T);
m.del_fn_ = nullptr;
if (!(std::is_empty<T>::value))
{
auto ptr = std::make_unique<T>(std::forward<Args>(args)...);
m.data_ = (uint64_t)ptr.release();
m.del_fn_ = &details::cleanup_t<T>::fun; // deleter template not shown
}
return m;
}
// creation:
msg m = msg::make<Payload>(params passed to payload constructor);
// using
if (m.tag() == typeid(Payload))
{
Payload* ptr = (Payload*)m.data;
ptr-> ...
}
Just check the tag if it contains your expected data (type) and cast the data to a pointer type.
Disclaimer: It is not the complete class. Some access member function are missing here.

Organizing static data in C++

I'm working on some embedded software where there is some static information about "products". Since the information for a certain product never changes during execution I would like to initialize these data structures at compile time to save some space on the stack/heap.
I made a Product class for the data, intending to make a huge array of all the products in the system and then do lookups in this structure, but I haven't figured out quite how to get it working. The arrays are giving me loads of trouble. Some psuedo code:
class Product {
int m_price;
int m_availability[]; // invalid, need to set a size
... etc
// Constructor grabbing values for all members
Product(int p, int a[], ...);
}
static const Product products[] =
{
Product(99, {52,30,63, 49}, ...), // invalid syntax
...
}
Is there a way to making something like this work? The only thing I can think of would be to organize by attribute and skip the whole Product object. I feel that would make the whole thing harder to understand and maintain though.
Does anyone have any suggestions on how I might best organize this kind of data?
Thank you.
An old school C style static array of structs sounds like a perfect match to your requirements. Initializes at compile time, zero runtime overhead, no use of stack or heap. It's not a co-incidence that C is still a major player in the embedded world.
So (one recipe - plenty of scope to change the details of this);
// in .h file
class Product {
public: // putting this first means the class is really a struct
int m_price;
int m_availability[4];
//.... (more)
};
extern const Product product_array[];
extern const int product_array_nbr;
// in .cpp file
const Product product_array[] =
{
{
23,
{56,1,2,4},
//....(more)
},
{
24,
{65,1,2,4},
//....(more)
},
//....(more)
};
const int product_array_nbr = sizeof(product_array)/sizeof(product_array[0]);
A couple of years ago when I was working in embedded we needed to explicitly control the memory allocation of our structures.
Imagine this type of struct :
.h file
template<class T,uint16 u16Entries>
class CMemoryStruct
{
public:
/**
*Default c'tor needed for every template
*/
CMemoryStruct(){};
/**
*Default d'tor
*/
~CMemoryStruct(){};
/**
*Array which hold u16Entries of T objects. It is defined by the two template parameters, T can be of any type
*/
static T aoMemBlock[u16Entries];
/**
*Starting address of the above specified array used for fast freeing of allocated memory
*/
static const void* pvStartAddress;
/**
*Ending address of the above specified array used for fast freeing of allocated memory
*/
static const void* pvEndAddress;
/**
*Size of one T object in bytes used for determining the array to which the necessary method will be invoked
*/
static const size_t sizeOfEntry;
/**
*Bitset of u16Entries which has the same size as the Array of the class and it is used to specify whether
*a particular entry of the templated array is occupied or not
*/
static std::bitset<u16Entries> oVacancy;
};
/**
*Define an array of Type[u16Entries]
*/
template<class Type,uint16 u16Entries> Type CMemoryStruct<Type,u16Entries>::aoMemBlock[u16Entries];
/**
*Define a const variable of a template class
*/
template<class Type,uint16 u16Entries> const void* CMemoryStruct<Type,u16Entries>::pvStartAddress=&CMemoryStruct<Type,u16Entries>::aoMemBlock[0];
template<class Type,uint16 u16Entries> const void* CMemoryStruct<Type,u16Entries>::pvEndAddress=&CMemoryStruct<Type,u16Entries>::aoMemBlock[u16Entries-1];
template<class Type,uint16 u16Entries> const size_t CMemoryStruct<Type,u16Entries>::sizeOfEntry=sizeof(Type);
/**
*Define a bitset inside a template class...
*/
template<class Type,uint16 u16Entries> std::bitset<u16Entries> CMemoryStruct<Type,u16Entries>::oVacancy;
Depending on your compiler and environment you could manipulate the area of where the static allocation take place. In our case we moved this to the ROM which was plenty. Also note that depending on your compiler i.e. Greenhills compilers, you may need to use the export keyword and define your static members to the .cpp file.
You can use the start and end pointers to navigate through the data. If your compiler supports full STL you may want to use std::vectors with custom allocators and overloaded new operators which would save your memory to somewhere else than the stack. In our case the new operators were overloaded in such a way that all the memory allocation was done on predefined memory structures.
Hope I gave you an idea.
In C++98/03, you cannot initialize arrays in a constructor initializer.
In C++11, this has been fixed with uniform initialization:
class Product
{
int m_availability[4];
public:
Product() : m_availability{52,30,63, 49} { }
};
If you need the data to be provided in the constructor, use a vector instead:
class Product
{
const std::vector<int> m_availability;
public:
Product(std::initializer_list<int> il) : m_availability(il) { }
};
Usage:
extern const Product p1({1,2,3});
Memory for the static variables is still reserved when the code is actually executing -- you won't be saving space on the stack. You might want to consider use of vectors instead of arrays -- they're easier to pass and process.

C++ design - Network packets and serialization

I have, for my game, a Packet class, which represents network packet and consists basically of an array of data, and some pure virtual functions
I would then like to have classes deriving from Packet, for example: StatePacket, PauseRequestPacket, etc. Each one of these sub-classes would implement the virtual functions, Handle(), which would be called by the networking engine when one of these packets is received so that it can do it's job, several get/set functions which would read and set fields in the array of data.
So I have two problems:
The (abstract) Packet class would need to be copyable and assignable, but without slicing, keeping all the fields of the derived class. It may even be possible that the derived class will have no extra fields, only function, which would work with the array on the base class. How can I achieve that?
When serializing, I would give each sub-class an unique numeric ID, and then write it to the stream before the sub-class' own serialization. But for unserialization, how would I map the read ID to the appropriate sub-class to instanciate it?
If anyone want's any clarifications, just ask.
-- Thank you
Edit: I'm not quite happy with it, but that's what I managed:
Packet.h: http://pastebin.com/f512e52f1
Packet.cpp: http://pastebin.com/f5d535d19
PacketFactory.h: http://pastebin.com/f29b7d637
PacketFactory.cpp: http://pastebin.com/f689edd9b
PacketAcknowledge.h: http://pastebin.com/f50f13d6f
PacketAcknowledge.cpp: http://pastebin.com/f62d34eef
If someone has the time to look at it and suggest any improvements, I'd be thankful.
Yes, I'm aware of the factory pattern, but how would I code it to construct each class? A giant switch statement? That would also duplicade the ID for each class (once in the factory and one in the serializator), which I'd like to avoid.
For copying you need to write a clone function, since a constructor cannot be virtual:
virtual Packet * clone() const = 0;
Which each Packet implementation implement like this:
virtual Packet * clone() const {
return new StatePacket(*this);
}
for example for StatePacket. Packet classes should be immutable. Once a packet is received, its data can either be copied out, or thrown away. So a assignment operator is not required. Make the assignment operator private and don't define it, which will effectively forbid assigning packages.
For de-serialization, you use the factory pattern: create a class which creates the right message type given the message id. For this, you can either use a switch statement over the known message IDs, or a map like this:
struct MessageFactory {
std::map<Packet::IdType, Packet (*)()> map;
MessageFactory() {
map[StatePacket::Id] = &StatePacket::createInstance;
// ... all other
}
Packet * createInstance(Packet::IdType id) {
return map[id]();
}
} globalMessageFactory;
Indeed, you should add check like whether the id is really known and such stuff. That's only the rough idea.
You need to look up the Factory Pattern.
The factory looks at the incomming data and created an object of the correct class for you.
To have a Factory class that does not know about all the types ahead of time you need to provide a singleton where each class registers itself. I always get the syntax for defining static members of a template class wrong, so do not just cut&paste this:
class Packet { ... };
typedef Packet* (*packet_creator)();
class Factory {
public:
bool add_type(int id, packet_creator) {
map_[id] = packet_creator; return true;
}
};
template<typename T>
class register_with_factory {
public:
static Packet * create() { return new T; }
static bool registered;
};
template<typename T>
bool register_with_factory<T>::registered = Factory::add_type(T::id(), create);
class MyPacket : private register_with_factory<MyPacket>, public Packet {
//... your stuff here...
static int id() { return /* some number that you decide */; }
};
Why do we, myself included, always make such simple problems so complicated?
Perhaps I'm off base here. But I have to wonder: Is this really the best design for your needs?
By and large, function-only inheritance can be better achieved through function/method pointers, or aggregation/delegation and the passing around of data objects, than through polymorphism.
Polymorphism is a very powerful and useful tool. But it's only one of many tools available to us.
It looks like each subclass of Packet will need its own Marshalling and Unmarshalling code. Perhaps inheriting Packet's Marshalling/Unmarshalling code? Perhaps extending it? All on top of handle() and whatever else is required.
That's a lot of code.
While substantially more kludgey, it might be shorter & faster to implement Packet's data as a struct/union attribute of the Packet class.
Marshalling and Unmarshalling would then be centralized.
Depending on your architecture, it could be as simple as write(&data). Assuming there are no big/little-endian issues between your client/server systems, and no padding issues. (E.g. sizeof(data) is the same on both systems.)
Write(&data)/read(&data) is a bug-prone technique. But it's often a very fast way to write the first draft. Later on, when time permits, you can replace it with individual per-attribute type-based Marshalling/Unmarshalling code.
Also: I've taken to storing data that's being sent/received as a struct. You can bitwise copy a struct with operator=(), which at times has been VERY helpful! Though perhaps not so much in this case.
Ultimately, you are going to have a switch statement somewhere on that subclass-id type. The factory technique (which is quite powerful and useful in its own right) does this switch for you, looking up the necessary clone() or copy() method/object.
OR you could do it yourself in Packet. You could just use something as simple as:
( getHandlerPointer( id ) ) ( this )
Another advantage to an approach this kludgey (function pointers), aside from the rapid development time, is that you don't need to constantly allocate and delete a new object for each packet. You can re-use a single packet object over and over again. Or a vector of packets if you wanted to queue them. (Mind you, I'd clear the Packet object before invoking read() again! Just to be safe...)
Depending on your game's network traffic density, allocation/deallocation could get expensive. Then again, premature optimization is the root of all evil. And you could always just roll your own new/delete operators. (Yet more coding overhead...)
What you lose (with function pointers) is the clean segregation of each packet type. Specifically the ability to add new packet types without altering pre-existing code/files.
Example code:
class Packet
{
public:
enum PACKET_TYPES
{
STATE_PACKET = 0,
PAUSE_REQUEST_PACKET,
MAXIMUM_PACKET_TYPES,
FIRST_PACKET_TYPE = STATE_PACKET
};
typedef bool ( * HandlerType ) ( const Packet & );
protected:
/* Note: Initialize handlers to NULL when declared! */
static HandlerType handlers [ MAXIMUM_PACKET_TYPES ];
static HandlerType getHandler( int thePacketType )
{ // My own assert macro...
UASSERT( thePacketType, >=, FIRST_PACKET_TYPE );
UASSERT( thePacketType, <, MAXIMUM_PACKET_TYPES );
UASSERT( handlers [ thePacketType ], !=, HandlerType(NULL) );
return handlers [ thePacketType ];
}
protected:
struct Data
{
// Common data to all packets.
int number;
int type;
union
{
struct
{
int foo;
} statePacket;
struct
{
int bar;
} pauseRequestPacket;
} u;
} data;
public:
//...
bool readFromSocket() { /*read(&data); */ } // Unmarshal
bool writeToSocket() { /*write(&data);*/ } // Marshal
bool handle() { return ( getHandler( data.type ) ) ( * this ); }
}; /* class Packet */
PS: You might dig around with google and grab down cdecl/c++decl. They are very useful programs. Especially when playing around with function pointers.
E.g.:
c++decl> declare foo as function(int) returning pointer to function returning void
void (*foo(int ))()
c++decl> explain void (* getHandler( int ))( const int & );
declare getHandler as function (int) returning pointer to function (reference to const int) returning void