• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 516
  • Last Modified:

generic message holder class

Reference source code below:  I'm receving incoming messages R1,R2,R3..Rn from a source.  I respond with T1,T2,T3..Tn.

I'd like store an instance of each message within a container of Msg_Holder type.   My issues:

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.

Let me be clear.  A solution that involves working source is what I'm after.
# 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(); 



}

Open in new window

0
forums_mp
Asked:
forums_mp
  • 13
  • 11
  • 10
  • +2
3 Solutions
 
js-profiCommented:
make the array

   std::vector<MSG_HOLDER*>;

and derive each specific message from MSG_HOLDER.

to force singleton you could make a static class member theMsgHolder and provide a private constructor only.
0
 
ZoppoCommented:
Hi,

about second question: IMO you should derive a class from 'std::vector < Msg_Holder* >'. Then you could implement a function to add a new 'Msg_Holder*'. This function then can call a member function of 'Msg_Holder'. It's even possible to name that function 'push_back' too, i.e. like this:

> class Msg_Holder_Vec : public std::vector< Msg_Holder* >
> {
> public:
>      void push_back( const Msg_Holder*& _Val )
>      {
>            std::vector< Msg_Holder*>::push_back( _Val );
>
>            // call a function against _Val here ...
>      }
> };

Hope that helps,

ZOPPO
0
 
Infinity08Commented:
Are you looking for something like this ?
#include <iostream>
#include <string>
#include <vector>
#include <sstream>


// Base class for messages
class Message {
	private :
		int _id;

	public :
		Message(int id) : _id(id) { }
		virtual ~Message() { }

		int getId() const { return _id; }

		virtual std::string getMessage() const = 0;
};

// R1
class MessageR1 : public Message {
	private :
		double _latitude;

	public :
		MessageR1(int id, double latitude) : Message(id), _latitude(latitude) { }
		~MessageR1() { }

		double getLatitude() const { return _latitude; }

		virtual std::string getMessage() const {
			std::stringstream ss;
			ss << "R1 : latitude = " << _latitude;
			return ss.str();
		}
};

// R2
class MessageR2 : public Message {
	private :
		unsigned short _adConfirmation;

	public :
		MessageR2(int id, unsigned short adConfirmation) : Message(id), _adConfirmation(adConfirmation) { }
		~MessageR2() { }

		unsigned short getAdConfirmation() const { return _adConfirmation; }

		virtual std::string getMessage() const {
			std::stringstream ss;
			ss << "R2 : adConfirmation = " << _adConfirmation;
			return ss.str();
		}
};

class MessageHolder {
	private :
		std::vector<const Message*> _messages;

	public :
		MessageHolder() { }
		~MessageHolder() { }

		size_t count() const { return _messages.size(); }
		const Message* getMessage(size_t i) const { return (i < _messages.size()) ? _messages[i] : NULL; }

		void addMessage(const Message* message) { _messages.push_back(message); }
		void removeMessage(size_t i) { if (i < _messages.size()) _messages.erase(_messages.begin() + i); }
};


int main() {
	MessageHolder holder;

	holder.addMessage(new MessageR1(1, 1.1));
	holder.addMessage(new MessageR1(2, 2.2));
	holder.addMessage(new MessageR2(11, 5));

	std::cout << "message count : " << holder.count() << std::endl;
	for (size_t i = 0; i < holder.count(); ++i) {
		const Message* message = holder.getMessage(i);
		std::cout << " -> message " << i << " : [" << message->getId() << "] " << message->getMessage() << std::endl;
	}

	// make sure to delete messages

	return 0;
}

Open in new window

0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
forums_mpAuthor Commented:
|| Are you looking for something like this ?
No!  Good concept however, no changes allowed to the Base and message classes (R1_Msg. etc.).  The code presented in my initial post is just representative of the real ones.
0
 
Infinity08Commented:
>> no changes allowed to the Base and message classes (R1_Msg. etc.).

Ok. So, just the Msg_Holder class.

In that case, I'm not very clear on what its purpose is. What it seems to do right now, is provide a separate Msg_Holder template specialization for each of the message types, and it acts as a wrapper around one message, adding an id and a count to it (what's that count for btw ?).
You then have a vector of these Msg_Holder instances which you do something with ...

But I don't see the use of this class ... ??

Is my above description what you were trying to do ? If not, could you explain what kind of functionality you want ?
0
 
forums_mpAuthor Commented:
|| What it seems to do right now, is provide a separate Msg_Holder template specialization
|| for each of the message types, and it acts as a wrapper around one message
|| adding an id and a count to it (what's that count for btw ?).
Your assessment is correct.  I'm dealing with bi-directional communication between an aircraft and 4 sources.   For discussion purposes I'll ignore writes/reads to/from source.

Each 25Hz frame i read aircraft data to determine the 'R type' or "R types' (there could be multiple messages in the unsigned char buffer).   Once I determine the which 'type' to update the type gets updated along with count parameter (the count is strictly for instrumentation).  Similar premise when I write data to the aircraft.

My initial thought is to have a conglomerate class to house all these messages, hence Msg_Holder. Msg_Holder commits me to one messages.
i.e typedef std::vector< Msg_Holder < R1_Msg >* > MSG_HOLDER;

I can't use boost hence I could address this by using boost::any (see source code concept below).  Implementing my version boost::any is - I think beyond my template skills at this point. :-)

The Msg_Holder class will serve as a parameter to the classes that process the messages.
Of course a vector of messages might be overkill .  A 'class' per message doesn't bode well because there's a handful of "R's' that are tightly coupled with Ts.  i.e. in the - say R1_Process class.  The Process method.
void Process () {
      if ( obj_R1.Get_Test_Msg () == Type_Info ) {
        obj_T1.Set_Test_Msg ( Type_Info ) ; // store it for transmittal.
                                                                   // NOTE here I'm echoing back just this R msg value in a T
        New_T1_Msg = true ;                        // set flag
      }

Hope I answered your question
class Holder {
  std::vector < boost::any > msg_vec ;
public:
  std::vector < boost::any >& add ( boost::any msg ) {
    msg_vec.push_back ( msg );
   return msg_vec ;
  }
};
int main() {
  Holder hold ;
  hold.add( boost::any ( new Holder < R1_Msg > ( singleton< R1_Msg >::instance() )))
        .add (  boost::any ( new Holder < R2_Msg > ( singleton< R2_Msg >::instance() ))) ;
}

Open in new window

0
 
Infinity08Commented:
>> Msg_Holder commits me to one messages.

And do you want that ? If not, why did you use templates ? Using polymorphism as in my earlier code would solve this issue easily.

But it seems you're stuck with the existing base and message classes. In that case, RTTI might be what you need (unless you want to encapsulate each existing message class into your own polymorphic message class).
0
 
forums_mpAuthor Commented:
|| And do you want that ? If not, why did you use templates ?
I think the remainder of my message answered this.  The issue boils down to an collection of generic Msg_Holder which would require something akin to boost any.  

|| But it seems you're stuck with the existing base and message classes.
Correct!  We've established that.

|| In that case, RTTI might be what you need
I'd prefer to avoid downcasts :)

|| (unless you want to encapsulate each existing message class into your own
|| polymorphic message class).
Not sure if I'm following you here.  Could you demo this with psedo or real code?

An aside:  Here's my initial (pseudo code) design
class Msg_Holder {
protected :
  R1_Msg obj_R1 ;  //NOTE:  These MUST be singleton.  Don't want each Derived class with their own copy
  int R1_Msg_Count ;
  R2_Msg obj_R2 ; //NOTE:  These MUST be singleton.  ......
  int R2_Msg_Count ;
  /// up Rn_Msg  
  T1_Msg  obj_T1 ;
  T2_Msg  obj_T2 ;
   // up to Tn
  virtual ~Msg_Holder () {}
  void Process ()  = 0 ;
};

class Msg_Handler_R1 :
  public Msg_Holder {
public :
  void Process() {
  // when called do work on R1_Msg ..
  // i.e 1) decompose message 2) Store msg within bridge 3) Notify observers
  }
};
//lots more Handlers for R's and T's


//later
class Msg_Processor () {
   Msg_Handler_R1 Obj_R1_Handler ;
   // lost more
   void Process () {
     // should call the appropriate Process function inside the handler
  }
public :  
  unsigned int Read_Aircraft_Data ( unsigned char* buf, int const len ) {}
  unsigned int Write_Aircraft_Data ( unsigned char* buf, int const len ) {}
};

FIrst issue:  
a) The various counts within the Msg_Holder class.   i.e R1_Msg_Count, R2_Msg_Count, etc. etc.  Similar story for T's.   This becomes a maintenance nightmare.  So I then asked.  How do I circumvent this (my approach is reflected in my initial post)?
b) The Msg_Holder class holds a conglomerate of R and T messages.  Truth is a R2_Msg_Handler does not need to know about an R1_Msg, R3_Msg..etc.etc, however, that doesn't seem like a show stopper.   The "T's" present an interesting problem because of the need to 'echo' back a handful of parameters.  SImply put perhaps Msg_Holder ought to be a conglomerate of T messages.

Those are core issues that given a poor implementation could results in a maintenance nightmare.
0
 
js-profiCommented:
the counts needed to be put in the Msg_Handler_* as a static. a virtual function could retrieve them from there. Msg_Holder holds an static array of pointers to Msg_Handler_*  classed. instances could be created by static member functions for each handler class and added to Msg_Holder at initilisation. Msg_holder must not know from Message_Handler classes, only manage the access to them virtually.
0
 
Infinity08Commented:
>> I think the remainder of my message answered this.

What I meant was : do you WANT separate Msg_Holder instances for every message type ? Or do you want one Msg_Holder object to handle them all ?
Currently they are separate instances, due to the use of templates.
0
 
forums_mpAuthor Commented:
Separate Msg_Holder instances
0
 
Infinity08Commented:
Well, then with your current templated Msg_Holder class, you can't have a vector that holds Msg_Holder instances with different template arguments. Unless you introduce a base class for Msg_Holder.

Furthermore, I'm not really sure what the singleton is for ... Will you have only one message of a certain type at any given time ? That sounds odd, and the name 'message' seems a bit misleading.

It seems to me like the current design is not solid. Try listing all the requirements, and I'm sure a better design should be possible.
0
 
forums_mpAuthor Commented:
|| Well, then with your current templated Msg_Holder class, you can't have a vector that holds
|| Msg_Holder instances with different template arguments.
|| Unless you introduce a base class for Msg_Holder.
Negative.  I could accomplish the same feat using boost::any in my standalone/test environment.  Trouble is Im apprehensive about using Boost in an embedded environment.

|| Furthermore, I'm not really sure what the singleton is for ...
|| Will you have only one message of a certain type at any given time ?
|| That sounds odd, and the name 'message' seems a bit misleading.

|| It seems to me like the current design is not solid. Try listing all the
|| requirements, and I'm sure a better design should be possible.

Heres the 50 foot systems view from a software perspective.  Picture a black box attached to an aircraft with software executing within the box and at most four sources hanging off the box.   The software within the box sends/receives messages between the aircraft and the four sources. 50 foot vie of the execution flow:
 
a) Read (R data) from aircraft
b) Process aircraft data
c) Write to source(s)
d) Read from source(s)
e) Process source data
f) Write (T data) to aircraft
 
Well ignore the nomenclature surround the read/writes to source.  The source code is structured around a handful of design patterns.  Notable, singleton, bridge and observers. Aircraft and source data is decomposed in the Process operations, stored in the bridge and observes on both sides (source and platform) gets notified. The handlers depicted within one of my posts reflect handlers for each message type for both aircraft and source.
 
class R1_Handler : public Base_Handler {};
class R2_Handler : public Base_Handler {};
//lots more
 
class T1_Handler :public Base_Handler {};
class T2_Handler : public Base_Handler {};
//lots more
 
The _fundamental_ issue I have surrounds the message types.  Do I create one class thatll serve as a repository for ALL messages and in doing so wrap each message in a singleton or make the repository the singleton.  Of course, R_Handlers could contain R messages.  i.e.
 
class R1_Handler : public Base_Handler {
  R1_Msg objR1 ;
public:
};
 
Trouble is there are cases where an update to a T (echo back a certain R input) in step b) above _needs_ to be get caught/reflected during step f).
 
class Repository {
public :  //exposing the interface here does not seem ideal..but ..
  T1_Msg  objT1 ;
  //lots more ..
};
 
Later:  Make the repository a singleton.
 
singleton < Repository > instance ;
R1_Handler* pR1 = new R1_Handler ( instance ) ;
 
Of course, with this approach Id like to demand a singleton in the R1_Handler constructor.   In any event, I hope you get the feel for what Im after and the rationale for the singleton
0
 
Infinity08Commented:
>> Negative.  I could accomplish the same feat using boost::any

How do you think boost::any is implemented to achieve this ? Exactly as I said ;)


>> I hope you get the feel for what Im after and the rationale for the singleton

Not really. But I've called in an extra set of eyes, because maybe I'm missing something.
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> I've called in an extra set of eyes

And here they are :)

Ok, I've only had the opportunity for a cursory read through so forgive me if I'm either covering ground already discussed or I'm wide of the mark.

My understanding of your problem is that you have a pre-defined list of message holder classes, which have no polymorphic relationship and you want to store these in the same vector in an agnostic fashion?

Although the message holder classes are not related do they present a common interface? If so have you considerer using a variation of an adaptor pattern as a way of providing the polymorphic interface you need to allow them to be stored in the vector?

http://en.wikipedia.org/wiki/Adapter_pattern

I presume singleton is some kind of factory?

In case I'm wide of the mark I won't twitter on any more, I'll provide a quick example of what I mean and if you think it's a possible way to go I'll let you and Infinity08 thrash it out.

I hope this helps.
#include <vector>

struct IMsgHolderWrapper
{
   // The functions exposed by MsgHolder, this will forward calls to the wrapper item
   virtual  void someMsgHolderFunction() = 0;
   virtual ~IMsgHolderWrapper() {};
};

template <typename msgT>
class MsgHolderWrapper : public IMsgHolderWrapper
{
public:
   typedef msgT msgholder_type;

   MsgHolderWrapper (msgholder_type * pMsgHolder) : pMsgHolder_(pMsgHolder) {}

   void someMsgHolderFunction()
   {
      pMsgHolder_->someMsgHolderFunction();
   }

private:
   msgholder_type* pMsgHolder_;
};

typedef std::vector<IMsgHolderWrapper *> msgs_t;

struct R1_Msg
{
   void someMsgHolderFunction(){}
};

struct R2_Msg
{
   void someMsgHolderFunction(){}
};

template <typename msgT>
class singleton
{
public:
   typedef msgT msg_t;

   static msg_t * instance()
   {
      static msg_t msg; // Only created on initial call
      return &msg;
   }
};

int main()
{
   msgs_t msgs;
   msgs.push_back(new MsgHolderWrapper<R1_Msg>(singleton< R1_Msg >::instance()));
   msgs.push_back(new MsgHolderWrapper<R2_Msg>(singleton< R2_Msg >::instance()));
}

Open in new window

0
 
forums_mpAuthor Commented:
Infinity08.......  After all these years of quality service please restore my faith on this one...I'm close to my last (ditch) attempt at an explanation.  Let's start with the fundamentals:

An incoming R1_Message is processed by a R handler (R1_Handler).   A handful of the incoming R messages has a requirement to store R1_Message (not all) data in  say a T1_Message (essentially echo back).   So given our strawman:
 
//------------------ Start Strawman Message Classes ------------------
class Message_Base{
pubic:
  ~virtual Message_Base() {}
};
//incoming message
class R1_Message : public Message_Base {
public :
   //Accessor/Mutators ignored
};
// Up to Rn
//outgoing message
class T1_Message : public Message_Base {
public :
   //Accessor/Mutators ignored
};
// Up to Tn
//------------------ End Strawman Message Classes ------------------
 
//------------------                    The handlers                   ------------------
class Base_Handler {
public:
  ~virtual Base_Handler() {}
  void Process () = 0 ;
};
class R1_Handler  : public Base_Handler{
public:
  void Process() {}
};
 
class T1_Handler  : public Base_Handler{
public:
  void Process() {}
};
 
The question:
Given the coupling between Rs and Ts (R handlers need access to T messages but not vice versa).   How would you address this?  NOTE:  Recall that I read Rs first then write Ts last, so any change to a T message by an R handler needs to remain persistent so further updates by the Tn_Handler (where n is 1 in our case) will include the update made by the Rn_Handle.  So now do you make the R messages local (albeit private) within the R_Handlers and create a class with a collection of T messages that you'll then pass to the Base_Handler or ......?
0
 
js-profiCommented:
i doubt you need templates. i doubt you have to count in the singleton. i doubt you need the derived type in msg_holder.

i would count in each derived handler. i would hold two maps of pointers to handlers in msg_holder class one for r handlers, one for t handlers. key could be class name or simply n number. then when a r message goes to a t message a r handler of the msg_holder class has made that job and invokes a new job in msg_holder class which would get corresponding t handler from map. the job would contain key to r handler so that baseclass pointer could be retrieved from msg_holder and data could be retrieved virtually and could generate t message virtually by t handler same way. the vectors of messages were handled in handlers as well where each was a singleton. msg_holder class only would manage maps of handlers and queue(s) of jobs.
0
 
Infinity08Commented:
>> I'm close to my last (ditch) attempt at an explanation.

This is what I got so far :

You have a bunch of message types. There are two kinds of messages : messages that are received (R messages) and messages that are sent (T messages). When a message is received, it generally results in the corresponding T message being sent.

So, for each R message type, you need a handler (and you don't need any handler for T message types, since you'll never receive them anyway). This handler will do what's appropriate for the type of message received, and if needed it will construct a corresponding T message and send it.


None of this requires a complicated design, singletons, RTTI, ... none of that.

Just a simple message handler where incoming messages are dispatched to the appropriate R message handler (function overloading sounds like an appropriate mechanism here), which might or might not construct a T message and send it.


Either that's all you need, or you need to explain more of the reauirements.
0
 
forums_mpAuthor Commented:
|| You have a bunch of message types. There are two kinds of messages :
|| messages that are received (R messages) and messages that are sent (T messages).
Ok!

|| When a message is received, it generally results in the corresponding T message being sent.
There's no generally T messages are always sent. Read on.

|| So, for each R message type, you need a handler (and you don't need any handler
||  for T message types, since you'll never receive them anyway).
|| This handler will do what's appropriate for the type of message
|| received, and if needed it will construct a corresponding T message and send it
Herein lies the misconception.  

Open the attached file to get a feel for execution flow.  Start with the Blue lines – i.e. work your way from left to right, then followed by the Red lines - essentially working in the reverse direction.  

When viewed from the Source side (Red lines) , incoming data (an SR) from _a_ Source gets parsed then stored in the Bridge and the T handles are notified.  So YES! I need T handlers.   Simply put: I have Update methods within the T handlers that gets called whenever the observed data within the “Bridge” changes by a source handler.

----------------   ISSUE  
So in theory:  A common base class for R and T handlers is (probably) silly.   A specialized version for Source and Aircraft seems - at least to me - to make more sense.  IOW:
BaseHandler < Source > xx ;
BaseHandler < Aircraft > yy ;
 
---------------  ISSUE
Today, R messages are _local_ to R handlers, T messages are _local_ to T handlers. i.e .
 
class T1Handler : public BaseHandler {
T1Message T1Obj ;
public;
};

R handlers _need_ access to T messages.  

Why!   _Again_, during decomposition of an R message in an R handler's Process method, _most_ of information is stored in the bridge and Source observers notified.  The _remainder_ of the information is simply echoed back in a T message, which - of course - is transmitted to the Aircraft during the 'last step' (the Write operation to the Aircraft).  
[Remember follow the Blue lines to completion - Write to Source interface, then follow the Red lines.  We start with a Read on the Aircraft interface (Blue line) and we end with a Write to the Aircraft interface (Red line)].

Clear?
An aside:  There's a Manager on the Aircraft side that'll Read the data and call the appropriate R handlers.  The Manger also 'queries' T handlers (do you have new data?) then invoke the Write operation.  IOW: I need another circle between the 'circles' on the Aircraft side.

 

diagram.pdf
0
 
Infinity08Commented:
>> Open the attached file to get a feel for execution flow.

I understand that's what you're trying to do, but I don't understand why ... It seems easier to do what I proposed, ie. :
diagram.png
0
 
forums_mpAuthor Commented:
|| I understand that's what you're trying to do,
Hmnnn!  And you still asked for 'requirements' definition.   In any event ...
||  It seems easier to do what I proposed, ie. :
As in an R handler to handle Source interface and Aircraft interface messages?   In addition why is the handler placed within the Bridge?   Truthfully, I'd like to get on with a solution given - at this juncture the two issues outlined in my last post.
   
0
 
Infinity08Commented:
>> Hmnnn!  And you still asked for 'requirements' definition.   In any event ...

Of course ... Because I see no reason to do it that way. So, either there is something I'm missing, which means that I don't have the whole picture, and thus cannot give you accurate advice. Or there's nothing I'm missing, in which case my advice still stands.


>> In addition why is the handler placed within the Bridge?

That's what a bridge does ... it receives messages and forwards them ... You can place the handler outside of the bridge if you prefer ... the principle is the same.


>> Truthfully, I'd like to get on with a solution given - at this juncture the two issues outlined in my last post.

In which case, either you'll have to clarify what I asked for, or I cannot help you, because I don't have all the information needed to be able to help you.
0
 
Infinity08Commented:
Alternatively, simply say that you don't want my help any more, and I'll be on my merry way ... Maybe you'll find someone else to help you ...
0
 
js-profiCommented:
if the handler's task is to receive messages and forward them it would be part of bridge. is that really the main task of the handlers?

following the blue lines the r handlers were issued by aircraft and finally disposed to source. dont see any bridge functionality which couldnt be solved generically. same is for t handlers. they were created (used) by source and their final goal is aircraft.

why the bridge should store the messages?  if r message was passed to source and source decides whether to send back a t message why didnt source store the r messages? and aircraft the t messages? why should a bridge decide what to do? or is bridge only a word for super manager?
0
 
forums_mpAuthor Commented:
||Of course ... Because I see no reason to do it that way.
I think it's important for us to call timeout at this juncture - in which case I'll capitalize on your follow on post by stating be on your merry way.  You insist on a solution that I'm not interested in and I've entertained  this dialog for too long.  In the end this is of no value added to us given the Moderator will perhaps getting involved at closure of this message.  So either it's done _MY_ way or we move on.
0
 
Infinity08Commented:
No problem. I hope you get your solution.
0
 
js-profiCommented:
> The Msg_Holder class is a generic class and I'm unsure how to typedef the vector so I could push-back message classes

if all messages were derived from common baseclass, you could define a vector containing baseclass pointers to messages.

> 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.

you could use a map instead of a vector. the key of the map ould be class name of message class. the data is the baseclass pointer. such a pair can be automatically registered by the derived message class calling a static member function of Msg_Holder
 
    // define static member bMsgIsRegistered
    bool R1_Message::bMsgIsRegistered  =
         Msg_Holder::registerMessageInstance("R1_Message, new R1_Message());

instead of registering messages you might consider registering message handlers that way.

> FIrst issue:  
a) The various counts within the Msg_Holder class.   i.e R1_Msg_Count, R2_Msg_Count, etc. etc.  Similar story for T's.   This becomes a maintenance nightmare.  So I then asked.  How do I circumvent this (my approach is reflected in my initial post)?

if you would use above map, you could add the counter to the instance pointer of message class for example by

    std::map<std::string, std::pair<Base_Message *, int count> > msg_map;

> b) The Msg_Holder class holds a conglomerate of R and T messages.  Truth is a R2_Msg_Handler does not need to know about an R1_Msg, R3_Msg..etc.etc, however, that doesn't seem like a show stopper.   The "T's" present an interesting problem because of the need to 'echo' back a handful of parameters.  SImply put perhaps Msg_Holder ought to be a conglomerate of T messages.

if a Tn message needs data of Rn message you could have a third baseclass like Base_Message_Data where all  Dn_Message_Data were derived from. if an Rn messages causes a Tn message to be echoed back you could retrieve the Dn_Message_Data by baseclass pointer from Rn message and use it fro constructing the Tn message. Neither R and T message classes nor R and T message handlers know of other messages or handlers but only would share the Dn_Message_Data.

> The _fundamental_ issue I have surrounds the message types.  Do I create one class thatll serve as a repository for ALL messages and in doing so wrap each message in a singleton or make the repository the singleton.  Of course, R_Handlers could contain R messages.

i thought the Msg_Holder class is that singleton repository. if you would store pointers to handlers in the map i described above each handler instance could store a vector of messages.

> Trouble is there are cases where an update to a T (echo back a certain R input) in step b) above _needs_ to be get caught/reflected during step f).

Base_T_Message_Handler * Msg_Holder::getTHandler(std::string message_name)
{
   return (Base_T_Message_Handler * )msg_map[message_name].first;
}

void Bridge::echoTMessage(Base_R_Message *pRMsg, Sender *pSender, Receiver *pReceiver)
{
     std::string tMsgName = pRMsg->getTMsgName();
     Base_R_Message_Handler *pTMsgHdl =
          Msg_Holder::getTMessageHandler(tMsgName);
     Base_D_Message_Data *pMsgData = pRMsg->getMsgData();
     pTMsgHdl->echoTMessage(pMsgData,  pSender, pReceiver);
}

the Bridge could be any manager that controls the flow. it also could be the Rn message handler or the Msg_Holder class in case you would like to let the repository handle the workflow. the r message classes only would know the name of the corresponding t message class. instead of class name you more easily could use the n number as key if you hold two maps for r and t handlers or Rn and Tn as string keys if using one map for both.

> ----------------   ISSUE  
So in theory:  A common base class for R and T handlers is (probably) silly.   A specialized version for Source and Aircraft seems - at least to me - to make more sense.  IOW:
BaseHandler < Source > xx ;
BaseHandler < Aircraft > yy ;

they could have a common base class but should have a direct baseclass for r and t:

  class R2_Handler : public Base_R_Handler {};
  class Base_R_Handler : public Base_Handler {};







0
 
forums_mpAuthor Commented:

Here’s how we’ll wrap this up.  Clean slate:

We know: A handful of R handlers need access to T messages.   The R handlers will update parts of a T message then sent the new message available flag.   The updated T message may further be updated by a T handler then transmitted to the Aicraft.  

For discussion  purposes here’s a layout.

R1 Handler needs access to a T1 message
R3 Handler needs access to a T2 message
R2 Handler needs access to a T2 message
// the rest omitted for brevity.
etc.

Modify the attached source to provide an approach that will allow the two handlers (R&T) to share T messages and a New_Msg_Available flag as opposed to ‘New_TXYZ_Message’ flag where XYZ reflects 1,2,…,N (see source/current design).  Since updates to a message could occur from two sources, the message needs to be persistent.

Ideally if there’s a way to have R handlers subscribe to the appropriate T message that would be nice.  

main.zip
0
 
js-profiCommented:
wouldn't it be better that T handlers subscribe to those R Handlers where the R messages might be of interest. then R Handler could invoke each subscriber passing those parts of data which were supposed for either to decide whether the message needs to be echoed at all and which were needed for the T message? following your approach (R handlers subscribed at T handlers) i dont see how the T handlers could get notified.

the subscribing could work using a static register function in each R handler that probably must invoke T handlers. the register function could be called by the T handlers at initialisation time as showed in sample code for Msg_Holder and R1 message in my last post. the R handler must not know about the T handlers subscribed. it simply would notify (invoke) all T handlers registered passing the 'shared' data part of its R message.
0
 
forums_mpAuthor Commented:
|| wouldn't it be better that T handlers subscribe to those R Handlers
|| where the R messages might be of interest.
Ok! I think we're on to something.

|| then R Handler could invoke each subscriber passing those parts of data
|| which were supposed for either to decide whether the message needs
|| to be echoed at all and which were needed for the T message?
Excellent!

The element that's missing from all this is in my initial post.  modify the existing source to what you just described.  IOW. give me something that works in code.
0
 
js-profiCommented:
probably will find some time for the coding sample today. i wanted to verify that the concept is ok for you. would you prefer singleton handlers or handlers created newly for each job (message)? in first case we need some kind of repository for singeleton handlers. in second case we need some kind of factory for handlers.
0
 
forums_mpAuthor Commented:
If I understand your question, you're asking about single instances of handlers verus single instances of messages.  I'm inclined to go with the 'second case'
0
 
js-profiCommented:
not quite. you could have a repository - say in msg_holder class - which holds one instance of each handler class. if aircraft would need a r1 handler to process an r1 message it could make a request to msg_holder singleton for the r1 handler and msg_holder would return a baseclass pointer to the one and only r1 handler. then the r1 handler (singleton) was virtually called to create an r1 message and pass it versus source. the r1 handler also would look for t handlers which has subscribed. as the r1 handler is a singleton it would hold a non-static container containing all subscriber keys, for example "t2", "t3". using those keys it would request corresponding t handlers from msg_holder and virtuall call the doecho function by passing them (shared) message data from r1 message. each t1 handler would check message data whether an echo is necessary and if yes would create t message to be sent back to aircraft.

the alternative is to have the msg_holder hold a function pointer for each handler class which creates a handler instance when being called. each derived handler would have a static create function like
   class r1_handler : public base_r_handler
   {
         public:
            static bool registerCreateFunc;  // the static bool was used
            static base_r_handler * create() { return new  r1_handler; }
         ...
the function pointer to create function was registered in msg_holder class at initialization associated to the key "r1". with that the msg_holder class could generate new handler instances on request:

   base_r_handler * pRHandler = theMsgHolder::createRHandler("r1");
   pRHandler->sendMessage(sender, receiver, msg_data);
   delete pRHandler; // delete after use

for the alternative each handler would do only one job. data which was singleton for a handler was stored in static containers.

none of the both concepts stores messages til now. if that is necessary it could be stored via baseclass pointer in msg_holder. or in derived handler class in a container<rx_message>. the container now can be specific. it is non-static in case of singleton handlers and static otherwise.  
 
0
 
forums_mpAuthor Commented:
||none of the both concepts stores messages til now.
|| if that is necessary it could be stored via baseclass pointer in msg_holder.
OK! I like this approach
|| or in derived handler class in a container<rx_message>.
I think I like this approach even better, although if you're motivated I'll also take 'code' showing 'both' approach's
|| the container now can be specific. it is non-static in case of singleton handlers and static otherwise
OK!
0
 
js-profiCommented:
yes i am motivated. hope you have little time left cause i wont find time before evening (cet).
0
 
js-profiCommented:
The below should cover most of that i suggested.  you would need some more virtual functions that actually would  do the work.
#include <vector>
#include <string>
#include <map>


class Sender;
class Receiver;

class BaseMessageData
{
    static int lastid;   // initialised to 0 in cpp
    int id;
    Sender * sender;
    Receiver * receiver;
public:
    BaseMessageData(Sender * s, Receiver * r) 
      : id(++lastid), sender(s), receiver(r)  { }
    virtual ~BaseMessageData() {}
};

class BaseRMessageData : public BaseMessageData
{
    // attributes for R messages only
public:
	BaseRMessageData(Sender * s, Receiver * r) : BaseMessageData(s, r) {}
    virtual ~BaseRMessageData() {}
};

class BaseTMessageData : public BaseMessageData
{
    // attributes for T messages only
public:
	BaseTMessageData(Sender * s, Receiver * r) : BaseMessageData(s, r) {}
    virtual ~BaseTMessageData() {}
};

class BaseMessage 
{
       Sender * sender;
       Receiver * receiver;
protected:
       BaseMessageData * data;
public:
	BaseMessage(Sender * s, Receiver * r) : sender(s), receiver(r), data(0) {}
       virtual ~BaseMessage() {}
       const BaseMessageData * getData() const { return data; }
	   Sender  * getSender()    { return sender; } 
	   Receiver * getReceiver() { return receiver; } 
};

class BaseRMessage : public BaseMessage
{
public:
       BaseRMessage( Sender * s, Receiver * r)  :BaseMessage(s, r) {}

       virtual ~BaseRMessage() {}
       const BaseRMessageData * getData() const
       { return (const BaseRMessageData *)getData() ; }

     
};

class BaseTMessage : public BaseMessage
{
public:
       BaseTMessage( Sender * s, Receiver * r)  :BaseMessage(s, r) {}

       virtual ~BaseTMessage() {}
       const BaseTMessageData * getData() const
       { return (const BaseTMessageData *)getData() ; }
     
};

class BaseRMessageHandler;
class BaseTMessageHandler;

// function pointers 
typedef BaseRMessageHandler * (*FuncCreateRMessageHandler)();
typedef BaseTMessageHandler * (*FuncCreateTMessageHandler)();
 
class MessageHolder
{
	MessageHolder() {}  // singleton
	std::map<int, FuncCreateRMessageHandler> rfactory;
	std::map<int, FuncCreateTMessageHandler> tfactory;
	std::map<int, BaseMessage*> messages;
public:
	static MessageHolder& theMsgHolder() 
	{
		static  MessageHolder *  msgHolder = new MessageHolder();
		return *msgHolder;  
	}
	bool addRHandlerCreateFunction(FuncCreateRMessageHandler funcRHdlr, int id)
	{   rfactory[id] = funcRHdlr; return true; }
	bool addTHandlerCreateFunction(FuncCreateTMessageHandler funcTHdlr, int id)
	{   tfactory[id] = funcTHdlr; return true; }
	BaseRMessageHandler * getRHandler(int i)
	{
		std::map<int, FuncCreateRMessageHandler>::iterator f;
		f = rfactory.find(i);
		if (f == rfactory.end()) return 0;
		return f->second();  
	}
	BaseTMessageHandler * getTHandler(int i)
	{
		std::map<int, FuncCreateTMessageHandler>::iterator f;
		f = tfactory.find(i);
		if (f == tfactory.end()) return 0;
		return f->second();  
	}
	void storeMessage(BaseMessage * msg, int mid)
	{ messages[mid] = msg; }
	BaseMessage * getMessage(int mid)
	{
		std::map<int, BaseMessage*>::iterator f;
		f = messages.find(mid);
		if (f == messages.end()) return 0;
		return f->second;  
	}
};

class BaseMessageHandler
{
protected:
       BaseMessage * msg;
public:
       BaseMessage * getMessage() { return msg; }
       BaseMessageHandler() : msg() {} 
       virtual ~BaseMessageHandler() {} 
};
 
class BaseTMessageHandler : public BaseMessageHandler
{
       
protected:
      
       BaseTMessage * getTMessage() { return (BaseTMessage *)getMessage(); }
       virtual bool checkRMessageForEcho(const BaseRMessageData * rdata);   
       virtual void echoRMessage(const BaseRMessageData * rdata);   
       
public:
       BaseTMessageHandler() {}
       virtual ~BaseTMessageHandler() {} 
       virtual bool onNotifyRMessage(const BaseRMessageData * rdata)
       {
             if (checkRMessageForEcho(rdata))
             {
                  echoRMessage(rdata);
                  return true;
             }           
             return false;
       }     
};

class BaseRMessageHandler : public BaseMessageHandler
{
protected:
      static std::vector<int> subscribers;
      BaseRMessage * getRMessage() { return (BaseRMessage *)getMessage(); }

public:
	   BaseRMessageHandler() {}
       virtual ~BaseRMessageHandler() {} 
       
       int notifyAllSubscribers()
       {
             const BaseRMessageData * rdata = getRMessage()->getData();
             std::vector<int>::iterator i;
             for (i = subscribers.begin(); i != subscribers.end(); ++i)
             {
				 BaseTMessageHandler * thdlr = MessageHolder::theMsgHolder().getTHandler(*i);
                   if (thdlr != 0)
                        thdlr->onNotifyRMessage(rdata);
             }
       }
};


class R1MessageData : public BaseRMessageData
{
     // sample data     
     int i;
     double d;
     std::string s;
     R1MessageData(Sender * s, Receiver * r, int i1, double d2, const std::string & s3)
         : BaseRMessageData(s, r), i(i1), d(d2), s(s3) {}
public:

     friend class  R1Message;        // R1 message has R1MessageData 
     friend class  T2MessageHandler; // T2 message handler uses R1MessageData
};

class R1Message : public BaseRMessage
{
public:
      R1Message(Sender * s, Receiver * r)  : BaseRMessage(s, r) {}
      virtual ~R1Message()  {}       
      bool setMessageData(int i1, double d2, std::string s3)
      {
            data = new R1MessageData(getSender(), getReceiver(), i1, d2, s3);
      }  
};

class R1MessageHandler : public BaseRMessageHandler
{
       static bool setCreateFunc;  // serves for setting the create function
                                                   // to MessageHolder factory at initialisation
       static BaseRMessageHandler * create() { return new R1MessageHandler(); }
public:
       static void addSubscriber(int ti)
	   {
		  subscribers.push_back(ti);
	   }
	   friend class MessageHolder;
};

// r1_message_handler.cpp


// set create function
bool R1MessageHandler::setCreateFunc = 
     MessageHolder::theMsgHolder().addRHandlerCreateFunction(R1MessageHandler::create, 1);


class T2MessageData : public BaseTMessageData
{
     // sample data  
	 char c;
     T2MessageData(Sender * s, Receiver * r, char c1)
         : BaseTMessageData(s, r), c(c1) {}
public:

     friend class  T2Message; // T2 message has T2MessageData
};

class T2Message : public BaseTMessage
{
public:
      T2Message(Sender * s, Receiver * r)  : BaseTMessage(s, r) {}
      virtual ~T2Message()  {}       
      bool setMessageData(char c1)
      {
            data = new T2MessageData(getSender(), getReceiver(), c1);
      }  
};

class T2MessageHandler : public BaseTMessageHandler
{
       static bool setCreateFunc;  // serves for setting the create function
                                                   // to MessageHolder factory at initialisation
	   static void subscribeAtR1Handler()
	   {
		   // that is a bit tricky as we need the R1 handler already been added to factory in MessageHolder
		   R1MessageHandler::addSubscriber(2);
             
	   }
public:
       static BaseTMessageHandler * create() { return new T2MessageHandler(); }
};


// t2_message_handler.cpp
// set create function
bool T2MessageHandler::setCreateFunc = 
       MessageHolder::theMsgHolder().addTHandlerCreateFunction(T2MessageHandler::create, 1);

Open in new window

0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 13
  • 11
  • 10
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now