34 static unsigned long long T_MEASURE;
36 inline void START_T() {
40 inline double STOP_T() {
41 T_MEASURE =
rdtsc() - T_MEASURE;
44 return (
double)T_MEASURE;
78 virtual void clear(
bool destroy_entities=
false) = 0;
79 virtual const char*
Name() =0;
157 priority(p->Priority)
159 create_reverse_link();
174 delete_reverse_link();
184 create_reverse_link();
200 static const unsigned MAXSIZELIMIT = 1000000;
215 if(freed>MAXSIZELIMIT)
284 bool empty() {
return begin() == end(); }
297 while(evn!=end() && (*evn)->time > t) {
301 while(evn!=end() && (*evn)->time==t &&
302 (*evn)->priority < prio) {
325 Entity *e = first()->entity;
335 Entity *e = remove_first();
375 virtual void clear(
bool destroy=
false)
override;
380 Dprintf((
"CalendarList::create()"));
386 virtual const char*
Name()
override {
return "CalendarList"; }
390 Dprintf((
"CalendarList::CalendarList()"));
394 Dprintf((
"CalendarList::~CalendarList()"));
463 Entity *e = l.remove_first();
501 Dprintf((
"CalendarList::clear(destroy=%s)", destroy?
"true":
"false"));
568 return static_cast<int>(fmod(t/bucket_width, static_cast<double>(nbuckets)));
576 return t + 1.5*bucket_width;
579 double estimate_bucket_width();
592 virtual void clear(
bool destroy=
false)
override;
597 Dprintf((
"CalendarQueue::create()"));
604 virtual const char*
Name()
override {
return "CalendarQueue"; }
609 void Resize(
int grow=0);
610 void SearchMinTime(
double starttime);
615 void visualize(
const char *msg);
621 #define MAX_OP (Size()/2) 636 last_dequeue_time(-1.0),
637 sumdelta(0.0), ndelta(0)
639 Dprintf((
"CalendarQueue::CalendarQueue()"));
648 Dprintf((
"CalendarQueue::ScheduleAt(%s,%g)", e->
Name().c_str(),
t));
797 for (
int n__ =
nbuckets; n__ > 0; --n__) {
804 if (t < starttime)
SIMLIB_error(
"CalendarQueue implementation error in SearchMinTime");
838 Dprintf((
"Calendar bucket width estimation:"));
840 OP_MEASURE |= OP_ESTIMATE;
844 Dprintf((
" estm1: %g", bu_width));
846 SIMLIB_error(
"CalendarQueue:e1 bucketwidth < 1e-12*Time -- total loss of precision");
856 for(
int a__ = 0; a__<2; ++a__) {
861 for (
int n__ =
nbuckets; n__ > 0; --n__) {
866 if (t > bucket_top||t < last_time) {
872 double diff = t - last_time;
877 if(count>LIMIT)
break;
879 if(count>LIMIT)
break;
889 double avg = (last_time-
MinTime())/count;
890 Dprintf((
" estm2: avg=%g", avg));
891 double bu_width = MUL_PAR * avg;
893 SIMLIB_error(
"CalendarQueue:e2 bucketwidth < 1e-12*Time -- total loss of precision");
898 Dprintf((
" estm3: next tmpmin=%g", tmpmin));
925 OP_MEASURE |= OP_RESIZE;
929 bool bucket_width_changed =
false;
936 bucket_width_changed =
true;
959 if(oldnbuckets ==
nbuckets && !bucket_width_changed)
970 if (oldbuckets == NULL)
975 for (
unsigned n = 0; n < oldnbuckets; ++n) {
977 while(!oldbp.
empty()) {
987 delete [] oldbuckets;
999 OP_MEASURE |= OP_SWITCH2LIST;
1003 for (
unsigned n = 0; n <
nbuckets; ++n) {
1005 while(!oldbp.
empty()) {
1024 OP_MEASURE |= OP_SWITCH2CQ;
1040 double t0=(*i)->time;
1042 for(
unsigned n=0; i!=
list.
end() && n<100; ++i, ++n) {
1043 double t1=(*i)->time;
1044 if(t1==t0)
continue;
1049 double avg = (t0-
MinTime())/count;
1056 SIMLIB_warning(
"CalendarQueue:switchtocq bucketwidth<1e-12*Time = loss of precision");
1091 Dprintf((
"CalendarQueue::clear(%s)",destroy?
"true":
"false"));
1123 Dprintf((
"CalendarQueue::~CalendarQueue()"));
1139 for(
iterator i = begin(); i!=end(); ++i) {
1140 Print(
" [%03u]:", ++n );
1141 Print(
"\t %s", (*i)->entity->Name().c_str() );
1142 Print(
"\t at=%g", (*i)->time );
1146 Print(
" <empty>\n");
1151 Print(
"CalendarList:\n");
1159 Print(
"CalendarQueue:\n");
1161 for(
unsigned i=0; i<
nbuckets; i++) {
1162 Print(
" bucket#%03u:\n", i);
1172 Print(
"# CalendarQueue::visualize %s\n",msg);
1176 Print(
"# size=%u, nbuckets=%d, mintime=%g, operations=%u, bucket_width=%g\n",
1179 for(
unsigned b=0; b<
nbuckets; b++) {
1185 Print(
" %g", (*i)->time );
1206 #if 1 // choose default 1217 Dprintf((
"Calendar::delete_instance()"));
1227 typedef Calendar * (*create_fun_ptr_t)();
1228 std::map<string, create_fun_ptr_t> record;
1230 Register(create_fun_ptr_t f,
const char *name) {
1232 for(string::iterator i=n.begin(); i!=n.end(); ++i)
1233 *i = std::tolower(*i);
1238 for(string::iterator i=n.begin(); i!=n.end(); ++i)
1239 *i = std::tolower(*i);
1240 if(record.count(n)==0)
1242 create_fun_ptr_t f = record[n];
1254 if(Calendar::_instance)
1256 if(name==0 || std::strcmp(name,
"")==0 || std::strcmp(name,
"default")==0)
1258 else if(std::strcmp(name,
"list")==0)
1260 else if(std::strcmp(name,
"cq")==0)
1273 unsigned cal_cost_size;
1274 double cal_cost_time;
1276 const char * cal_cost_op;
1295 double ttt=STOP_T();
1298 cal_cost_time = ttt;
1299 cal_cost_flag = OP_MEASURE;
1300 cal_cost_op =
"enqueue";
1314 double ttt=STOP_T();
1317 cal_cost_time = ttt;
1318 cal_cost_flag = OP_MEASURE;
1319 cal_cost_op =
"delete";
1333 double ttt=STOP_T();
1336 cal_cost_time = ttt;
1337 cal_cost_flag = OP_MEASURE;
1338 cal_cost_op =
"dequeue";
1361 return GetEventNotice()->time;
void Resize(int grow=0)
Resize bucket array.
const double SIMLIB_MAXTIME
maximum time (1e30 works for float, too)
static bool instance_exists()
check if the instance exists
void insert(Entity *e, double t)
enqueue operation
void free(EventNotice *en)
free EventNotice, add to freelist for future allocation
void SIMLIB_error(const enum _ErrEnum N)
print error message and abort program
virtual void debug_print() override
for debugging only
friend void SetCalendar(const char *name)
choose calendar implementation default is list
CalendarListImplementation()
virtual const char * Name()=0
const unsigned MINBUCKETS
CQ implementation of calendar.
double time2bucket_top(double t)
Compute bucket top limit.
void clear(bool destroy)
remove all items
Priority_t Priority
priority of the entity (scheduling,queues)
~CalendarQueue()
Destroy calendar queue.
virtual ~Calendar()
clear is called in derived class dtr
allocate activation records fast
EventNotice * GetEventNotice()
virtual const char * Name() override
Entity * remove(Entity *e)
special dequeue operation for rescheduling
EventNoticeLinkBase * p
< bidirectional iterator
CalendarListImplementation BucketList
void Get(Entity *e)
remove selected entity activation record from calendar
virtual void ScheduleAt(Entity *p, double t) override
enqueue
virtual Entity * GetFirst() override
dequeue first
void delete_reverse_link()
delete link from entity to activation record
EventNotice * _evn
points to calendar item, iff scheduled
int Print(const char *fmt,...)
for Output methods, can be redirected
~ CalendarListImplementation()
EventNotice * operator*()
int time2bucket(double t)
Convert time to bucket number.
EventNotice * extract_first()
fast special operations for list swap (Dangerous!):
common interface for all calendar (PES) implementations
Implementation of class CalendarList interface is static - using global functions in SQS namespace...
virtual void debug_print() override
for debugging only
virtual void debug_print()=0
for debugging only
static EventNotice * Create(Entity *p, double t)
creates new EventNotice,
void SIMLIB_warning(const enum _ErrEnum N)
print warning message and continue
abstract base class for active entities (Process, Event) instances of derived classes provide Behavio...
void Set(Entity *e, double t)
set new values to existing (unlinked) record
EventNoticeLinkBase * succ
next object in list
static void delete_instance()
destroy single instance
virtual Entity * GetFirst() override
dequeue first entity
const double & Time
model time (is NOT the block)
static Calendar * instance()
create/get single instance (singleton)
void remove()
remove from calendar list
EventNotice(Entity *p, double t)
class simlib3::EventNoticeAllocator allocator
void SearchMinTime(double starttime)
compute new mintime
double ActivationTime()
get activation time of entity - iff scheduled it is here, because Entity has no knowledge of calend...
class CalendarListImplementation — sorted list
virtual void clear(bool destroy=false) override
remove all
void visualize(const char *msg)
CalendarQueue::visualize – output suitable for Gnuplot.
void switchtocq()
switch to calendar queue implementation
Entity::Priority_t priority
priority at the time of scheduling
void ScheduleAt(Entity *e, double t)
schedule entity e at given time t using scheduling priority from e
void clear()
clear: delete all free-list items
EventNoticeLinkBase l
head of circular list
iterator(EventNoticeLinkBase *pos)
double estimate_bucket_width()
compute new bucket width — EXPERIMENTAL
bool operator==(const ParameterVector &p1, const ParameterVector &p2)
static void Destroy(EventNotice *en)
delete EventNotice, if inserted in calendar remove it first
Entity * GetFirst()
remove entity with minimum activation time
double MinTime() const
time of activation of first item
CalendarListImplementation l
virtual void ScheduleAt(Entity *p, double t) override
enqueue
Internal header file for SIMLIB/C++.
class CalendarList — list implementation of calendar
const double & NextTime
next-event time
void insert_extracted(EventNotice *evn)
fast special enqueue operation
static CalendarQueue * create()
create calendar instance
static Calendar * _instance
pointer to single instance
Main SIMLIB/C++ interface.
Entity * entity
which entity is scheduled
virtual std::string Name() const
get object name
void SetMinTime(double t)
set cache for faster access
void debug_print()
print of calendar contents - FOR DEBUGGING ONLY
unsigned _size
number of scheduled items
bool Empty()
empty calendar predicate
virtual void clear(bool destroy=false) override
remove all
#define _SetTime(t, x)
macro for simple assignement to internal time variables
bool Idle()
entity activation is not scheduled in calendar
void switchtolist()
switch to list implementation
virtual void clear(bool destroy_entities=false)=0
remove all scheduled entities
EventNotice * alloc(Entity *p, double t)
EventNotice allocation or reuse from freelist.
iterator search(EventNotice *en)
search — linear search for insert position
SIMLIB_Phase_t SIMLIB_Phase
CalendarQueue()
Initialize calendar queue.
virtual Entity * Get(Entity *p) override
dequeue
virtual void ScheduleAt(Entity *e, double t)=0
enqueue
EntityPriority_t Priority_t
calendar item - PRIVATE for any implementation we use double-linked circular list ...
virtual const char * Name() override
virtual Entity * GetFirst()=0
dequeue first
static __inline__ unsigned long long rdtsc(void)
EventNoticeLinkBase * pred
previous object in list
virtual Entity * Get(Entity *p) override
dequeue
virtual Entity * Get(Entity *e)=0
dequeue
void SIMLIB_atexit(SIMLIB_atexit_function_t p)
void insert(EventNoticeLinkBase *p)
insert at position p
Entity * remove_first()
dequeue operation
double mintime
activation time of first event
double time
activation time of entity
void create_reverse_link()
create link from entity to activation record
void Clear()
remove all scheduled entities
static CalendarList * create()
create calendar instance