34static unsigned long long T_MEASURE;
36inline void START_T() {
40inline 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;
297 while(evn!=
end() && (*evn)->time >
t) {
301 while(evn!=
end() && (*evn)->time==
t &&
302 (*evn)->priority < prio) {
339 ~ CalendarListImplementation() {
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()"));
501 Dprintf((
"CalendarList::clear(destroy=%s)", destroy?
"true":
"false"));
592 virtual void clear(
bool destroy=
false)
override;
597 Dprintf((
"CalendarQueue::create()"));
604 virtual const char*
Name()
override {
return "CalendarQueue"; }
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");
856for(
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()"));
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 );
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);
1236 Calendar *create(
const char *name) {
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];
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)
1273unsigned cal_cost_size;
1274double cal_cost_time;
1276const char * cal_cost_op;
1295 double ttt=STOP_T();
1299cal_cost_flag = OP_MEASURE;
1300cal_cost_op =
"enqueue";
1314 double ttt=STOP_T();
1318cal_cost_flag = OP_MEASURE;
1319cal_cost_op =
"delete";
1333 double ttt=STOP_T();
1337cal_cost_flag = OP_MEASURE;
1338cal_cost_op =
"dequeue";
EventNotice * operator*()
bool operator!=(iterator q)
bool operator==(iterator q)
EventNoticeLinkBase * p
< bidirectional iterator
iterator(EventNoticeLinkBase *pos)
class CalendarListImplementation — sorted list
Entity * remove(Entity *e)
special dequeue operation for rescheduling
EventNotice * extract_first()
fast special operations for list swap (Dangerous!):
EventNoticeLinkBase l
head of circular list
CalendarListImplementation()
void debug_print()
print of calendar contents - FOR DEBUGGING ONLY
void insert(Entity *e, double t)
enqueue operation
Entity * remove_first()
dequeue operation
void insert_extracted(EventNotice *evn)
fast special enqueue operation
iterator search(EventNotice *en)
search — linear search for insert position
void clear(bool destroy)
remove all items
class CalendarList — list implementation of calendar
virtual const char * Name() override
CalendarListImplementation l
virtual Entity * GetFirst() override
dequeue first entity
virtual void clear(bool destroy=false) override
remove all
virtual void debug_print() override
for debugging only
virtual void ScheduleAt(Entity *p, double t) override
enqueue
virtual Entity * Get(Entity *p) override
dequeue
static CalendarList * create()
create calendar instance
CQ implementation of calendar.
virtual void debug_print() override
for debugging only
CalendarQueue()
Initialize calendar queue.
virtual void ScheduleAt(Entity *p, double t) override
enqueue
~CalendarQueue()
Destroy calendar queue.
void SearchMinTime(double starttime)
compute new mintime
double time2bucket_top(double t)
Compute bucket top limit.
virtual const char * Name() override
CalendarListImplementation BucketList
void switchtocq()
switch to calendar queue implementation
void visualize(const char *msg)
CalendarQueue::visualize – output suitable for Gnuplot.
void Resize(int grow=0)
Resize bucket array.
double estimate_bucket_width()
compute new bucket width — EXPERIMENTAL
int time2bucket(double t)
Convert time to bucket number.
static CalendarQueue * create()
create calendar instance
virtual void clear(bool destroy=false) override
remove all
virtual Entity * Get(Entity *p) override
dequeue
virtual Entity * GetFirst() override
dequeue first
void switchtolist()
switch to list implementation
common interface for all calendar (PES) implementations
static bool instance_exists()
check if the instance exists
virtual void debug_print()=0
for debugging only
static Calendar * instance()
create/get single instance (singleton)
virtual const char * Name()=0
static void delete_instance()
destroy single instance
virtual Entity * GetFirst()=0
dequeue first
virtual void ScheduleAt(Entity *e, double t)=0
enqueue
static Calendar * _instance
pointer to single instance
unsigned _size
number of scheduled items
double mintime
activation time of first event
virtual Entity * Get(Entity *e)=0
dequeue
double MinTime() const
time of activation of first item
void SetMinTime(double t)
set cache for faster access
virtual void clear(bool destroy_entities=false)=0
remove all scheduled entities
friend void SetCalendar(const char *name)
choose calendar implementation default is list
virtual ~Calendar()
clear is called in derived class dtr
abstract base class for active entities (Process, Event) instances of derived classes provide Behavio...
EventNotice * GetEventNotice()
EntityPriority_t Priority_t
bool Idle()
entity activation is not scheduled in calendar
EventNotice * _evn
points to calendar item, iff scheduled
Priority_t Priority
priority of the entity (scheduling,queues)
double ActivationTime()
get activation time of entity - iff scheduled it is here, because Entity has no knowledge of calend...
allocate activation records fast
static const unsigned MAXSIZELIMIT
EventNotice * alloc(Entity *p, double t)
EventNotice allocation or reuse from freelist.
void clear()
clear: delete all free-list items
void free(EventNotice *en)
free EventNotice, add to freelist for future allocation
virtual std::string Name() const
get object name
Internal header file for SIMLIB/C++.
#define _SetTime(t, x)
macro for simple assignement to internal time variables
void Get(Entity *e)
remove selected entity activation record from calendar
Entity * GetFirst()
remove entity with minimum activation time
void ScheduleAt(Entity *e, double t)
schedule entity e at given time t using scheduling priority from e
void Clear()
remove all scheduled entities
bool Empty()
empty calendar predicate
Implementation of class CalendarList interface is static - using global functions in SQS namespace.
const double & Time
model time (is NOT the block)
const double & NextTime
next-event time
void SIMLIB_error(const enum _ErrEnum N)
print error message and abort program
class simlib3::EventNoticeAllocator allocator
void SetCalendar(const char *name)
choose calendar implementation default is list
void SIMLIB_atexit(SIMLIB_atexit_function_t p)
const unsigned MINBUCKETS
void SIMLIB_warning(const enum _ErrEnum N)
print warning message and continue
int Print(const char *fmt,...)
for Output methods, can be redirected
SIMLIB_Phase_t SIMLIB_Phase
const double SIMLIB_MAXTIME
maximum time (1e30 works for float, too)
static __inline__ unsigned long long rdtsc(void)
Main SIMLIB/C++ interface.
calendar item - PRIVATE for any implementation we use double-linked circular list
void insert(EventNoticeLinkBase *p)
insert at position p
EventNoticeLinkBase * pred
previous object in list
void remove()
remove from calendar list
EventNoticeLinkBase * succ
next object in list
static void Destroy(EventNotice *en)
delete EventNotice, if inserted in calendar remove it first
Entity::Priority_t priority
priority at the time of scheduling
void delete_reverse_link()
delete link from entity to activation record
double time
activation time of entity
void create_reverse_link()
create link from entity to activation record
EventNotice & operator=(const EventNotice &)
void Set(Entity *e, double t)
set new values to existing (unlinked) record
Entity * entity
which entity is scheduled
EventNotice(const EventNotice &)
EventNotice(Entity *p, double t)
static EventNotice * Create(Entity *p, double t)
creates new EventNotice,