-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimtime.h
141 lines (119 loc) · 3.79 KB
/
simtime.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#ifndef SIM_TIME_H
#define SIM_TIME_H
#include <iostream>
#include <set>
struct SimEvent
{
enum EventType
{
Error = 0,
GroupChange,
Callback
};
EventType _type;
double _timestamp;
public:
SimEvent( EventType type, double t );
virtual ~SimEvent();
inline EventType type() const {
return _type;
}
};
/** An implementation operator< for the multiset<SimEvent*>.
* It specifies an order that is based only on the timestamp. All other
* information in the SimEvent or its child class is ignored where
* temporal ordering is concerned.
*/
struct SimEventCmp
{
inline bool operator()( SimEvent* const & l, SimEvent* const & r ) const
{
return ( l->_timestamp < r->_timestamp );
}
};
/** This class implements time in this discrete event simulation.
* As in all discrete event simulation, simulated time passes in jumps between
* retrieval of events from an event queue, while the time that is required for
* computing the simulation is zero simulated time.
*/
class SimTime
{
/* Discrete event simulators tend to implement their event queues using a stable
* tree. Conveniently, the multiset in STL is exactly such a thing. Insert a
* value A and the STL multiset will store it in a tree in such a way that
* for all B with B<A, B is located left in the tree, while all with B>A are
* stored right in the tree. The order for A==B is undefined, just like in
* typical discrete event simulators.
*
* The question is: what is the operator<? It is simulation time, and it is
* stored in every SimEvent object. The SimEvent contains more information but
* that is ignored for ordering.
*/
typedef std::multiset<SimEvent*,SimEventCmp> Queue;
typedef std::multiset<SimEvent*,SimEventCmp>::iterator Queue_it;
public:
/** Put a SimEvent into the global event queue
*/
static void insert( SimEvent* ev );
/** Get the next event from the global event queue. If that object has a
* timestamp higher than the current simulation time, set the current simulation
* time to that timestamp.
*/
static SimEvent* get( );
/** Return the current simulation time.
*/
static double Now( );
/** Reset the simulation time to 0. Called once after a partial simulation
* was run to create the initial state.
*/
static void reset( );
/** Set an absolute time for ending the simulation
*/
static void setDeadline( double d );
static void dump( std::ostream& ostr );
private:
static Queue _q;
static double _now;
static double* _deadline;
};
/** This is the most frequently used event.
* It encodes the time when the given node changes group membership.
* These values are read from the .ljt that is input to the simulation.
*/
class EvGroupChange : public SimEvent
{
public:
EvGroupChange( double ts, int node, int oldgroup, int newgroup )
: SimEvent( GroupChange, ts )
, _node( node )
, _oldgroup( oldgroup )
, _newgroup( newgroup )
{
}
void extractInfo( int& node, int& oldgroup, int& newgroup ) const
{
node = _node;
oldgroup = _oldgroup;
newgroup = _newgroup;
}
int newGroup() const { return _newgroup; }
int oldGroup() const { return _oldgroup; }
int node() const { return _node; }
private:
int _node;
int _oldgroup;
int _newgroup;
};
/** All other kinds of events that must be handled in the simulation.
* This class is obviously abstract and must be implemented for the
* different algorithms if necessary.
*/
class EvCallback : public SimEvent
{
public:
EvCallback( double ts )
: SimEvent( Callback, ts )
{ }
virtual void callme( ) = 0;
};
#endif /* SIM_TIME_H */