Re: Generic message holder class design
On Jan 6, 12:11 pm, Mark <ma740...@gmail.com> wrote:
I'm receving incoming messages R1,R2,R3..Rn from an aircraft. I
respond with T1,T2,T3..Tn. So now consider the source snippet.
# include <iostream>
# include <string>
# include <vector>
# include <memory>
class non_copyable {
protected:
non_copyable() {}
~non_copyable() {}
private:
non_copyable(const non_copyable &);
non_copyable & operator=(const non_copyable &);
};
/*
==============================================================================
| singleton class: Used to enforce an single instance
==============================================================================
*/
template <class T>
class singleton : non_copyable
{
public:
static T& instance() {
if (!_object.get()) //Not yet created
_object = std::auto_ptr<T>(new T);
return * ( _object.get() );
}
static T* get_singleton_ptr() { return &( instance() ); }
static void destroy() { _object.reset() ; }
protected:
singleton() {}
virtual ~singleton() {}
static std::auto_ptr<T> _object; //auto_ptr ensures T is deleted at
end
};
template <class T>
std::auto_ptr<T> singleton<T>::_object; //Initilize static variable
/*
==============================================================================
| Incoming messages: R1,R2,R3 ....Rn
| Outgoing messages: T1,T2,T3 ....Tn
==============================================================================
*/
//Base class for messages
class Base {
public:
// handful of methods.
virtual ~Base() {}};
//R1
class R1_Msg : public Base {
public :
explicit R1_Msg( /*arg*/ ) {}
double Get_Latitude() const { std::cout << "R1" << '\n'; return
(1.); }
// more Sets/Gets};
//R2
class R2_Msg : public Base {
public :
explicit R2_Msg( /*arg*/ ) {}
unsigned short Get_Ad_Confirmation() const { std::cout << "R2" <<
'\n'; return ( 5 ) ; }
// more Sets/Gets
};
template < typename Type >
class Msg_Holder : public non_copyable {
//class Msg_Holder {
//useful statistic
int msg_count ;
//msg count
int msg_id ;
Type msg_instance ;
//singleton < Type > msg_instance ;
public:
//std::string would be 'better' for an id, nonethless for now
Msg_Holder ( int const id, Type& in )
: msg_id ( id )
, msg_instance ( in )
{}
int Get_Msg_ID() const { return ( msg_id ) ; }
int Get_Msg_Count() const { return ( msg_count ) ; }
void Increment_Msg_Count() { msg_count ++ ; }
/*
| This gets tricky.....we want the derived type, hence:
| a) downcasting
| b) dynamic_cast possibly
| Do I care though since the 'message classes' are wrapped
| in a singleton?
*/
Type Get_Type () const { return ( msg_instance ) ; }
//destruct
~Msg_Holder () {}
};
int main()
{
typedef std::vector < Msg_Holder* > MSG_HOLDER_VEC ;
MSG_HOLDER_VEC msg_vec;
msg_vec.push_back ( new Msg_Holder < R1_Msg > (
( 1, singleton < R1_Msg >::instance() ) ) ) ;
std::cin.get();
}
I'd like store an instance of each message within a container of
Msg_Hholder type. My issues here is predicated upon template usage/
understanding (something i struggle with often), noetheless at issue:
a) The Msg_Holder class is a generic class and I'm unsure how to
typedef the vector so I could push-back message classes
b) How do I enforce the use of the singleton in the Msg_Holder
constructor? IOW: push_back of Msg_Holder instances must be routed
through the singleton class.
c) I suspect there's no way to 'chain' push back? Ideally I'd like to
do .
msg_vec.push_back ( id1, single_instance::r1_msg ).
push_back ( id2, single_instance::r2_msg ) // etc.;
lots more
// later iterate and find the id i'm interested in)
R1_Msg obj ;
for ( MSG_HOLDER_VEC::const_iterator it = msg_vec.begin(), it !=
msg_ve.end(); ++it ) {
if ( .. ... ) {
obj = it -> ....
//increment the count
int ->
}
}
Of course this might seem painful but I dont think a map helps me
here.
I'm open to ideas (source snippet works even better). Thanks in
advance.
Mark
I'm not sure if it is a good idea to make the messages classes.
At least that isn't how I do it. I associate message ids with
functions and use something called Middle code to handle the
description of messages. For example, this Middle code:
msgs
(list<int32_t>) @msg_id_a1
}
results in this output:
// Generated by the C++ Middleware Writer version 1.10
#include <list>
#include <MarshallingFunctions.hh>
#include <ReceiveCompressedBuffer.hh>
#include <SendCompressedBuffer.hh>
uint16_t const msg_id_a1 = 1201;
uint16_t const msg_id_max = 1202;
extern uint32_t msg_length_max;
struct msgs
{
void
Send(SendCompressedBuffer* buf, const list<int32_t>& abt1)
{
unsigned int headCount = 0;
buf->Receive(&msg_id_a1, sizeof(msg_id_a1)); // sending message
id here
Counter cntr(msg_length_max);
cntr.Add(sizeof(int));
cntr.MultiplyAndAdd(abt1.size(), sizeof(int32_t));
buf->Receive(&cntr.value_, sizeof(cntr.value_));
headCount = abt1.size();
buf->Receive(&headCount, sizeof(headCount));
list<int32_t >::const_iterator mediator2 = abt1.begin();
list<int32_t >::const_iterator omega2 = abt1.end();
for (; mediator2 != omega2; ++mediator2) {
buf->Receive(&(*mediator2), sizeof(int32_t));
}
buf->SendStoredData();
}
template <typename B>
void
Receive(B* buf, list<int32_t>& abt1)
{
unsigned int headCount[1];
buf->Give(headCount[0]);
while (headCount[0] > 0) {
--headCount[0];
int32_t rep3;
buf->Give(rep3);
abt1.push_back(rep3);
}
}
};
Notice how the Send function includes code to send the message ID,
but the Receive function doesn't have any related code. The data
sent by the Send function will probably be handled by two Receive
functions. The first Receive function (not shown) to execute will
get a message id, which can then be used to dispatch to the Receive
function above. These programs
http://webEbenezer.net/misc/sendsample.cc
http://webEbenezer.net/misc/receivesample.cc
show an example of that.
Brian Wood
http://webEbenezer.net
(651) 251-9384
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]