Listing 6 (main2.cpp)

// main2.cpp
// A demonstration of a database buffer
// made simpler by smart pointers.

#define DEBUG

#include "anyclass.hpp"

class BufferedDatabase
 {
  public:
    BufferedDatabase (void) {};
    ~BufferedDatabase (void);
    
    void getRecPtr (
       int recNum,
       RefCntPtr(anyClass)& ptr);
  
  private:
    enum {bfrSize=3};
    
    RefCntPtr(anyClass) bfr[bfrSize];
    
    // these functions would actually
    // read from the disk DB.
    // for now, we'll just pretend
    void getRecWithNew (
       int recNum,
       RefCntPtr(anyClass)& ptr);
    
    void putRec (
       RefCntPtr(anyClass)& ptr);
};

void BufferedDatabase::getRecPtr (
       int recNum,
       RefCntPtr(anyClass)& ptr)
  {
    // first, see if it is in the buffer
    
    for (int i = 0; i < bfrSize; ++i)
        if ( bfr[i]
           && (bfr[i]->intVal == recNum)
           )
          {
            ptr = bfr[i];
            return;
          };
    
    // if we made it to here, then it
    // is not in the buffer, so get it
    // from disk;
    
    RefCntPtr(anyClass) tmp;
    getRecWithNew (recNum, tmp);
    
    // return if not found
    if (0 == tmp)
      {
       ptr = 0;
       return;
      };
    
    // see if it can be inserted
    // into buffer
    for (i = 0; i < bfrSize; ++i)
       if (0 == bfr[i])
         {
          bfr[i] = tmp;
          ptr = tmp;
          return;
         };
         
    ptr = 0;
    
    // if it didn't return, then there
    // is no space - will have to find
    // some.
    for (i = 0; i < bfrSize; ++i)
      
      // reference count of 1 means the
      // only pointer to this object
      // is bfr[i]. Since nothing
      // outside this routine is pointing
      // to it, we can get rid of it.
      
        if (bfr[i]->refCnt() == 1)
          {
           putRec (bfr[i]);
           bfr[i] = tmp;
           ptr = tmp;
           return;
          };
    
    // if still didn't return,
    // out of space
    
    cout << "BUFFER FULL\n\n";
    // obviously, running out of space
    // is a bad thing - a real-world
    // scheme wouldn't use as array,
    // but some form of dynamic
    // allocation
  
  };

void BufferedDatabase::getRecWithNew (
       int recNum,
       RefCntPtr(anyClass)& ptr)
  {
    // would get record from database
    // again, we'll just fake it
    
    // pretend that records 1000
    // and above don't exist
    
    if (recNum >= 1000)
      {
       ptr = 0;
       return;
      };
    
    ptr = new anyClass;
    
    // pretend that it's
    // getting a record from disk
    ptr->intVal = recNum;
    ptr->string = "something";
    
    cout << "getting from disk - rec # "
        << ptr->intVal << "\n\n";
  };

void BufferedDatabase::putRec (
       RefCntPtr(anyClass)& ptr)
  {
    cout << "putting to disk - rec # "
        << ptr->intVal << "\n\n";
  };

BufferedDatabase::~BufferedDatabase(void)
  {
   for (int i = 0; i < bfrSize; ++i)
       if (bfr[i])
         {
          putRec (bfr[i]);
          bfr[i] = 0;
         };
  };

void main (void)
  {
   cout << "start of main\n\n";
   BufferedDatabase db;
   
   RefCntPtr(anyClass) ptrA, ptrB,
                    ptrC, ptrD;
  
   db.getRecPtr (1, ptrA);
   ptrA->show();
   
   db.getRecPtr (2, ptrA);
   db.getRecPtr (3, ptrA);
   db.getRecPtr (4, ptrA);
   
   db.getRecPtr (2, ptrA);
   db.getRecPtr (3, ptrB);
   db.getRecPtr (4, ptrC);
   db.getRecPtr (5, ptrD);
   if (!ptrD)
     cout << "getRecFailed\n\n";
   
   db.getRecPtr (1005, ptrD);
   ptrD->show();//an error
   
   cout << "end of main\n\n";
  };
// End of File