implementation details

From: forums_mp (forums_mp_at_hotmail.com)
Date: 10/25/03


Date: 25 Oct 2003 09:33:53 -0700

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



Relevant Pages

  • Re: problem iterating over list view items
    ... > int y = 5; ... retrieve, and iSubItem to zero (unless you actually want to retrieve a ... Further, since you are requesting the text of the item, you ... of this buffer in characters. ...
    (microsoft.public.vc.language)
  • Simple script annimation problem usig swing
    ... To change this template, ... public void destroy{ ... public state cstate; ... public static int respawn = 20; ...
    (comp.lang.java.programmer)
  • Re: Simple script annimation problem usig swing
    ... To change this template, ... public void destroy{ ... public state cstate; ... public static int respawn = 20; ...
    (comp.lang.java.programmer)
  • Re: Replacing merge fields in headers/footers
    ... database, and a newly populated document can be requested at any time. ... to my way of thinking is to have a merge template ... I'm using exactly the same code to populate the fields in the ... >> private FileStream PopulateTemplateDocument(int theFileID, ...
    (microsoft.public.word.vba.general)
  • Re: implementation details
    ... double buffer data. ... via a call to some function with the template parameter being the ... the individual structs form a part of an overall struct. ... A separate function will retrieve the 'overall'. ...
    (comp.lang.cpp)