473,837 Members | 1,581 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

implementation details

Lets suppose the return value on new_command is MSG2_STATUS

My intent then is to memcpy the data via the call to CMDHolder and
have a function that'll retrieve a copy of the 'stored' data. The
latter I'm unsure how to do. Any help appreaciated.
#include <iostream>
#include <map>
using namespace std;

int msg2_status_ind ex = 0;
int msg1_status_ind ex = 0;
int msg1_cmd_index = 0;

MSG2_STATUS _msg2_stat[ 2 ]; // used for double buffering
MSG1_STATUS _msg1_stat[ 2 ]; // used for double buffering
MSG1_CMD _msg1_cmd[ 2 ]; // used for double buffering

typedef enum
{
_msg1_cmd = 0,
_msg1_status,
_msg2_status
} MSG_ID;

typedef struct // this is ++. Why use typedef. 'details' I suppose
{
MSG_ID source;
unsigned int msg_length : 12;
unsigned int count : 4;
} MSG_HEADER;

typedef struct _MSG2_STATUS
{
MSG_HEADER header;
unsigned int idx : 1;
unsigned int jdx : 3;
unsigned int kdx : 4;
unsigned int spare : 24;
unsigned int ldx : 32;
} MSG2_STATUS;

typedef struct _MSG1_STATUS
{
MSG_HEADER header;
unsigned int idx : 1;
unsigned int jdx : 3;
unsigned int kdx : 4;
unsigned int spare : 8;
} MSG1_STATUS;

typedef struct _MSG1_CMD
{
MSG_HEADER header;
unsigned int idx : 1;
unsigned int jdx : 3;
} MSG1_CMD;

class CMDBase
{
public:
virtual ~CMDBase(){}
/* what operations do you perform on these commands?
virtual void operation1() = 0;
virtual void operation2() = 0; */
};
template <class CMD>
class CMDHolder: public CMDBase
{
public:
CMDHolder(unsig ned char const* buffer)
{
memcpy(&m_CMDSt ruct, buffer, sizeof m_CMDStruct);
}

/* virtual void operation1()
{
//use overloaded global functions?
structOperation 1(m_CMDStruct);
}

virtual void operation2()
{
structOperation 2(m_CMDStruct);
} */
private:
CMD m_CMDStruct;
};

class CMDFactory
{
public:
static CMDFactory& instance()
{
CMDFactory fact;
return fact;
}

// Register the creator
template <class T> void Register(int Id)
{
m_creators[Id] = CMDCreator<T>;
}
// unregister creator
bool Unregister( const int& Id )
{
return m_creators.eras e( Id ) == 1;
}

CMDBase* Create(unsigned char const* buffer)
{
//MSG_HEADER* msg_id = reinterpret_cas t<MSG_HEADER*>( buffer);
MSG_HEADER* msg_id; // only here because reinterpret_cas t error
complaint

//insert error checking!
return (m_creators[msg_id->source])(buffer);
}
reinterpret_cas t generates an error with respect to the constant
buffer and the non constant MSG_HEADER*. ??

return (m_creators[msg_id->source])(buffer); // return here might be
a bit confusing

private:
typedef CMDBase* (*CMDCreator_t) (unsigned char const*);

template <class T>
static CMDBase* CMDCreator(unsi gned char const* buffer)
{
return new T(buffer);
}

std::map<int, CMDCreator_t> m_creators;
};

int main ( void )
{
//called once, in initialization function:
CMDFactory::ins tance().Registe r<MSG2_STATUS> (1);
CMDFactory::ins tance().Registe r<MSG1_STATUS> (2);
// inside your command processing loop:
unsigned char buffer[512];
// Read_1553_Data( CHANNEL_FIVE, &buffer);
CMDBase* newCommand = CMDFactory::ins tance().Create( buffer);

// newCommand->operation1() ; //whatever you want to do with it
//maybe add it to a queue<CMDBase*> ?
//myqueue.push(ne wCommand);

return EXIT_SUCCESS;
}
Jul 19 '05 #1
6 2930
On 2 Oct 2003 03:57:29 -0700, mp********@hotm ail.com (MPowell) wrote:
Lets suppose the return value on new_command is MSG2_STATUS

My intent then is to memcpy the data via the call to CMDHolder and
have a function that'll retrieve a copy of the 'stored' data. The
latter I'm unsure how to do. Any help appreaciated.
Well, I can fix the errors in the code, but you'll have to explain
what the code is meant to do. What do you want to do with the messages
that you receive? Do you need to perform some action depending on the
type of message you receive?
CMDBase* Create(unsigned char const* buffer)
{
//MSG_HEADER* msg_id = reinterpret_cas t<MSG_HEADER*>( buffer);
MSG_HEADER* msg_id; // only here because reinterpret_cas t error
complaint

//insert error checking!
return (m_creators[msg_id->source])(buffer);
}
The above function should go more like this:

CMDBase* Create(unsigned char const* buffer)
{
MSG_HEADER const* msg_id = reinterpret_cas t<MSG_HEADER
const*>(buffer) ;
map_t::const_it erator 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 );
}
reinterpret_ca st generates an error with respect to the constant
buffer and the non constant MSG_HEADER*. ??
Making the header const fixes your problem.
return (m_creators[msg_id->source])(buffer); // return here might be
a bit confusing


The above is actuall a function call made through a function pointer.
m_creators maps source id onto a creation function pointer than can
create the Holder object for messages of that type. The above accesses
that function pointer and calls the function, passing "buffer" as the
first parameter. That function in tern returns a new Holder object,
initialized with the buffer.

Tom
Jul 19 '05 #2
MPowell wrote:

<snip>

MSG2_STATUS _msg2_stat[ 2 ]; // used for double buffering
MSG1_STATUS _msg1_stat[ 2 ]; // used for double buffering
MSG1_CMD _msg1_cmd[ 2 ]; // used for double buffering

typedef enum
{
_msg1_cmd = 0,
_msg1_status,
_msg2_status
} MSG_ID;


Every one of these variables and enumerators is illegal. Identifiers
beginning with an underscore followed by a lowercase letter are reserved
in the global namespace.

Just don't use identifiers beginning with an underscore. It's the
easiest way to avoid this problem.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #3
> Well, I can fix the errors in the code, but you'll have to explain
what the code is meant to do. What do you want to do with the messages
that you receive? Do you need to perform some action depending on the
type of message you receive?
Consider

#define ID_ERROR_MASK 0x08 // #defined at top of the translation unit
#define ID_MASK 0x07 // #defined at top of the translation unit
int _msg2_header_er ror_count = 0;
int _msg1_header_er ror_count = 0;

int _msg2_message_i ndex = 0;
int _msg1_message_i ndex = 0;
// lots more

struct _MSG2_STATUS // here for demo and lots more of these
{
// for simplicity strip out 'stuff'.
unsigned int idx : 1;
unsigned int ldx : 32;
} MSG2_STATUS;

MSG2_STATUS _msg2_message[ 2 ]; // for double buffering
// lots more

The Create function will look at the msg_id (which it does) then check
for error.

if (msg_id & ID_ERROR_MASK) == 0 )
{
// if no error look at msg_type
MSG_HEADER msg_type =
(((( msg_id >> 4 ) & ID_MASK ) <<3 )) | ( msg_id &
ID_MASK );

Lets suppose now the msg_type maps to MSG2_STATUS defined above

switch (msg_type)
{
case _msg2_status: //got a status 2 message

// double buffer it
i = _msg2_message_i ndex ^ 1;
memcpy( &_msg2_messa ge[i], buffer, sizeof(MSG2_STA TUS) );
_msg2_message_i ndex ^= 1;
_msg2_message_r eady = TRUE;
break;

case _msg1_status: //got a status 1 message

// double buffer it
i = _msg1_message_i ndex ^ 1;
memcpy( &_msg1_messa ge[i], buffer, sizeof(MSG1_STA TUS) );
_msg1_message_i ndex ^= 1;
_msg1_message_r eady = TRUE;
break;
// and so on
default:
break;
}
else
{
switch( msg_id )
{
case _msg2_header_er ror: //got a status 2 message
_msg2_header_er ror_count++;
printf (" msg2_header_err or = &d ", msg2_header_err or);
break;
case _msg1_header_er ror: //got a status 2 message
_msg1_header_er ror_count++;

// I suspect it'd be prudent to pass in the counters and
have values returend by the ++ ostream approach
printf (" msg1_header_err or = &d ", msg1_header_err or);
break;
// and so on
default:
break;
}
}

So now, double buffer the data,increment a counter, then set a flag -
for no errors. For errors, increment an error counter. The current
template style approach is certainly more elegant

A separate function within the class should retrieve the most current
double buffer data. I suspect (assuming i understand templates) each
buffered data will be 'pushed' into a container/holder/?? and when
necessary (a 120hz processing rountine retrieves the latest) retrieved
via a call to some function with the template parameter being the
appropriate struct.

Lastly, the individual structs form a part of an overall struct. ie
struct OVERALL
{
MSG1_TYPE msg1;
MSG2_TYPE msg2;
lots more.
}

A separate function will retrieve the 'overall'.

In essence, a template to 'get' the data and hold data for the
requestor
CMDBase* Create(unsigned char const* buffer)
{
//MSG_HEADER* msg_id = reinterpret_cas t<MSG_HEADER*>( buffer);
MSG_HEADER* msg_id; // only here because reinterpret_cas t error
complaint

//insert error checking!
return (m_creators[msg_id->source])(buffer);
}
The above function should go more like this:

CMDBase* Create(unsigned char const* buffer)
{
MSG_HEADER const* msg_id = reinterpret_cas t<MSG_HEADER
const*>(buffer) ;
map_t::const_it erator i = m_creators.find (msg_id->source);


map_t error ??
if (i == m_creators.end( ))
{
throw runtime_error(" Invalid source");
}
else
{
//call create function through pointer.
return (i->second)(buffer );
}
reinterpret_ca st generates an error with respect to the constant
buffer and the non constant MSG_HEADER*. ??


Making the header const fixes your problem.
return (m_creators[msg_id->source])(buffer); // return here might be
a bit confusing


The above is actuall a function call made through a function pointer.
m_creators maps source id onto a creation function pointer than can
create the Holder object for messages of that type. The above accesses
that function pointer and calls the function, passing "buffer" as the
first parameter. That function in tern returns a new Holder object,
initialized with the buffer.

Tom


Tom, truly appreaciate the assistance. Feel free to use my email
address if necessary.
Jul 19 '05 #4
MPowell wrote:

<snip>

int _msg2_header_er ror_count = 0;
int _msg1_header_er ror_count = 0;

int _msg2_message_i ndex = 0;
int _msg1_message_i ndex = 0;
These are all illegal (assuming this is the global namespace).
// lots more

struct _MSG2_STATUS // here for demo and lots more of these


This is illegal anywhere. From the standard:

17.4.3.1.2 Global names [lib.global.name s]

1 Certain sets of names and function signatures are always reserved to
the implementation:

--Each name that contains a double underscore __) or begins with an
underscore followed by an uppercase letter (_lex.key_) is reserved
to the implementation for any use.

--Each name that begins with an underscore is reserved to the imple-
mentation for use as a name in the global namespace.
I still don't understand your question - can it be demonstrated in a
smaller, simpler code sample?

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #5
On 2 Oct 2003 13:47:49 -0700, mp********@hotm ail.com (MPowell) wrote:
Well, I can fix the errors in the code, but you'll have to explain
what the code is meant to do. What do you want to do with the messages
that you receive? Do you need to perform some action depending on the
type of message you receive?
Consider


The below doesn't answer the question, a couple of paragraphs of text
might.

#define ID_ERROR_MASK 0x08 // #defined at top of the translation unit
#define ID_MASK 0x07 // #defined at top of the translation unit
int _msg2_header_er ror_count = 0;
int _msg1_header_er ror_count = 0;

int _msg2_message_i ndex = 0;
int _msg1_message_i ndex = 0;
// lots more

struct _MSG2_STATUS // here for demo and lots more of these
{
// for simplicity strip out 'stuff'.
unsigned int idx : 1;
unsigned int ldx : 32;
} MSG2_STATUS;

MSG2_STATUS _msg2_message[ 2 ]; // for double buffering
I now finally understand what you mean by double buffering - you want
to keep the last two messages of each type.
// lots more

The Create function will look at the msg_id (which it does) then check
for error.

if (msg_id & ID_ERROR_MASK) == 0 )
{
// if no error look at msg_type
MSG_HEADER msg_type =
(((( msg_id >> 4 ) & ID_MASK ) <<3 )) | ( msg_id &
ID_MASK );

Lets suppose now the msg_type maps to MSG2_STATUS defined above

switch (msg_type)
{
case _msg2_status: //got a status 2 message

// double buffer it
i = _msg2_message_i ndex ^ 1;
memcpy( &_msg2_messa ge[i], buffer, sizeof(MSG2_STA TUS) );
_msg2_message_i ndex ^= 1;
_msg2_message_r eady = TRUE;
break;

case _msg1_status: //got a status 1 message

// double buffer it
i = _msg1_message_i ndex ^ 1;
memcpy( &_msg1_messa ge[i], buffer, sizeof(MSG1_STA TUS) );
_msg1_message_i ndex ^= 1;
_msg1_message_r eady = TRUE;
break;
// and so on
default:
break;
The above code doesn't really do anything. Instead, you should
probably just add the message to a queue and signal a condition
variable on that queue so that another thread whose job is to process
these messages can do so.
}
else
{
switch( msg_id )
{
case _msg2_header_er ror: //got a status 2 message
_msg2_header_er ror_count++;
printf (" msg2_header_err or = &d ", msg2_header_err or);
break;
case _msg1_header_er ror: //got a status 2 message
_msg1_header_er ror_count++;

// I suspect it'd be prudent to pass in the counters and
have values returend by the ++ ostream approach
printf (" msg1_header_err or = &d ", msg1_header_err or);
break;
// and so on
default:
break;
}
}

So now, double buffer the data,increment a counter, then set a flag -
for no errors. For errors, increment an error counter. The current
template style approach is certainly more elegant
Yes, since all messages can be treated the same - no switch
statements. Polymorphism is the important thing here though -
templates are just an implementation detail.
A separate function within the class should retrieve the most current
double buffer data.
Does this operate in the same thread? It might be good to put it in
another thread.

I suspect (assuming i understand templates) eachbuffered data will be 'pushed' into a container/holder/??
Seems like a good idea.

and whennecessary (a 120hz processing rountine retrieves the latest) retrieved
via a call to some function with the template parameter being the
appropriate struct.
Yes, something like that. You could use the visitor pattern as Gianni
suggested.
Lastly, the individual structs form a part of an overall struct. ie
struct OVERALL
{
MSG1_TYPE msg1;
MSG2_TYPE msg2;
lots more.
}

A separate function will retrieve the 'overall'.
Now I'm confused - aren't the messages separate? What *are* these
messages? What do they signify? Where do they come from? Some hardware
device? How are you meant to react to different messages? Why is there
more than one message type?
In essence, a template to 'get' the data and hold data for the
requestor
> CMDBase* Create(unsigned char const* buffer)
> {
> //MSG_HEADER* msg_id = reinterpret_cas t<MSG_HEADER*>( buffer);
> MSG_HEADER* msg_id; // only here because reinterpret_cas t error
>complaint
>
> //insert error checking!
> return (m_creators[msg_id->source])(buffer);
> }


The above function should go more like this:

CMDBase* Create(unsigned char const* buffer)
{
MSG_HEADER const* msg_id = reinterpret_cas t<MSG_HEADER
const*>(buffer) ;
map_t::const_it erator i = m_creators.find (msg_id->source);


map_t error ??


Whoops, that's meant to be a typedef for the map type that you need to
add to your class definition. e.g.
typedef std::map<int, Creator*> map_t;

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.

#include <iostream>
#include <map>
#include <queue>

using namespace std;

//message queue
class CMDBase;
queue<CMDBase*> CMDQueue;

enum MSG_ID
{
msg1_cmd = 0,
msg1_status = 1,
msg2_status = 2
};

struct MSG_HEADER
{
MSG_ID source;
unsigned int msg_length : 12;
unsigned int count : 4;
};

struct MSG2_STATUS
{
MSG_HEADER header;
unsigned int idx : 1;
unsigned int jdx : 3;
unsigned int kdx : 4;
unsigned int spare : 24;
unsigned int ldx : 32;
};

struct MSG1_STATUS
{
MSG_HEADER header;
unsigned int idx : 1;
unsigned int jdx : 3;
unsigned int kdx : 4;
unsigned int spare : 8;
};

struct MSG1_CMD
{
MSG_HEADER header;
unsigned int idx : 1;
unsigned int jdx : 3;
};

class CMDProcessor
{
public:
void process(MSG2_ST ATUS& msg)
{
std::cout << "MSG2_STATU S processed\n";
}

void process(MSG1_ST ATUS& msg)
{
std::cout << "MSG1_STATU S processed\n";
}

void process(MSG1_CM D& cmd)
{
std::cout << "MSG1_CMD processed\n";
}
};

class CMDBase
{
public:
virtual ~CMDBase(){}
virtual void process(CMDProc essor* processor) = 0;
};
template <class CMD>
class CMDHolder: public CMDBase
{
public:
CMDHolder(unsig ned char const* buffer)
{
memcpy(&m_CMDSt ruct, buffer, sizeof m_CMDStruct);
}

virtual void process(CMDProc essor* processor)
{
processor->process(m_CMDS truct);
}

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<CMDH older<T> >;
}
// unregister creator
bool Unregister( const int& Id )
{
return m_creators.eras e( Id ) == 1;
}

CMDBase* Create(unsigned char const* buffer)
{
MSG_HEADER const* msg_id = reinterpret_cas t<MSG_HEADER
const*>(buffer) ;
map_t::const_it erator 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 );
}
}
private:
typedef CMDBase* (*CMDCreator_t) (unsigned char const*);

template <class T>
static CMDBase* CMDCreator(unsi gned char const* buffer)
{
return new T(buffer);
}

typedef std::map<int, CMDCreator_t> map_t;
map_t m_creators;
};

void register_types( )
{
CMDFactory::ins tance().Registe r<MSG1_CMD>(0) ;
CMDFactory::ins tance().Registe r<MSG1_STATUS>( 1);
CMDFactory::ins tance().Registe r<MSG2_STATUS>( 2);
}

size_t ReadData(unsign ed char* buffer, size_t size)
{
//generate sample data
static bool doMsg1 = false;
void* data;
size_t actualSize;
MSG1_STATUS msg1 = {};
MSG2_STATUS msg2 = {};
if (doMsg1)
{
msg1.header.sou rce = msg1_status;
data = &msg1;
actualSize = sizeof msg1;
}
else
{
msg2.header.sou rce = 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.empt y())
{
CMDBase* cmd = CMDQueue.front( );
CMDQueue.pop();
cmd->process(&proce ssor);
delete cmd;
}
}

void fillQueue()
{
unsigned char buffer[512];
ReadData(buffer , 512);
CMDBase* newCommand = CMDFactory::ins tance().Create( buffer);
CMDQueue.push(n ewCommand);
}

int main ( void )
{
register_types( );

for (int i = 0; i < 5; ++i)
{
fillQueue();
processQueue();
}

return EXIT_SUCCESS;
}
Jul 19 '05 #6
tom_usenet <to********@hot mail.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_ST ATUS& msg)
{
std::cout << "MSG2_STATU S 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_STATU S'. 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(unsig ned char const* buffer)
{
memcpy(&m_CMDSt ruct, buffer, sizeof m_CMDStruct);
}

virtual void process(CMDProc essor* processor)
{
processor->process(m_CMDS truct);
}

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<CMDH older<T> >;
}
// unregister creator
bool Unregister( const int& Id )
{
return m_creators.eras e( Id ) == 1;
}

CMDBase* Create(unsigned char const* buffer)
{
MSG_HEADER const* msg_id = reinterpret_cas t<MSG_HEADER
const*>(buffer) ;
map_t::const_it erator 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(unsi gned char const* buffer)
{
return new T(buffer);
}

typedef std::map<int, CMDCreator_t> map_t;
map_t m_creators;
};

void register_types( )
{
CMDFactory::ins tance().Registe r<MSG1_CMD>(0) ;
CMDFactory::ins tance().Registe r<MSG1_STATUS>( 1);
CMDFactory::ins tance().Registe r<MSG2_STATUS>( 2);
}

size_t ReadData(unsign ed 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.sou rce = msg1_status;
data = &msg1;
actualSize = sizeof msg1;
}
else
{
msg2.header.sou rce = 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.empt y())
{
CMDBase* cmd = CMDQueue.front( );
CMDQueue.pop();
cmd->process(&proce ssor);
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(byte 1)
BYTE2. while !empty 2 results in : <- pop .. cmd->process(byte 2)
&process is in effect a pass through to
processor->process(m_CMDS truct);?
I missed how the CMD type was passed in?
Thanks again.
Jul 19 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
4659
by: Anon Email | last post by:
Hi people, I'm learning about header files in C++. The following is code from Bartosz Milewski: // Code const int maxStack = 16; class IStack
2
3293
by: Nobody | last post by:
I took the advice from the group and got rid of the node accessor functions and arrived at this definition. I have not added the copy constructor/assignment operators to this class yet. template <class TYPE, class ARG_TYPE = const TYPE&> class CBTree : public CObject { // Constructors public: CBTree();
2
4484
by: pvinodhkumar | last post by:
I am reading Lippman's Inside C++ object model. I feel lonely because the Microsoft C++ compiler which I use does not provide me an implementation details manual, describing how they implement vtables in case of single inheritance and multiple inheritance. Just to verify what I read is correct I don't have the same from any other compiler vendors also. I do not know where CFront's implementation manuals are.
1
1569
by: P Vinodh Kumar | last post by:
Reposting, please give your ideas/suggestions/comments. I am reading Lippman's Inside C++ object model. I feel lonely because the Microsoft C++ compiler which I use does not provide me an implementation details manual, describing how they implement vtables in case of single inheritance and multiple inheritance. Just to verify what I read is correct I don't have the same from any
15
2358
by: Claudio Grondi | last post by:
Let's consider a test source code given at the very end of this posting. The question is if Python allows somehow access to the bytes of the representation of a long integer or integer in computers memory? Or does Python hide such implementation details that deep, that there is no way to get down to them? The test code below shows, that extracting bits from an integer value n is faster when using n&0x01 than when using n%2 and I...
17
15674
by: Soumyadip Rakshit | last post by:
Hi, Could anyone direct me to a very good 1D DCT Implementation in C/C++ My data is in sets of 8 numbers. Thanks a ton, Soumyadip.
1
1295
by: vighnesh | last post by:
Hi Folks Can anybody please help me in finding out information ( implementation details )regarding Registry Optimization, defragmentation ? Since I am dealing with an application in which I have to implment those features, I googled the NET, but clouldn't find any implmentation details than some tools that do these defragmentation and Optimization. Please suggest me . I am thanking you very much in advance.
6
2612
by: Achim Domma | last post by:
Hi, I'm interested in details about how sets are implemented in python. They seem to be quite fast and I found some remarks who state, that the implementation is highly optimized. I need to implemented sets in C/C++ and need a starting point on how to do it right. Could somebody give me a starting point? regards, Achim
6
3969
by: Ralph | last post by:
Hi, I was reading effictive C++ and some other books again and they all tell you about hiding implementation details (proxy/pimpl/inheritance) but they never really explain when to use it. I am starting on a new project which is part library so I think it would be good to hide the implementation for the public classes in the library but this seems a lot of overhead to me (both when developing and runtime overhead).
173
14024
by: Ron Ford | last post by:
I'm looking for a freeware c99 compiler for windows. I had intended to use MS's Visual C++ Express and use its C capability. In the past with my MS products, I've simply needed to make .c the filetype to invoke the C compiler. Here's a link http://www.microsoft.com/express/download/#webInstall The download is 2.6 megs, which is near a reasonable size for a compiler, but then setup.exe wants to download 87 megs of dot net framework...
0
10560
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10611
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9390
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7801
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6988
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5663
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
4469
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4034
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
3120
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.