1 #ifndef _adevs_model_h_ 2 #define _adevs_model_h_ 14 #define ADEVS_ERROR_CHECK(cond,model,msg) \ 16 std::ostringstream buf; \ 17 buf << __FILE__ << ":" << __LINE__ << ":" << model->name() << ":" << msg; \ 18 throw std::logic_error(buf.str()); \ 24 template <
typename DataType,
typename TimeType>
class Model;
25 template <
typename DataType,
typename TimeType>
class Simulator;
37 template <
typename DataType,
typename TimeType=Time>
69 virtual TimeType
now() = 0;
79 template <
typename DataType,
typename TimeType=Time>
83 Model():priority(adevs_inf<TimeType>()),heap_pos(0),
84 remove(
false),msgs(NULL),defer(NULL){}
101 virtual void fini(TimeType
now) = 0;
113 virtual TimeType update(
140 virtual std::pair<Model<DataType,TimeType>*,DataType>
142 return std::pair<Model<DataType,TimeType>*,DataType>(
this,x);
151 virtual std::string
name() {
return ""; }
171 if (msgs != NULL)
delete msgs;
172 if (defer != NULL )
delete defer;
176 priority = adevs_inf<TimeType>();
179 friend class Simulator<DataType,TimeType>;
183 std::vector<DataType> *msgs, *defer;
192 template <
typename DataType,
typename TimeType=Time>
200 Simulator(TimeType tStart = adevs_zero<TimeType>());
230 TimeType
now() {
return m_now; }
232 TimeType next_event_time()
const;
234 void exec_next_event();
236 void exec_until(TimeType t);
238 std::vector<std::vector<DataType>* > msg_lists;
239 std::vector<Model<DataType,TimeType>* > heap;
245 std::vector<DataType>* get_message_list();
246 void replace_message_list(std::vector<DataType>* msgs);
249 template <
typename DataType,
typename TimeType>
254 heap.push_back(NULL);
257 template <
typename DataType,
typename TimeType>
260 if (heap.size() == 1)
return adevs_inf<TimeType>();
261 return heap[1]->priority;
264 template <
typename DataType,
typename TimeType>
272 template <
typename DataType,
typename TimeType>
276 if (heap.size() == 1)
279 m_now = heap[1]->priority;
281 while ((heap.size() > 1) && (heap[1]->priority == m_now))
288 percolate_away(model);
289 replace_message_list(model->msgs);
290 replace_message_list(model->defer);
291 model->msgs = model->defer = NULL;
292 model->remove =
false;
299 if (model->msgs != NULL)
301 model->priority = model->
update(
this,*(model->msgs));
303 ADEVS_ERROR_CHECK(m_now < model->priority,model,
"update(x) <= now()")
307 model->priority = model->
update(
this);
309 ADEVS_ERROR_CHECK(m_now < model->priority,model,
"update() <= now()")
312 replace_message_list(model->msgs);
314 model->msgs = model->defer;
319 if (model->msgs != NULL || model->remove)
320 model->priority = m_now + adevs_epsilon<TimeType>();
321 assert(m_now < model->priority);
323 if (model->priority < adevs_inf<TimeType>())
324 percolate_down(model);
326 percolate_away(model);
331 template <
typename DataType,
typename TimeType>
335 TimeType priority = model->
init(
this);
336 ADEVS_ERROR_CHECK(m_now < priority,model,
"init() <= now()")
338 (model->msgs != NULL && model->priority == m_now+adevs_epsilon<TimeType>()) ||
339 model->heap_pos == 0,model,
"new model is already active")
340 if (model->msgs == NULL)
342 model->priority = priority;
343 if (model->priority < adevs_inf<TimeType>())
348 template <
typename DataType,
typename TimeType>
351 model->remove =
true;
352 model->priority = m_now + adevs_epsilon<TimeType>();
354 if (model->heap_pos == 0)
361 template <
typename DataType,
typename TimeType>
367 std::pair<Model<DataType,TimeType>*,DataType> r(dst->
relay(src,data));
369 while (r.first != dst && r.first != NULL)
372 send(dst,r.first,r.second);
374 r = dst->
relay(src,data);
377 if (r.first == NULL)
return;
378 assert(r.first == dst);
380 if (dst->priority == m_now)
382 if (dst->defer == NULL)
383 dst->defer = get_message_list();
384 dst->defer->push_back(r.second);
389 if (dst->msgs == NULL)
390 dst->msgs = get_message_list();
391 dst->msgs->push_back(r.second);
392 dst->priority = m_now + adevs_epsilon<TimeType>();
394 assert(dst->priority < adevs_inf<TimeType>());
395 if (dst->heap_pos == 0)
403 template <
typename DataType,
typename TimeType>
406 assert(model->priority < adevs_inf<TimeType>());
407 assert(heap[model->heap_pos] == model);
408 unsigned index = model->heap_pos;
411 while (heap[index/2] != NULL && model->priority < heap[index/2]->priority)
413 heap[index] = heap[index/2];
414 heap[index]->heap_pos = index;
418 heap[index]->heap_pos = index;
422 template <
typename DataType,
typename TimeType>
425 assert(heap[model->heap_pos] == model);
426 unsigned child, index = model->heap_pos;
427 for (; index*2 < heap.size(); index = child)
430 if (child+1 < heap.size() && heap[child+1]->priority < heap[child]->priority)
432 if (heap[child]->priority < model->priority)
434 heap[index] = heap[child];
435 heap[index]->heap_pos = index;
440 heap[index]->heap_pos = index;
441 assert(index != 0 && index < heap.size());
444 template <
typename DataType,
typename TimeType>
447 assert(model->heap_pos == 0);
448 model->heap_pos = heap.size();
449 heap.push_back(model);
453 template <
typename DataType,
typename TimeType>
458 move->heap_pos = model->heap_pos;
462 const unsigned parent = move->heap_pos/2;
463 if (heap[parent] != NULL &&
464 heap[move->heap_pos]->priority < heap[parent]->priority)
467 percolate_down(move);
469 model->priority = adevs_inf<TimeType>();
473 template <
typename DataType,
typename TimeType>
476 std::vector<DataType>* result;
477 if (msg_lists.empty())
478 return (result =
new std::vector<DataType>());
479 result = msg_lists.back();
480 msg_lists.pop_back();
484 template <
typename DataType,
typename TimeType>
486 std::vector<DataType>* msgs)
488 if (msgs == NULL)
return;
490 msg_lists.push_back(msgs);
493 template <
typename DataType,
typename TimeType>
496 for (
unsigned i = 0; i < msg_lists.size(); i++)
The simulator generates trajectories for its models.
Definition: adevs_base.h:25
void reset()
Reset simulation support to reuse the model in a new simulation context.
Definition: adevs_base.h:169
virtual void add(Model< DataType, TimeType > *model)=0
Add a model to the simulator.
void remove(Model< DataType, TimeType > *model)
Remove a model from the simulation context.
Definition: adevs_base.h:349
virtual ~SimEnv()
Destructor.
Definition: adevs_base.h:71
virtual std::pair< Model< DataType, TimeType > *, DataType > relay(Model< DataType, TimeType > *src, DataType x)
Relay a message to another model.
Definition: adevs_base.h:141
virtual ~Model()
Destructor.
Definition: adevs_base.h:153
~Simulator()
Destructor leaves all models intact.
Definition: adevs_base.h:494
void add(Model< DataType, TimeType > *model)
Add a model to the simulation context.
Definition: adevs_base.h:332
void exec_next_event()
Execute update() methods at the next event time.
Definition: adevs_base.h:273
virtual TimeType init(SimEnv< DataType, TimeType > *env)=0
Called when the model is added to the simulation.
Definition: adevs_base.h:21
virtual TimeType update(SimEnv< DataType, TimeType > *env, std::vector< DataType > &x)=0
Called to assign a new state to the model at now() when input is present.
Simulator(TimeType tStart=adevs_zero< TimeType >())
Constructor sets the simulation start time.
Definition: adevs_base.h:250
virtual std::string name()
Return a name for this model.
Definition: adevs_base.h:151
virtual void send(Model< DataType, TimeType > *src, Model< DataType, TimeType > *dst, DataType data)=0
Send a message to a model.
Interface to a simulation context for sending messages, getting the time, and adding or removing mode...
Definition: adevs_base.h:38
virtual void fini(TimeType now)=0
Called after the model has been removed from the simulation.
A model in the simulation.
Definition: adevs_base.h:24
void exec_until(TimeType t)
Advance until the simulation time until it equals the supplied time.
Definition: adevs_base.h:265
TimeType next_event_time() const
Returns the time of the next event.
Definition: adevs_base.h:258
void send(Model< DataType, TimeType > *src, Model< DataType, TimeType > *dst, DataType data)
Send a message to a model.
Definition: adevs_base.h:362
TimeType now()
Returns the current simulation time.
Definition: adevs_base.h:230
virtual TimeType now()=0
Get the current time.