<!--
    Licensed to the Apache Software  Foundation (ASF) under one or more
    contributor  license agreements.  See  the NOTICE  file distributed
    with  this  work  for  additional information  regarding  copyright
    ownership.   The ASF  licenses this  file to  you under  the Apache
    License, Version  2.0 (the  License); you may  not use  this file
    except in  compliance with the License.   You may obtain  a copy of
    the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the  License is distributed on an  "AS IS" BASIS,
    WITHOUT  WARRANTIES OR CONDITIONS  OF ANY  KIND, either  express or
    implied.   See  the License  for  the  specific language  governing
    permissions and limitations under the License.

    Copyright 1999-2007 Rogue Wave Software, Inc.
-->

<HTML>
<HEAD>
<TITLE>Example Program: Event-Driven Simulation</TITLE>
<LINK REL=StyleSheet HREF="../rw.css" TYPE="text/css" TITLE="Apache stdcxx Stylesheet"></HEAD>
<BODY BGCOLOR=#FFFFFF>
<A HREF="11-2.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="12.html"><IMG SRC="images/bnext.gif" WIDTH=25 HEIGHT=21 ALT="Next file" BORDER=O></A><DIV CLASS="DOCUMENTNAME"><B>Apache C++ Standard Library User's Guide</B></DIV>
<H2>11.3 Example Program: Event-Driven Simulation</H2>
<A NAME="idx212"><!></A>
<A NAME="idx213"><!></A>
<P>An extended example will now illustrate one of the more common uses of a priority_queues, which is to support the construction of a simulation model. A <I>discrete event-driven simulation</I> is a popular simulation technique. Objects in the simulation model objects in the real world, and are programmed to react as much as possible as the real objects would react. A <B><I><A HREF="../stdlibref/priority-queue.html">priority_queue</A></I></B> is used to store a representation of <I>events</I> that are waiting to happen. This queue is stored in order, based on the time the event should occur, so the smallest element will always be the next event to be modeled. As an event occurs, it can spawn other events. These subsequent events are placed into the queue as well. Execution continues until all events have been processed.</P>
<BLOCKQUOTE><HR><B>
NOTE -- The complete version of the ice cream store simulation program is in icecream.cpp.
</B><HR></BLOCKQUOTE>
<P>Events can be represented as subclasses of a base class, which we call <B><I>event</I></B>. The base class simply records the time at which the event will take place. A pure virtual function named <SAMP>processEvent</SAMP> is invoked to execute the event:</P>

<UL><PRE>
class event {
public:
  // Construct sets time of event.
  event (unsigned int t) : time (t)
    { }

  // Execute event by invoking this method.
  virtual void processEvent () = 0;

  const unsigned int time;
};
</PRE></UL>
<A NAME="idx214"><!></A>
<P>The simulation queue needs to maintain a collection of different types of events, sometimes called a <I>heterogeneous</I> collection. Each different form of event is represented by a subclass of class <B><I>event</I></B>, but not all <B><I>event</I></B>s have the same exact type. For this reason the collection must store <I>pointers</I> to <B><I>event</I></B>s, instead of the events themselves.  Since the containers maintain pointers to values, not the values themselves, the programmer is responsible for managing the memory for the objects being manipulated.</P>
<P>Since comparison of pointers cannot be specialized on the basis of the pointer types, we must instead define a new comparison function for pointers to events. In the C++ Standard Library we do this by defining a new structure whose sole purpose is to define the function invocation <SAMP>operator()()</SAMP> in the appropriate fashion.   Since in this particular example we want to use the <B><I><A HREF="../stdlibref/priority-queue.html">priority_queue</A></I></B> to return the smallest element each time, rather than the largest, the order of the comparison is reversed, as follows:</P>

<UL><PRE>
struct eventComparator {
  bool operator() (const event * left, const event * right) const {
    return left-&gt;time &gt; right-&gt;time;
  }
};
</PRE></UL>
<BLOCKQUOTE><HR><B>
NOTE -- We use a priority queue as a structure for quickly discovering the smallest element in a sequence. If, instead, your problem requires the discovery of the largest element, there are various possibilities. One is to supply the inverse operator as either a template argument or the optional comparison function argument to the constructor. If you are defining the comparison argument as a function, as in the example problem, another solution is to simply invert the comparison test.
</B><HR></BLOCKQUOTE>
<P>We are now ready to define the class <B><I>simulation</I></B>, which provides the structure for the simulation activities. The class <B><I>simulation</I></B> provides two functions: the first is used to insert a new event into the queue, while the second runs the simulation. A data member is also provided to hold the current simulation <B><I>time</I></B>:</P>

<UL><PRE>
class simulation {
public:
  simulation () : time (0), eventQueue () 
    {}
  void run ();
  void  scheduleEvent (event * newEvent) {
    eventQueue.push (newEvent);
  }
  unsigned int time;
protected:
  std::priority_queue&lt;event*,
                      std::vector&lt;event *, std::allocator&lt;event*&gt; &gt;,
                      eventComparator&gt; eventQueue;
};
</PRE></UL>
<P>Notice the declaration of the <B><I><A HREF="../stdlibref/priority-queue.html">priority_queue</A></I></B> used to hold the pending <B><I>event</I></B>s. In this case we are using a <B><I><A HREF="../stdlibref/vector.html">vector</A></I></B> as the underlying container, but we could just as easily have used a <B><I><A HREF="../stdlibref/deque.html">deque</A></I></B>. </P>
<P>The heart of the simulation is the member function<SAMP> run()</SAMP>, which defines the event loop. This procedure makes use of three of the five <B><I><A HREF="../stdlibref/priority-queue.html">priority_queue</A></I></B> operations, namely <SAMP>top()</SAMP>, <SAMP>pop()</SAMP>, and <SAMP>empty().</SAMP> It is implemented as follows:</P>

<UL><PRE>
void simulation::run () {

  while (! eventQueue.empty ()) {

    event * nextEvent = eventQueue.top ();
    eventQueue.pop ();
    time = nextEvent-&gt;time;
    nextEvent-&gt;processEvent ();
    delete nextEvent;
  }
}
</PRE></UL>
<A NAME="idx215"><!></A>
<A NAME="1131"><H3>11.3.1 Example Program: An Ice Cream Store Simulation</H3></A>
<A NAME="idx216"><!></A>
<P>To illustrate the use of our simulation framework, this example program gives a simple simulation of an ice cream store. Such a simulation might be used, for example, to determine the optimal number of chairs that should be provided, based on assumptions such as the frequency with which customers arrive, the length of time they stay, and so on.</P>
<P>Our store simulation is based around a subclass of class <B><I>simulation</I></B>, defined as follows:</P>

<UL><PRE>
class storeSimulation : public simulation {
public:
  storeSimulation () : simulation (), freeChairs (35), profit (0.0)
    { }
  bool canSeat (unsigned int numberOfPeople);
  void order   (unsigned int numberOfScoops);
  void leave   (unsigned int numberOfPeople);
  // Data fields.
  unsigned int freeChairs;
  double       profit;  
} theSimulation;
</PRE></UL>
<P>There are three basic activities associated with the store: arrival, ordering and eating, and leaving. This is reflected not only in the three member functions defined in the <B><I>simulation</I></B> class, but in three separate subclasses of <B><I>event</I></B>.</P>
<P>The member functions associated with the store simply record the activities taking place, producing a log that can later be studied to evaluate the simulation.</P>

<UL><PRE>
bool storeSimulation::canSeat (unsigned int numberOfPeople) {
    
  std::cout &lt;&lt; "Time: " &lt;&lt; time;
  std::cout &lt;&lt; " group of " &lt;&lt; numberOfPeople &lt;&lt; " customers arrives";

  if (numberOfPeople &lt; freeChairs) {
    std::cout &lt;&lt; " is seated\n";
    freeChairs -= numberOfPeople;
    return true;
  }
  else {
    std::cout &lt;&lt; " no room, they leave\n";
    return false;
  }
}

void storeSimulation::order (unsigned int numberOfScoops) {
    
  std::cout &lt;&lt; "Time: " &lt;&lt; time &lt;&lt; " serviced order for "
            &lt;&lt; numberOfScoops &lt;&lt; '\n';
  profit += 0.35 * numberOfScoops;
}

void storeSimulation::leave (unsigned int numberOfPeople) {
    
  std::cout &lt;&lt; "Time: " &lt;&lt; time &lt;&lt; " group of size "
            &lt;&lt; numberOfPeople &lt;&lt; " leaves\n";
  freeChairs += numberOfPeople;
}
</PRE></UL>
<A NAME="idx217"><!></A>
<P>As we noted already, each activity is matched by a subclass of <B><I>event</I></B>.  Each subclass of <B><I>event</I></B> includes an integer data member, which represents the size of a group of customers. The arrival event occurs when a group enters. When executed, the arrival event creates and installs a new instance of the order event. The function <SAMP>randomInteger()</SAMP> is used to compute a random integer between 1 and the argument value (see <A HREF="2-2.html#225">Section&nbsp;2.2.5</A>).</P>

<UL><PRE>
class arriveEvent : public event {
public:
  arriveEvent (unsigned int t, unsigned int groupSize)
    : event (t), size (groupSize)
    { }
  virtual void processEvent ();
private:
  unsigned int size;
};

void arriveEvent::processEvent () {

  if (theSimulation.canSeat (size))
    theSimulation.scheduleEvent
      (new orderEvent (time + 1 + irand (4), size));
}
</PRE></UL>
<P>An order event similarly spawns a leave event:</P>

<UL><PRE>
class orderEvent : public event {
public:
  orderEvent (unsigned int t, unsigned int groupSize)
    : event (t), size (groupSize)
    { }
  virtual void processEvent ();
private:
  unsigned int size;
};

void orderEvent::processEvent () {

  // Each person orders some number of scoops.
  for (unsigned int i = 0; i &lt; size; i++)
    theSimulation.order (1 + irand (4));

  // Then we schedule the leave event.
  theSimulation.scheduleEvent
    (new leaveEvent (time + 1 + irand (10), size));
}

</PRE></UL>
<P>Finally, leave events free up chairs, but do not spawn any new events:</P>

<UL><PRE>
class leaveEvent : public event
{
public:
  leaveEvent (unsigned int t, unsigned int groupSize)
    : event (t), size (groupSize)
    { }
  virtual void processEvent ();
private:
  unsigned int size;
};

void leaveEvent::processEvent () {

  theSimulation.leave (size);
}
</PRE></UL>
<P>To run the simulation we simply create some number of initial events (say, 30 minutes worth), then invoke the <SAMP>run()</SAMP> member function:</P>

<UL><PRE>
int main () {

  std::cout &lt;&lt; "Ice Cream Store simulation from Chapter 9\n";

  // Load queue with some number of initial events.
  for (unsigned t = 0; t &lt; 20; t += irand (6)) {

    std::cout &lt;&lt; "pumping queue with event " &lt;&lt; t &lt;&lt; '\n';
    theSimulation.scheduleEvent (new arriveEvent (t, 1 + irand (4)));
  }

  // Run the simulation.
  theSimulation.run ();

  std::cout &lt;&lt; "Total profits " &lt;&lt; theSimulation.profit
            &lt;&lt; "\nEnd of ice cream store simulation\n";

  return 0;
}
</PRE></UL>

<BR>
<HR>
<A HREF="11-2.html"><IMG SRC="images/bprev.gif" WIDTH=20 HEIGHT=21 ALT="Previous file" BORDER=O></A><A HREF="noframes.html"><IMG SRC="images/btop.gif" WIDTH=56 HEIGHT=21 ALT="Top of Document" BORDER=O></A><A HREF="booktoc.html"><IMG SRC="images/btoc.gif" WIDTH=56 HEIGHT=21 ALT="Contents" BORDER=O></A><A HREF="tindex.html"><IMG SRC="images/bindex.gif" WIDTH=56 HEIGHT=21 ALT="Index page" BORDER=O></A><A HREF="12.html"><IMG SRC="images/bnext.gif" WIDTH=20 HEIGHT=21 ALT="Next file" BORDER=O></A>

<!-- Google Analytics tracking code -->
<script src="http://www.google-analytics.com/urchin.js" type="text/javascript">
</script>
<script type="text/javascript">
    _uacct = "UA-1775151-1";
    urchinTracker();
</script>
<!-- end of Google Analytics tracking code -->

</BODY>
</HTML>
