The Complete Resource for All Web Builders
home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
[an error occurred while processing this directive]
Previous Table of Contents Next


The Throw member function, as said before, performs stack unwinding; that is, it empties the stack by recurrent pop operations, each of these removing the last element from the stack until the stack is empty:

 void CallChain::Throw(const string& excep)
{
  while (!st.empty())
  {
    if (! HandlerExists(excep))
      ExitCurrentScope();
    else
      break; // a handler for the current exception was found
  }
}

The HandlerExists member function looks for an appropriate handler for the thrown exception. Because a full-blown exception handling mechanism is not implemented, the member function always returns false. (If it returned true, it would mean that the current exception was caught and handled, so there was no need to unwind the stack.)

 bool CallChain::HandlerExists(const string& excep)
{
  return false;
}

ExitCurrentScope performs a forced function exit. It terminates the current function by pooping it from the stack. But before a function is popped from the stack, take its name by calling the stack::top member function. Top() returns a reference to the element at the highest position in the stack (that is, the one pushed latest). size() is another member function that returns the number of elements currently stored in a stack. size() is used to display the increasing number of functions pushed on the stack, and during stack unwinding, it is used to display the decreasing number of elements.

void CallChain::ExitCurrentScope()
{
 string func = st.top();
 st.pop();
 cout<<”popped “ << func <<”; total “<< st.size() <<endl;
}

Now let’s look at MAIN.CPP. First, include the header file callchain.h that contains the declaration of class CallChain, as shown earlier.

#include “callchain.h”

The first statement in main declares a variable of type status and initializes it to success.

status stat = success;

An object of type CallChain is instantiated with a name chain.

CallChain chain;

chain simulates function calls. As you remember, one function was already called by the constructor, main. Now call another function named func1 from main and check the returned status.

stat = chain.Call(“func1”); // call another function from main
if (stat != failure)

Because func1 did not throw an exception, as the status returned from Call indicates, you can now call another function from func1

{
 stat = chain.Call(“bad_func”); //now call thrower
}

As you might guess from its name, bad_func threw an exception, as the returned status indicates. Because you have no handler for the thrown exception, you have to perform stack unwinding. This is done by calling the member function Throw:

chain.Throw(“disaster!”); //unwind stack

Comments

The STL stack container is generic. That is, it applies to any data type. This example used it with string for the sake of brevity; however, you can use it to model a LIFO with built-in types, objects, pointers, and so on.

7.5 Prevent automatic reallocation of a container?

Problem

I’m using a container that has to meet strict performance demands. In peak times, it can store as many as thousands of objects within minutes. However, the default reallocation scheme is unsatisfactory because my container has to reallocate itself frequently. The reallocation process imposes significant runtime overhead: the existing elements have to be copied to a new memory location. Copying implies an invocation of every element’s destructor as well as a reconstruction every element in its new location. Is there a way to optimize my container’s performance?

Technique

The memory allocation scheme of STL containers has to address two conflicting demands. On the one hand, a container should not pre-allocate large amounts of memory—it might impair system performance. On the other hand, it is inefficient to let a container reallocate memory whenever it stores a few more elements. The allocation strategy has to walk a thin line. However, in cases in which you can estimate in advance how many elements the container will have to store, you can force it to pre-allocate sufficient amount of memory and the recurrent reallocation process will be avoided.

Imagine a mail server of some Internet service provider. The server is almost idle at 4:00 AM in the morning. However, at 9:00 AM it has to transfer thousands of emails every minute. The incoming emails are first stored in a vector before they are routed to other mail servers across the Web. Letting our vector reallocate itself, little by little, with every few dozen emails is a recipe for a traffic bottleneck. Fortunately, you know in advance that 9:00–17:00 are peak hours, so you can avoid reallocation by calling the member function vector::reserve(). Reserve(n) ensures that its container reserves sufficient free memory for at least at least n more elements.

Steps

1.  Change to your base source directory and create a new subdirectory named PRE_ALLOC.
2.  Start your source code editor and type the following code into a file named MAILSERVER.H.
#include <vector>
using namespace std;

struct message { char text[1000];}; //a simplified representation
				    //of an email message

class MailServer {

public:

  bool RushHour() const;
  bool MoreMessages() const;
  message& GetNewMsg() const;
};
3.  Save MAILSERVER.H. Create a new file with the name MAILSERVER.CPP and type the following code into it:
#include <iostream>
#include “mailserver.h”
using namespace std;

bool MailServer::RushHour() const // is the current time
				  // considered peak-time?
{
 bool rush = true;
 return rush;
}

bool MailServer::MoreMessages() const //are there more incoming
				      //messages?
{
  bool more = true;
  return more;
}

message& MailServer::GetNewMsg() const // store an incoming
				       // message
{
  static message msg; //static object is instantiated only once
  return msg;
}


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.