Re: implementation details
From: MPowell (mpowell_jr_at_hotmail.com)
Date: 10/03/03
- Next message: Sim Nanda: "Is there already a discrete range class?"
- Previous message: David Rubin: "Re: Help: 2D Array Reversing"
- In reply to: tom_usenet: "Re: implementation details"
- Next in thread: Kevin Goodsell: "Re: implementation details"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: 3 Oct 2003 13:35:31 -0700
tom_usenet <tom_usenet@hotmail.com> wrote in message >
> Following is some complete compileable code that might help. It
> basically shows how to enqueue all messages onto a queue, and how you
> might go about processing those messages. If you might need different
> processors for the messages in different circumstances, then the
> visitor pattern might be appropriate. This is rather a lot to take in
> if you are quite new to C++, but I hope it helps in any case.
Truly appreaciate the assistance. I'm starting to get a feel for what
a poster REALLY meant when he highlighted that C is not C++.
Theoretically I have to change my 'C' style design approach. This was
truly a lesson in implementation.
I was reading a post on recommended texts from a Mike Whaler and I've
since placed some orders.
Really despise having to continue/drag this post out, nonetheless I've
got a few more questions on this.
class CMDProcessor
{
public:
void process(MSG2_STATUS& msg)
{
std::cout << "MSG2_STATUS processed\n";
}
:
:
:
};
I assume these process functions is where I need to do my 'double
buffering'?
The system like any another is riddled with asynchrous processing. In
other words assume I had this.
MSG2_STATUS msg2_stat [ 2 ];
Now fillQueue() and processQueue(); fills and processes a
"MSG2_STATUS'. I'll copy the data to msg2_stat [ 0 ]. Lets suppose
now that we're filling (fillQueue()) and processing (processQueue())
another MSG2_STATUS BUT while filling or processing a separate 60
Hertz task (which I have) is getting the most current MSG2_STATUS.
The 60 Hertz task will grab/read the data in msg2_status[ 0 ] while
fill (fillQueue()) and process (processQueue()) writes to msg2_status
[ 1 ].
Yes, there's the 'unlikely' event where I'll have a race condition
where they're both trying to read (the 60 Hertz) and write
(processQueue) to the same location but i've got a handle on that via
the mechanisms of the RTOS.
>
> template <class CMD>
> class CMDHolder: public CMDBase
> {
> public:
> CMDHolder(unsigned char const* buffer)
> {
> memcpy(&m_CMDStruct, buffer, sizeof m_CMDStruct);
> }
>
> virtual void process(CMDProcessor* processor)
> {
> processor->process(m_CMDStruct);
> }
>
> private:
> CMD m_CMDStruct;
> };
>
> class CMDFactory
> {
> public:
> static CMDFactory& instance()
> {
> static CMDFactory fact;
> return fact;
> }
>
> // Register the creator
> template <class T> void Register(int Id)
> {
> m_creators[Id] = CMDCreator<CMDHolder<T> >;
> }
> // unregister creator
> bool Unregister( const int& Id )
> {
> return m_creators.erase( Id ) == 1;
> }
>
> CMDBase* Create(unsigned char const* buffer)
> {
> MSG_HEADER const* msg_id = reinterpret_cast<MSG_HEADER
> const*>(buffer);
> map_t::const_iterator i = m_creators.find(msg_id->source);
>
> if (i == m_creators.end())
> {
> throw runtime_error("Invalid source");
> }
> else
> {
> //call create function through pointer.
> return (i->second)(buffer);
Get an exception here in Visual C.NET. Not sure if a C style try
catch handler would be ideal
> }
> }
> private:
> typedef CMDBase* (*CMDCreator_t)(unsigned char const*);
>
> template <class T>
> static CMDBase* CMDCreator(unsigned char const* buffer)
> {
> return new T(buffer);
> }
>
> typedef std::map<int, CMDCreator_t> map_t;
> map_t m_creators;
> };
>
> void register_types()
> {
> CMDFactory::instance().Register<MSG1_CMD>(0);
> CMDFactory::instance().Register<MSG1_STATUS>(1);
> CMDFactory::instance().Register<MSG2_STATUS>(2);
> }
>
> size_t ReadData(unsigned char* buffer, size_t size)
> {
> //generate sample data
> static bool doMsg1 = false;
> void* data;
> size_t actualSize;
> MSG1_STATUS msg1 = {};
> MSG2_STATUS msg2 = {};
Interesting I had to change above to.
MSG1_STATUS msg1;
MSG2_STATUS msg2;
VC.NET complier complained that 'local function definitions are
illegal
> if (doMsg1)
> {
> msg1.header.source = msg1_status;
> data = &msg1;
> actualSize = sizeof msg1;
> }
> else
> {
> msg2.header.source = msg2_status;
> data = &msg2;
> actualSize = sizeof msg2;
> }
> if (size < actualSize)
> throw runtime_error("buffer too short");
> memcpy(buffer, data, actualSize);
> doMsg1 = !doMsg1;
> return actualSize;
> }
>
> CMDProcessor processor;
>
> void processQueue()
> {
> while (!CMDQueue.empty())
> {
> CMDBase* cmd = CMDQueue.front();
> CMDQueue.pop();
> cmd->process(&processor);
> delete cmd;
> }
> }
I suspect I understand the simplistic version of queues. The
cmd->process and delete cmd should be placed outside the while loop??
Each element that gets 'popped' off the queue results in a call to
cmd-process/delete cmd. so now assume two bytes.
BYTE1. while !empty 1 results in : <- pop .. cmd->process(byte1)
BYTE2. while !empty 2 results in : <- pop .. cmd->process(byte2)
&process is in effect a pass through to
processor->process(m_CMDStruct);?
I missed how the CMD type was passed in?
Thanks again.
- Next message: Sim Nanda: "Is there already a discrete range class?"
- Previous message: David Rubin: "Re: Help: 2D Array Reversing"
- In reply to: tom_usenet: "Re: implementation details"
- Next in thread: Kevin Goodsell: "Re: implementation details"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|