F
forums_mp
After reading a few texts - nameley koeing/moo and eckel - I decided
to investigating the importance of templates. Of course there's no
substitute for practice so I figured I try a simple program.
That said I'm interested in suggestions for improvement on the
template class (be gracious i'm slowly coming up to speed in ++ )
but more importantly I have a few questions.
For starters, in an ideal world each call to Store should be followed
by a subsequent Retrieve. If however, Store was called twice before a
Retrieve then I'd like to implement some sort of overrun check. I
suspect this could be handled with an overrun_count that'll get
incremented in Store and decremented in Retrieve or (implementation
help here)???
Conceptually I understand teh copy constructor and/or assignment
operator (the heavy stuff but need to revisit) but I'm curious to see
an implementation of the assignment operator that'll compare two
buffers and a copy constructor that'll do just that. Copy an new
object based on exisitng.
The code
// template.h
enum BOOLEAN { FALSE = 0,
TRUE};
template <class T>
class BUFFER
{
public:
BUFFER();
~BUFFER();
void Store(unsigned char const* buffer);
BOOLEAN Retrieve(T& data);
// T Retrieve(T& data); would this be more prudent ??
int Elements_Stored() const;
int Elements_Retrieved() const;
private:
static const int SIZE = 2;
T msg [ SIZE ];
unsigned int store_count;
unsigned int store_index;
unsigned int retrieve_count;
// override compiler defaults
BUFFER(BUFFER<T>& buffer); // Copy construtor.
void operator= (BUFFER<T>& rhs); // Assignment operator
};
// Constructor
template<class T>
BUFFER<T>::BUFFER()
: store_count(0), retrieve_count(0), store_index(1)
{
memset( msg, 0, SIZE * sizeof(T));
}
// Destructor
template<class T>
BUFFER<T>::~BUFFER()
{
}
// store two items. the current and the previous
template<class T>
void BUFFER<T>::Store( unsigned char const* buffer)
{
store_index ^= 1;
// supposidely memcpy is bad news but std::copy benchmarked is slow
// when compared to memcpy
memcpy( &msg[store_index], buffer, sizeof(T));
store_count++; // increment the message stored count
}
// retrieve the most CURRENT item at ALL times
template<class T>
BOOLEAN BUFFER<T>::Retrieve(T& data)
{
if (store_count > 0) // here only to ensure the Retrieve never
// gets called the VERY FIRST TIME before the
Store
{
memcpy( &data, &msg[store_index], sizeof(T));
retrieve_count++;
return TRUE;
}
else
{
return FALSE;
}
}
// returns number of elements stored.
template<class T>
int BUFFER<T>::Elements_Stored() const
{
return store_count;
}
// returns number of elements retrieved.
template<class T>
int BUFFER<T>::Elements_Retrieved() const
{
return retrieve_count;
}
// template.cpp file
#define MAX_MSG_SIZE 4 // avoid preprocessor macro in a ++
environment
enum BOGUS_MSG { msg1Msg,
msg2Msg };
// For simplicity make bit fields 8 deep
struct MSG1
{
unsigned int jdx1 : 8;
unsigned int jdx2 : 8;
unsigned int jdx3 : 8;
unsigned int jdx4 : 8;
};
struct MSG2
{
unsigned int idx1 : 8;
unsigned int idx2 : 8;
unsigned int idx3 : 8;
unsigned int idx4 : 8;
};
int main ( void )
{
BOGUS_MSG msgType;
MSG1 localMsg;
BOOLEAN success;
// Done once at initilization.
BUFFER<MSG1> msg1;
BUFFER<MSG2> msg2;
unsigned char buffer [ MAX_MSG_SIZE ] = { 12, 1, 15, 5 };
memset(&localMsg, 0, sizeof(MSG1)); // no real reason since
// I'll overwrite
localMsg
std::cout << " ----- Before call to Store and Retrieve ---- "
<< std::endl;
std::cout << "MSG1 - jdx1 = " << localMsg.jdx1 << std::endl;
std::cout << "MSG1 - jdx2 = "<< localMsg.jdx2 << std::endl;
std::cout << "MSG1 - jdx3 = " << localMsg.jdx3 << std::endl;
std::cout << "MSG1 - jdx4 = " << localMsg.jdx4 << std::endl;
msgType = msg1Msg;
switch ( msgType )
{
case msg1Msg:
msg1.Store ( buffer );
break;
case msg2Msg:
msg2.Store ( buffer );
break;
default:
std::cout << " bad msg " << std::endl;
break;
}
// later lets Retrieve a message
success = msg1.Retrieve(localMsg); // retrieve the message
if ( success )
{
std::cout << " ----- After call to Store and Retrieve ---- "
<< std::endl;
std::cout << "MSG1 - jdx1 = " << localMsg.jdx1 << std::endl;
std::cout << "MSG1 - jdx2 = "<< localMsg.jdx2 << std::endl;
std::cout << "MSG1 - jdx3 = " << localMsg.jdx3 << std::endl;
std::cout << "MSG1 - jdx4 = " << localMsg.jdx4 << std::endl;
}
// Call msg1.Store message a couple times
// Call msg2.Store
msg1.Store ( buffer );
msg1.Store ( buffer );
msg2.Store ( buffer );
// Print out the index of how many times msg1(should equate to 3)
stored
// Print out the index of how many times msg1(should equate to 1)
stored
std::cout << " --------------------------------------------- "
<< std::endl;
std::cout << "Times called -- MSG1: "
<< msg1.Elements_Stored()
<< std::endl;
std::cout << " --------------------------------------------- "
<< std::endl;
std::cout << "Times called -- MSG2: "
<< msg2.Elements_Stored()
<< std::endl;
std::cout << " --------------------------------------------- "
<< std::endl;
return EXIT_SUCCESS;
}//// end
I'll modify said code to move into the container realm later.
Thanks in advance
to investigating the importance of templates. Of course there's no
substitute for practice so I figured I try a simple program.
That said I'm interested in suggestions for improvement on the
template class (be gracious i'm slowly coming up to speed in ++ )
but more importantly I have a few questions.
For starters, in an ideal world each call to Store should be followed
by a subsequent Retrieve. If however, Store was called twice before a
Retrieve then I'd like to implement some sort of overrun check. I
suspect this could be handled with an overrun_count that'll get
incremented in Store and decremented in Retrieve or (implementation
help here)???
Conceptually I understand teh copy constructor and/or assignment
operator (the heavy stuff but need to revisit) but I'm curious to see
an implementation of the assignment operator that'll compare two
buffers and a copy constructor that'll do just that. Copy an new
object based on exisitng.
The code
// template.h
enum BOOLEAN { FALSE = 0,
TRUE};
template <class T>
class BUFFER
{
public:
BUFFER();
~BUFFER();
void Store(unsigned char const* buffer);
BOOLEAN Retrieve(T& data);
// T Retrieve(T& data); would this be more prudent ??
int Elements_Stored() const;
int Elements_Retrieved() const;
private:
static const int SIZE = 2;
T msg [ SIZE ];
unsigned int store_count;
unsigned int store_index;
unsigned int retrieve_count;
// override compiler defaults
BUFFER(BUFFER<T>& buffer); // Copy construtor.
void operator= (BUFFER<T>& rhs); // Assignment operator
};
// Constructor
template<class T>
BUFFER<T>::BUFFER()
: store_count(0), retrieve_count(0), store_index(1)
{
memset( msg, 0, SIZE * sizeof(T));
}
// Destructor
template<class T>
BUFFER<T>::~BUFFER()
{
}
// store two items. the current and the previous
template<class T>
void BUFFER<T>::Store( unsigned char const* buffer)
{
store_index ^= 1;
// supposidely memcpy is bad news but std::copy benchmarked is slow
// when compared to memcpy
memcpy( &msg[store_index], buffer, sizeof(T));
store_count++; // increment the message stored count
}
// retrieve the most CURRENT item at ALL times
template<class T>
BOOLEAN BUFFER<T>::Retrieve(T& data)
{
if (store_count > 0) // here only to ensure the Retrieve never
// gets called the VERY FIRST TIME before the
Store
{
memcpy( &data, &msg[store_index], sizeof(T));
retrieve_count++;
return TRUE;
}
else
{
return FALSE;
}
}
// returns number of elements stored.
template<class T>
int BUFFER<T>::Elements_Stored() const
{
return store_count;
}
// returns number of elements retrieved.
template<class T>
int BUFFER<T>::Elements_Retrieved() const
{
return retrieve_count;
}
// template.cpp file
#define MAX_MSG_SIZE 4 // avoid preprocessor macro in a ++
environment
enum BOGUS_MSG { msg1Msg,
msg2Msg };
// For simplicity make bit fields 8 deep
struct MSG1
{
unsigned int jdx1 : 8;
unsigned int jdx2 : 8;
unsigned int jdx3 : 8;
unsigned int jdx4 : 8;
};
struct MSG2
{
unsigned int idx1 : 8;
unsigned int idx2 : 8;
unsigned int idx3 : 8;
unsigned int idx4 : 8;
};
int main ( void )
{
BOGUS_MSG msgType;
MSG1 localMsg;
BOOLEAN success;
// Done once at initilization.
BUFFER<MSG1> msg1;
BUFFER<MSG2> msg2;
unsigned char buffer [ MAX_MSG_SIZE ] = { 12, 1, 15, 5 };
memset(&localMsg, 0, sizeof(MSG1)); // no real reason since
// I'll overwrite
localMsg
std::cout << " ----- Before call to Store and Retrieve ---- "
<< std::endl;
std::cout << "MSG1 - jdx1 = " << localMsg.jdx1 << std::endl;
std::cout << "MSG1 - jdx2 = "<< localMsg.jdx2 << std::endl;
std::cout << "MSG1 - jdx3 = " << localMsg.jdx3 << std::endl;
std::cout << "MSG1 - jdx4 = " << localMsg.jdx4 << std::endl;
msgType = msg1Msg;
switch ( msgType )
{
case msg1Msg:
msg1.Store ( buffer );
break;
case msg2Msg:
msg2.Store ( buffer );
break;
default:
std::cout << " bad msg " << std::endl;
break;
}
// later lets Retrieve a message
success = msg1.Retrieve(localMsg); // retrieve the message
if ( success )
{
std::cout << " ----- After call to Store and Retrieve ---- "
<< std::endl;
std::cout << "MSG1 - jdx1 = " << localMsg.jdx1 << std::endl;
std::cout << "MSG1 - jdx2 = "<< localMsg.jdx2 << std::endl;
std::cout << "MSG1 - jdx3 = " << localMsg.jdx3 << std::endl;
std::cout << "MSG1 - jdx4 = " << localMsg.jdx4 << std::endl;
}
// Call msg1.Store message a couple times
// Call msg2.Store
msg1.Store ( buffer );
msg1.Store ( buffer );
msg2.Store ( buffer );
// Print out the index of how many times msg1(should equate to 3)
stored
// Print out the index of how many times msg1(should equate to 1)
stored
std::cout << " --------------------------------------------- "
<< std::endl;
std::cout << "Times called -- MSG1: "
<< msg1.Elements_Stored()
<< std::endl;
std::cout << " --------------------------------------------- "
<< std::endl;
std::cout << "Times called -- MSG2: "
<< msg2.Elements_Stored()
<< std::endl;
std::cout << " --------------------------------------------- "
<< std::endl;
return EXIT_SUCCESS;
}//// end
I'll modify said code to move into the container realm later.
Thanks in advance