EventScheduler.hpp

Go to the documentation of this file.
00001 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
00002 //
00003 //        This file is part of E-Cell Simulation Environment package
00004 //
00005 //                Copyright (C) 1996-2005 Keio University
00006 //                Copyright (C) 2005 The Molecular Sciences Institute
00007 //
00008 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
00009 //
00010 //
00011 // E-Cell is free software; you can redistribute it and/or
00012 // modify it under the terms of the GNU General Public
00013 // License as published by the Free Software Foundation; either
00014 // version 2 of the License, or (at your option) any later version.
00015 // 
00016 // E-Cell is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00019 // See the GNU General Public License for more details.
00020 // 
00021 // You should have received a copy of the GNU General Public
00022 // License along with E-Cell -- see the file COPYING.
00023 // If not, write to the Free Software Foundation, Inc.,
00024 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00025 // 
00026 //END_HEADER
00027 //
00028 // written by Koichi Takahashi <shafi@e-cell.org>,
00029 // E-Cell Project.
00030 //
00031 
00032 #ifndef __EVENTSCHEDULER_HPP
00033 #define __EVENTSCHEDULER_HPP
00034 
00035 #include "libecs.hpp"
00036 #include "DynamicPriorityQueue.hpp"
00037 
00038 namespace libecs
00039 {
00040 
00041   /** @addtogroup model The Model.
00042 
00043       The model.
00044 
00045       @ingroup libecs
00046       @{ 
00047    */ 
00048 
00049   /** @file */
00050 
00051   DECLARE_CLASS( EventBase );
00052 
00053 
00054   /**
00055      EventBase
00056 
00057      A subclass must define three customization points;
00058     
00059      void fire()
00060      {
00061        (1) do what this event is supposed to do.
00062        (2) setTime( next scheduled time of this event );
00063      }
00064 
00065      void update( EventCref anEvent )
00066      {
00067        Given the last fired Event (anEvent) that this Event
00068        depends on,
00069 
00070        (1) recalculate scheduled time (if necessary).
00071        (2) setTime( new scheduled time ).
00072      }
00073 
00074      const bool isDependentOn( EventCref anEvent )
00075      {
00076        Return true if this Event must be updated when the
00077        given Event (anEvent) fired.  Otherwise return false;
00078      }
00079   */
00080 
00081   class EventBase
00082   {
00083 
00084   public:
00085 
00086     EventBase( TimeParam aTime )
00087       :
00088       theTime( aTime )
00089     {
00090       ; // do nothing
00091     }
00092 
00093     void setTime( TimeParam aTime )
00094     {
00095       theTime = aTime;
00096     }
00097 
00098     const Time getTime() const
00099     {
00100       return theTime;
00101     }
00102 
00103    
00104 
00105     const bool operator< ( EventBaseCref rhs ) const
00106     {
00107       if( getTime() < rhs.getTime() )
00108         {
00109           return true;
00110         }
00111       else
00112         {
00113           return false;
00114         }
00115     }
00116 
00117     const bool operator!= ( EventBaseCref rhs ) const
00118     {
00119       if( getTime() == rhs.getTime() )
00120         {
00121           return false;
00122         }
00123       else
00124         {
00125           return true;
00126         }
00127     }
00128 
00129 
00130     // dummy, because DynamicPriorityQueue requires this. better without.
00131     EventBase()
00132     {
00133       ; // do nothing
00134     }
00135 
00136 
00137   private:
00138 
00139     Time             theTime;
00140   };
00141 
00142 
00143   /**
00144      Event scheduler.
00145 
00146      This class works as a sequential
00147      event scheduler with a heap-tree based priority queue.
00148 
00149   */
00150 
00151   template <class Event_>
00152   class EventScheduler
00153   {
00154 
00155   public:
00156 
00157     DECLARE_TYPE( Event_, Event );
00158 
00159     DECLARE_TYPE( DynamicPriorityQueue<Event>, EventPriorityQueue );
00160 
00161     typedef typename DynamicPriorityQueue<Event>::Index EventIndex_;
00162     DECLARE_TYPE( EventIndex_, EventIndex );
00163 
00164     typedef std::vector<EventIndex> EventIndexVector;
00165     typedef std::vector<EventIndexVector> EventIndexVectorVector;
00166 
00167     //DECLARE_VECTOR( EventIndex, EventIndexVector );
00168     //DECLARE_VECTOR( EventIndexVector, EventIndexVectorVector );
00169 
00170 
00171     EventScheduler()
00172     {
00173       ; // do nothing
00174     }
00175 
00176     ~EventScheduler()
00177     {
00178       ; // do nothing
00179     }
00180 
00181 
00182     const EventIndex getSize() const
00183     {
00184       return theEventPriorityQueue.getSize();
00185     }
00186 
00187     EventCref getTopEvent() const
00188     {
00189       return theEventPriorityQueue.getTopItem();
00190     }
00191 
00192     EventRef getTopEvent()
00193     {
00194       return theEventPriorityQueue.getTopItem();
00195     }
00196 
00197     EventIndex getTopIndex()
00198     {
00199       return theEventPriorityQueue.getTopIndex();
00200     }
00201 
00202     EventCref getEvent( const EventIndex anIndex ) const
00203     {
00204       return theEventPriorityQueue.getItem( anIndex );
00205     }
00206 
00207     EventRef getEvent( const EventIndex anIndex )
00208     {
00209       return theEventPriorityQueue.getItem( anIndex );
00210     }
00211 
00212     void step()
00213     {
00214       EventRef aTopEvent( theEventPriorityQueue.getTopItem() );
00215       const Time aCurrentTime( aTopEvent.getTime() );
00216       const EventIndex aTopEventIndex( getTopIndex() );
00217 
00218       // fire top
00219       aTopEvent.fire();
00220       theEventPriorityQueue.moveDown( aTopEventIndex );
00221 
00222       // update dependent events
00223       const EventIndexVector&
00224         anEventIndexVector( theEventDependencyArray[ aTopEventIndex ] );
00225 
00226       for( typename EventIndexVector::const_iterator 
00227              i( anEventIndexVector.begin() );
00228            i != anEventIndexVector.end(); ++i )
00229         {
00230           const EventIndex anIndex( *i );
00231 
00232           updateEvent( anIndex, aCurrentTime );
00233         }
00234     }
00235 
00236     void updateAllEvents( TimeParam aCurrentTime )
00237     {
00238       const EventIndex aSize( getSize() );
00239       for( EventIndex anIndex( 0 ); anIndex != aSize; ++anIndex )
00240         {
00241           updateEvent( anIndex, aCurrentTime );
00242         }
00243     }
00244 
00245     void updateEvent( const EventIndex anIndex, TimeParam aCurrentTime )
00246     {
00247       EventRef anEvent( theEventPriorityQueue.getItem( anIndex ) );
00248       const Time anOldTime( anEvent.getTime() );
00249       anEvent.update( aCurrentTime );
00250       const Time aNewTime( anEvent.getTime() );
00251 
00252       // theEventPriorityQueue.move( anIndex );
00253       if( aNewTime >= anOldTime )
00254         {
00255           theEventPriorityQueue.moveDown( anIndex );
00256         }
00257       else
00258         {
00259           theEventPriorityQueue.moveUp( anIndex );
00260         }
00261     }
00262 
00263 
00264     void updateEventDependency();  // update all
00265 
00266     void updateEventDependency( const EventIndex anIndex );
00267     
00268     void clear()
00269     {
00270       theEventPriorityQueue.clear();
00271       theEventDependencyArray.clear();
00272     }
00273 
00274     const EventIndex addEvent( EventCref anEvent )
00275     {
00276       return theEventPriorityQueue.pushItem( anEvent );
00277     }
00278 
00279 
00280     // this is here for DiscreteEventStepper::log().
00281     // should be removed in future. 
00282     const EventIndexVector& getDependencyVector( const EventIndex anIndex )
00283     {
00284       return theEventDependencyArray[ anIndex ] ;
00285     }
00286 
00287   private:
00288 
00289     EventPriorityQueue       theEventPriorityQueue;
00290 
00291     EventIndexVectorVector   theEventDependencyArray;
00292 
00293   };
00294 
00295   
00296 
00297 
00298   template < class Event >
00299   void EventScheduler<Event>::updateEventDependency()
00300   {
00301     theEventDependencyArray.resize( theEventPriorityQueue.getSize() );
00302     
00303     for( EventIndex i1( 0 ); i1 != theEventPriorityQueue.getSize(); ++i1 )
00304       {
00305         updateEventDependency( i1 );
00306       }
00307   }
00308 
00309   template < class Event >
00310   void EventScheduler<Event>::
00311   updateEventDependency( const EventIndex i1 )
00312   {
00313     EventCref anEvent1( theEventPriorityQueue.getItem( i1 ) );
00314 
00315     EventIndexVector& anEventIndexVector( theEventDependencyArray[ i1 ] );
00316     anEventIndexVector.clear();
00317 
00318     for( EventIndex i2( 0 ); i2 < theEventPriorityQueue.getSize(); ++i2 )
00319       {
00320         if( i1 == i2 )
00321           {
00322             // don't include itself
00323             continue;
00324           }
00325         
00326         EventCref anEvent2( theEventPriorityQueue.getItem( i2 ) );
00327         
00328         if( anEvent2.isDependentOn( anEvent1 ) )
00329           {
00330             anEventIndexVector.push_back( i2 );
00331           }
00332       }
00333     
00334     std::sort( anEventIndexVector.begin(), anEventIndexVector.end() );
00335   }
00336 
00337 
00338 
00339 
00340 
00341   /*@}*/
00342 
00343 } // namespace libecs
00344 
00345 
00346 
00347 
00348 #endif /* __EVENTSCHEDULER_HPP */
00349 
00350 
00351 
00352 
00353 /*
00354   Do not modify
00355   $Author: shafi $
00356   $Revision: 2529 $
00357   $Date: 2005-11-19 10:36:40 +0100 (Sat, 19 Nov 2005) $
00358   $Locker$
00359 */
00360 

Generated on Fri Aug 31 18:32:07 2007 for E-CELL C++ libraries (libecs and libemc) 3.1.105 by  doxygen 1.5.3