[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ns] Time's up!



Ok, so much for the pop quiz. The subtle bug in all of the Scheduler
derived classes is that the base constructor isn't specified and at
least in my case, this lack of specification keeps the Scheduler()
constructor from being called.

While this may be classified as a GCC bug, good taste demands good
coding style, like specifying base ctors, virtual dtors, copy ctor,
default ctor, assignment operator, and such. For the prurient, I'm
using gcc version 2.95.2 19991024 on FreeBSD 4.2-STABLE.

I ran across this bug when my Application and Agent derived classes
tried to schedule events before the simulator started but much much
later than when '$ns use-scheduler Heap' was called. Scheduler::instance_
pointed to something totally bogotic and what it pointed to had a
NULL virtual table (clue!).

Here are the relevant patches to scheduler.h and scheduler.cc. Hope
this helps the community at large. And I've just noticed that I didn't
patch RealTimeScheduler... but I think I can safely save this as an
exercise to the reader... :-)


-scooter

Index: scheduler.h
===================================================================
RCS file: /work/repo/scottm/ns/scheduler.h,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -u -u -r1.1.1.2 -r1.2
--- scheduler.h	2000/11/28 20:45:08	1.1.1.2
+++ scheduler.h	2001/01/18 00:28:45	1.2
@@ -85,7 +85,10 @@
 	void dumpq();	// for debug: remove + print remaining events
 	void dispatch(Event*);	// execute an event
 	void dispatch(Event*, double);	// exec event, set clock_
+
 	Scheduler();
+	virtual ~Scheduler();
+
 	int command(int argc, const char*const* argv);
 	double clock_;
 	int halted_;
@@ -95,7 +98,9 @@
 
 class ListScheduler : public Scheduler {
 public:
-	inline ListScheduler() : queue_(0) {}
+	ListScheduler();
+	virtual ~ListScheduler();
+
 	virtual void cancel(Event*);
 	virtual void insert(Event*);
 	virtual Event* deque();
@@ -108,7 +113,9 @@
 
 class HeapScheduler : public Scheduler {
 public:
-	inline HeapScheduler() { hp_ = new Heap; } 
+	HeapScheduler();
+	virtual ~HeapScheduler();
+
 	virtual void cancel(Event* e) {
 		if (e->uid_ <= 0)
 			return;
Index: scheduler.cc
===================================================================
RCS file: /work/repo/scottm/ns/scheduler.cc,v
retrieving revision 1.1.1.2
retrieving revision 1.6
diff -u -u -r1.1.1.2 -r1.6
--- scheduler.cc	2000/11/28 20:45:08	1.1.1.2
+++ scheduler.cc	2001/01/18 00:28:45	1.6
@@ -49,7 +49,7 @@
 #include "mem-trace.h"
 #endif
 
-Scheduler* Scheduler::instance_;
+Scheduler* Scheduler::instance_ = NULL;
 int Scheduler::uid_ = 1;
 
 // class AtEvent : public Event {
@@ -59,8 +59,15 @@
 
 Scheduler::Scheduler() : clock_(SCHED_START), halted_(0)
 {
+	if (instance_ == NULL)
+		instance_ = this;
 }
 
+Scheduler::~Scheduler()
+{
+	instance_ = NULL;
+}
+
 /*
  * Schedule an event delay time units into the future.
  * The event will be dispatched to the specified handler.
@@ -158,7 +165,7 @@
 int Scheduler::command(int argc, const char*const* argv)
 {
 	Tcl& tcl = Tcl::instance();
-	if (instance_ == 0)
+	if (instance_ == NULL)
 		instance_ = this;
 	if (argc == 2) {
 		if (strcmp(argv[1], "run") == 0) {
@@ -262,10 +269,19 @@
 public:
 	ListSchedulerClass() : TclClass("Scheduler/List") {}
 	TclObject* create(int /* argc */, const char*const* /* argv */) {
 		return (new ListScheduler);
 	}
 } class_list_sched;
 
+ListScheduler::ListScheduler() : 
+  Scheduler(),
+  queue_(0)
+{
+}
+
+ListScheduler::~ListScheduler()
+{
+}
+
 void ListScheduler::insert(Event* e)
 {
 	double t = e->time_;
@@ -501,10 +518,21 @@
 public:
 	HeapSchedulerClass() : TclClass("Scheduler/Heap") {}
 	TclObject* create(int /* argc */, const char*const* /* argv */) {
 		return (new HeapScheduler);
 	}
 } class_heap_sched;
 
+
+HeapScheduler::HeapScheduler() :
+  Scheduler()
+{
+  hp_ = new Heap;
+} 
+
+HeapScheduler::~HeapScheduler()
+{
+  delete hp_;
+}
+
 Event* HeapScheduler::lookup(int uid)
 {
 	Event* e;
@@ -539,11 +568,13 @@
 public:
 	CalendarSchedulerClass() : TclClass("Scheduler/Calendar") {}
 	TclObject* create(int /* argc */, const char*const* /* argv */) {
-		return (new CalendarScheduler);
+		return (_NEW CalendarScheduler);
 	}
 } class_calendar_sched;
 
-CalendarScheduler::CalendarScheduler() {
+CalendarScheduler::CalendarScheduler() :
+	Scheduler()
+{
 	reinit(2, 1.0, 0.0);
 	resizeenabled_ = 1;
 	max_ = 0.0;
@@ -564,7 +595,8 @@
 	 */
 	if (e->time_ > max_) {
 		max_ = e->time_;
-		if (e->time_ * oneonwidth_ > ULONG_MAX) {
+
+		if (e->time_ * oneonwidth_ > UINT_MAX) {
 			resize(nbuckets_);
 		}
 	}