SIMLIB/C++  3.07
waitunti.cc
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 //! \file waitunti.cc Process::WaitUntil implementation
3 //
4 // Copyright (c) 1991-2004 Petr Peringer
5 //
6 // This library is licensed under GNU Library GPL. See the file COPYING.
7 //
8 
9 //
10 // class WaitUntilList --- not good implementation
11 // (uses list of waiting processes, and checks conditions after each
12 // activated event)
13 // better implementation will use objects in WUexpressions
14 //
15 // 199808 updated: uses standard list<>
16 
17 ////////////////////////////////////////////////////////////////////////////
18 // interface
19 //
20 #include "simlib.h"
21 #include "internal.h"
22 #include <list>
23 
24 
25 ////////////////////////////////////////////////////////////////////////////
26 // implementation
27 //
28 
29 namespace simlib3 {
30 
32 
33 ////////////////////////////////////////////////////////////////////////////
34 // class WaitUntilList --- singleton
35 //
37  typedef std::list<Process *> container_t;
38  container_t l;
39  static WaitUntilList *instance; // unique list
40  public:
41  typedef container_t::iterator iterator;
42  static iterator begin() { return instance->l.begin(); }
43  static iterator end() { return instance->l.end(); }
44  static bool empty() { return instance->l.empty(); }
45  static void InsertCurrent(); // insert current process into list
46  static void GetCurrent(); // get current process
47  static void WU_hook(); // active: next process in WUlist or 0
48  static void Remove(Process *p) { // find and remove p
49  Dprintf(("WaitUntil::Remove(Process#%ld)", p->id()));
50  instance->l.remove(p); // should be in list
51  }
52  static void clear(); // empty
53  static void create() { // create single instance
54  if(instance==0) instance = new WaitUntilList;
55  else SIMLIB_internal_error(); // called twice
57  SIMLIB_atexit(destroy); // last SIMLIB module cleanup calls this
58  }
59  static void destroy() { // destroy single instance
60  clear(); // remove all contents
61  delete instance;
62  instance = 0;
63  }
64  private:
65  WaitUntilList() { Dprintf(("WaitUntilList::WaitUntilList()")); }
66  ~WaitUntilList() { Dprintf(("WaitUntilList::~WaitUntilList()")); }
67  // destructor never called ###???
68  static iterator current;
69 #ifndef NDEBUG
70  friend void WU_print();
71 #endif
72 };
73 
74 #ifndef NDEBUG
75  void WU_print() {
76  _Print("WaitUntilList:\n");
77  if(WaitUntilList::instance == 0) { _Print("none\n"); return; }
79  for( int n=0 ; i!=WaitUntilList::end() ; ++i, ++n )
80  _Print(" [%d] Process#%ld\n", n, (*i)->id() );
81  }
82 #endif
83 
84 // WaitUntilList single instance
87 
88 ////////////////////////////////////////////////////////////////////////////
89 static bool flag = false; // valid iterator in WUList
90 ////////////////////////////////////////////////////////////////////////////
91 // main WUlist interface function
92 void WaitUntilList::WU_hook() { // get ptr to next process in WUlist or 0
93  Dprintf(("WaitUntilList::WU_hook"));
94  // PRECONDITION: WUList not empty
95  if(WaitUntilList::empty()) // this should never happen
97 
98  if(!flag) { // start processing, (first call or after remove)
99  current = WaitUntilList::begin(); // reset to first process
100  flag = true;
101  // loop_count++;
102  // if(loop_count>LIMIT) error("waituntil-loop");
103  SIMLIB_Current = *current; // always OK
104  return;
105  }
106  ++current; // next waiting process
107  if( current != WaitUntilList::end() ) { // not end
109  return;
110  }
111  flag = false; // no next process --- end of WaitUntil processing
112  // loop_count = 0;
113  SIMLIB_Current = 0; // not needed ???###
114  return;
115 }
116 
117 ////////////////////////////////////////////////////////////////////////////
118 // Process::
119 ////////////////////////////////////////////////////////////////////////////
120 // _WaitUntil --- wait to condition
121 // this is hidden by macro WaitUntil(b), useable in Process::Behavior
122 //
123 bool Process::_WaitUntil(bool test)
124 {
125  Dprintf(("Process#%ld._WaitUntil(%s)", id(), test?"true":"false" ));
126  if(test) { // true --- end of wait
127  WaitUntilList::GetCurrent(); // ***** remove from WUList
128  _wait_until = false; // not in WUlist
129  return false; // continue checking WaitUntil condition
130  } else { // false --- wait
131  if (SIMLIB_Current != this) SIMLIB_internal_error();
132  WaitUntilList::InsertCurrent(); // ***** insert into WUList
133  _wait_until = true; // is in WUlist
134  Passivate(); // deactivation = wait
135  return true; // repeat test (after activation)
136  }
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////
140 // _WaitUntilRemove() --- remove process from WUlist (called from destructor)
141 //
143  if(_wait_until)
144  WaitUntilList::Remove(this);
145  _wait_until = false; // is not in WUlist
146 }
147 
148 
149 ////////////////////////////////////////////////////////////////////////////
150 // InsertCurrent --- insert current process reference into WUlist
151 // (only called from Process::_WaitUntil)
152 //
154 {
155  if(flag) return; // is in WUlist
156  //CONDITION: current process is not in WUlist
157  Process *e = static_cast<Process*>(SIMLIB_Current); // TODO: dynamic_cast ?
158  Dprintf(("WaitUntilList.Insert(Process#%ld)", e->id()));
159  if(instance==0)
160  create(); // create singleton instance
161  if(empty()) // it was empty (FIXME: why not at creation time?)
162  INSTALL_HOOK(WUget_next, WaitUntilList::WU_hook); // install hook
163  iterator pos;
164  for( pos = begin(); // find place from beginning
165  pos != end() && (*pos)->Priority >= e->Priority; // higher first
166  ++pos ) { /*empty*/ }
167  instance->l.insert(pos,e); // insert at position
168  //e->_wait_until = true; // mark process as inserted
169 }
170 
171 ////////////////////////////////////////////////////////////////////////////
172 // GetCurrent --- get selected process from WUlist
173 // (called from Process::* )
174 //
176 {
177  if(!flag) return; // process is not in WUlist
178  //PRECONDITION: WUlist is initialized, not empty
179  Process *p = *current;
180  Dprintf(("WaitUntilList.Get(); // \"Process#%ld\" ", p->id()));
181  instance->l.erase(current); // remove item pointed by iterator (fast)
182  if(empty())
183  INSTALL_HOOK(WUget_next, 0); // uninstall hook if last item removed
184  flag = false; // iterator invalid, start from beginning
185 }
186 
187 ////////////////////////////////////////////////////////////////////////////
188 // clear --- remove all records (called from Init())
189 //
191 {
192  if(instance==0) return;
193  // remove all processes in WaitUntilList
194  // we can do this, because all processes in list are passivated
195  iterator i=begin();
196  while(i!=end()) { // destroy all processes in WUlist
197  Process *p = *i;
198  ++i;
199  p->_WaitUntilRemove(); // unmark and remove process
200  if( p->isAllocated() ) delete p; // the same behavior as Calendar###???
201  }
202  if(!instance->l.empty())
203  SIMLIB_internal_error(); // for sure
204  INSTALL_HOOK(WUget_next, 0); // uninstall hook if empty
205 }
206 
207 
208 } // end
209 
static void create()
Definition: waitunti.cc:53
int _Print(const char *fmt,...)
output of messages to stdout, too
Definition: print.cc:68
static bool empty()
Definition: waitunti.cc:44
Priority_t Priority
priority of the entity (scheduling,queues)
Definition: simlib.h:399
static iterator current
Definition: waitunti.cc:68
static void InsertCurrent()
Definition: waitunti.cc:153
static void destroy()
Definition: waitunti.cc:59
bool isAllocated() const
Definition: simlib.h:318
static WaitUntilList * instance
Definition: waitunti.cc:39
Implementation of class CalendarList interface is static - using global functions in SQS namespace...
Definition: algloop.cc:32
static void clear()
Definition: waitunti.cc:190
static void Remove(Process *p)
Definition: waitunti.cc:48
static iterator end()
Definition: waitunti.cc:43
static bool flag
Definition: waitunti.cc:89
static void WU_hook()
Definition: waitunti.cc:92
void Passivate(Entity *e)
passivate entity e
Definition: simlib.h:432
#define SIMLIB_internal_error()
Definition: internal.h:167
Internal header file for SIMLIB/C++.
void _WaitUntilRemove()
Definition: waitunti.cc:142
static void GetCurrent()
Definition: waitunti.cc:175
Main SIMLIB/C++ interface.
#define INSTALL_HOOK(name, function)
Definition: internal.h:255
SIMLIB_IMPLEMENTATION
Definition: algloop.cc:34
Entity * SIMLIB_Current
Definition: run.cc:53
friend void WU_print()
Definition: waitunti.cc:75
unsigned long id() const
Definition: simlib.h:396
std::list< Process * > container_t
Definition: waitunti.cc:37
container_t::iterator iterator
Definition: waitunti.cc:41
static iterator begin()
Definition: waitunti.cc:42
Abstract base class for all simulation processesProcess behavior is specified by Behavior method and ...
Definition: simlib.h:440
#define Dprintf(f)
Definition: internal.h:100
void SIMLIB_atexit(SIMLIB_atexit_function_t p)
Definition: atexit.cc:26
bool _WaitUntil(bool test)
wait for condition (slow!)
Definition: waitunti.cc:123