[Avida-cvs] [avida-svn] r503 - in development/source: analyze main tools

brysonda@myxo.css.msu.edu brysonda at myxo.css.msu.edu
Sat Mar 11 20:27:38 PST 2006


Author: brysonda
Date: 2006-03-11 23:27:38 -0500 (Sat, 11 Mar 2006)
New Revision: 503

Modified:
   development/source/analyze/cAnalyzeJobQueue.cc
   development/source/analyze/cAnalyzeJobQueue.h
   development/source/main/cEnvironment.cc
   development/source/main/cInstSet.h
   development/source/main/cWorld.h
   development/source/tools/cRandom.cc
   development/source/tools/cRandom.h
   development/source/tools/tList.h
Log:
Successful first step in multithreaded Analyze mode.  Landscape Pre-Gen works!

- Added Thread-Save cRandom (cRandomMT)
- Fixed pthread_mutexes so that they are actually initialized and function
- Fixed cTaskContext double memory leak

Caveat: this preliminary implementation substitutes the World objects cRandom with cRandomMT.  This essentially bottlenecks all threads and will also slow down standard runs with unnecessary locking overhead.  This will be fixed.

Modified: development/source/analyze/cAnalyzeJobQueue.cc
===================================================================
--- development/source/analyze/cAnalyzeJobQueue.cc	2006-03-11 18:06:56 UTC (rev 502)
+++ development/source/analyze/cAnalyzeJobQueue.cc	2006-03-12 04:27:38 UTC (rev 503)
@@ -16,6 +16,7 @@
 {
   cAnalyzeJob* job;
   while (job = m_queue.Pop()) delete job;
+  pthread_mutex_destroy(&m_mutex);
 }
 
 void cAnalyzeJobQueue::Execute()

Modified: development/source/analyze/cAnalyzeJobQueue.h
===================================================================
--- development/source/analyze/cAnalyzeJobQueue.h	2006-03-11 18:06:56 UTC (rev 502)
+++ development/source/analyze/cAnalyzeJobQueue.h	2006-03-12 04:27:38 UTC (rev 503)
@@ -35,7 +35,7 @@
   cAnalyzeJobQueue& operator=(const cAnalyzeJobQueue&); // @not_implemented
   
 public:
-  cAnalyzeJobQueue(cWorld* world) : m_world(world) { ; }
+  cAnalyzeJobQueue(cWorld* world) : m_world(world) { pthread_mutex_init(&m_mutex, NULL); }
   ~cAnalyzeJobQueue();
 
   void AddJob(cAnalyzeJob* job) { m_queue.PushRear(job); } // @DMB - warning: this method is NOT thread safe

Modified: development/source/main/cEnvironment.cc
===================================================================
--- development/source/main/cEnvironment.cc	2006-03-11 18:06:56 UTC (rev 502)
+++ development/source/main/cEnvironment.cc	2006-03-12 04:27:38 UTC (rev 503)
@@ -29,87 +29,87 @@
 
 
 bool cEnvironment::ParseSetting(cString entry, cString & var_name,
-				cString & var_value, const cString & var_type)
+                                cString & var_value, const cString & var_type)
 {
   // Make sure we have an actual entry to parse.
   if (entry.GetSize() == 0) {
     cerr << "Error: Empty setting to parse in " << var_type << endl;
     return false;
   }
-
+  
   // Collect the values...
   var_name = entry.Pop('=');
   var_value = entry;
-
+  
   // Make sure we have both a name and a value...
   if (var_name.GetSize() == 0) {
     cerr << "Error: No variable povided to set to '" << var_value
-	 << "' in " << var_type << endl;
+    << "' in " << var_type << endl;
     return false;
   }
-
+  
   if (var_value.GetSize() == 0) {
     cerr << "Error: No value given for '" << var_name
-	 << "' in " << var_type << endl;
+    << "' in " << var_type << endl;
     return false;
   }
-
+  
   // Make the names case insensitive.
   var_name.ToLower();
-
+  
   return true;
 }
 
 bool cEnvironment::AssertInputInt(const cString & input,
-				  const cString & name,
-				  const cString & type)
+                                  const cString & name,
+                                  const cString & type)
 {
   if (input.IsNumeric() == false) {
     cerr << "Error: In " << type << "," << name << " set to non-integer."
-	 << endl;
+    << endl;
     return false;
   }
   return true;
 }
 
 bool cEnvironment::AssertInputDouble(const cString & input,
-				     const cString & name,
-				     const cString & type)
+                                     const cString & name,
+                                     const cString & type)
 {
   if (input.IsNumber() == false) {
     cerr << "Error: In " << type << "," << name << " set to non-number."
-	 << endl;
+    << endl;
     return false;
   }
   return true;
 }
 
 bool cEnvironment::AssertInputBool(const cString & input,
-				  const cString & name,
-				  const cString & type)
+                                   const cString & name,
+                                   const cString & type)
 {
   if (input.IsNumber() == false) {
     cerr << "Error: In " << type << "," << name << " set to non-number."
-	 << endl;
+    << endl;
     return false;
   }
   int value = input.AsInt();
   if ((value != 1) && (value != 0))  {
     cerr << "Error: In " << type << "," << name << " set to non-bool."
-	 << endl;
+    << endl;
     return false;
   }
   return true;
 }
 
 bool cEnvironment::AssertInputValid(void * input,
-				    const cString & name,
-				    const cString & type,
-				    const cString & value)
+                                    const cString & name,
+                                    const cString & type,
+                                    const cString & value)
 {
   if (input == NULL) {
     cerr << "Error: In " << type << ", '" << name << "' setting of '"
-	 << value << "' not found." << endl;
+    << value << "' not found." << endl;
     return false;
   }
   return true;
@@ -120,7 +120,7 @@
 bool cEnvironment::LoadReactionProcess(cReaction * reaction, cString desc)
 {
   cReactionProcess * new_process = reaction->AddProcess();
-
+  
   // Loop through all entries in description.
   while (desc.GetSize() > 0) {
     // Entries are divided by colons.
@@ -128,15 +128,15 @@
     cString var_name;
     cString var_value;
     const cString var_type = cStringUtil::Stringf("reaction '%s' process", static_cast<const char*>(reaction->GetName()));
-
+    
     // Parse this entry.
     if (!ParseSetting(var_entry, var_name, var_value, var_type)) return false;
-
+    
     // Now that we know we have a variable name and its value, set it!
     if (var_name == "resource") {
       cResource * test_resource = resource_lib.GetResource(var_value);
       if (!AssertInputValid(test_resource, "resource", var_type, var_value)) {
-	return false;
+        return false;
       }
       new_process->SetResource(test_resource);
     }
@@ -149,9 +149,9 @@
       else if (var_value=="mult") new_process->SetType(nReaction::PROCTYPE_MULT);
       else if (var_value=="pow") new_process->SetType(nReaction::PROCTYPE_POW);
       else {
-	cerr << "Unknown reaction process type '" << var_value
-	     << "' found in '" << reaction->GetName() << "'." << endl;
-	return false;
+        cerr << "Unknown reaction process type '" << var_value
+        << "' found in '" << reaction->GetName() << "'." << endl;
+        return false;
       }
     }
     else if (var_name == "max") {
@@ -171,7 +171,7 @@
     else if (var_name == "product") {
       cResource * test_resource = resource_lib.GetResource(var_value);
       if (!AssertInputValid(test_resource, "product", var_type, var_value)) {
-	return false;
+        return false;
       }
       new_process->SetProduct(test_resource);
     }
@@ -184,40 +184,40 @@
     }
     else if (var_name == "lethal") {
       if (!AssertInputBool(var_value, "lethal", var_type)) 
-	return false;
+        return false;
       new_process->SetLethal(var_value.AsInt());
     }
     else if (var_name == "detect") {
       cResource * test_resource = resource_lib.GetResource(var_value);
       if (!AssertInputValid(test_resource, "product", var_type, var_value)) {
-	return false;
+        return false;
       }
       new_process->SetDetect(test_resource);
     }
     else if (var_name == "threshold") {
       if (!AssertInputDouble(var_value, "threshold", var_type))
-	return false;
+        return false;
       new_process->SetDetectionThreshold(var_value.AsDouble());
     }
     else if (var_name == "detectionerror") {
       if (!AssertInputDouble(var_value, "detectionerror", var_type)) 
-	return false;
+        return false;
       new_process->SetDetectionError(var_value.AsDouble());
     }
     else {
       cerr << "Error: Unknown process variable '" << var_name
-	   << "' in reaction '" << reaction->GetName() << "'" << endl;
+      << "' in reaction '" << reaction->GetName() << "'" << endl;
       return false;
     }
   }
-
+  
   return true;
 }
 
 bool cEnvironment::LoadReactionRequisite(cReaction * reaction, cString desc)
 {
   cReactionRequisite * new_requisite = reaction->AddRequisite();
-
+  
   // Loop through all entries in description.
   while (desc.GetSize() > 0) {
     // Entries are divided by colons.
@@ -225,22 +225,22 @@
     cString var_name;
     cString var_value;
     const cString var_type = cStringUtil::Stringf("reaction '%s' requisite", static_cast<const char*>(reaction->GetName()));
-
+    
     // Parse this entry.
     if (!ParseSetting(var_entry, var_name, var_value, var_type)) return false;
-
+    
     // Now that we know we have a variable name and its value, set it!
     if (var_name == "reaction") {
       cReaction * test_reaction = reaction_lib.GetReaction(var_value);
       if (!AssertInputValid(test_reaction, "reaction", var_type, var_value)) {
-	return false;
+        return false;
       }
       new_requisite->AddReaction(test_reaction);
     }
     else if (var_name == "noreaction") {
       cReaction * test_reaction = reaction_lib.GetReaction(var_value);
       if (!AssertInputValid(test_reaction,"noreaction",var_type, var_value)) {
-	return false;
+        return false;
       }
       new_requisite->AddNoReaction(test_reaction);
     }
@@ -254,11 +254,11 @@
     }
     else {
       cerr << "Error: Unknown requisite variable '" << var_name
-	   << "' in reaction '" << reaction->GetName() << "'" << endl;
+      << "' in reaction '" << reaction->GetName() << "'" << endl;
       return false;
     }
   }
-
+  
   return true;
 }
 
@@ -269,115 +269,115 @@
     cerr << "Warning: Resource line with no resources listed." << endl;
     return false;
   }
-
+  
   while (desc.GetSize() > 0) {
     cString cur_resource = desc.PopWord();
     const cString name = cur_resource.Pop(':');
     cResource * new_resource = resource_lib.AddResource(name);
-
+    
     while (cur_resource.GetSize() != 0) {
       cString var_entry = cur_resource.Pop(':');
       cString var_name;
       cString var_value;
       const cString var_type = cStringUtil::Stringf("resource '%s'", static_cast<const char*>(name));
-
+      
       // Parse this entry.
       if (!ParseSetting(var_entry, var_name, var_value, var_type)) {
-	return false;
+        return false;
       }
-
+      
       if (var_name == "inflow") {
-	if (!AssertInputDouble(var_value, "inflow", var_type)) return false;
-	new_resource->SetInflow( var_value.AsDouble() );
+        if (!AssertInputDouble(var_value, "inflow", var_type)) return false;
+        new_resource->SetInflow( var_value.AsDouble() );
       }
       else if (var_name == "outflow") {
-	if (!AssertInputDouble(var_value, "outflow", var_type)) return false;
-	new_resource->SetOutflow( var_value.AsDouble() );
+        if (!AssertInputDouble(var_value, "outflow", var_type)) return false;
+        new_resource->SetOutflow( var_value.AsDouble() );
       }
       else if (var_name == "initial") {
-	if (!AssertInputDouble(var_value, "initial", var_type)) return false;
-	new_resource->SetInitial( var_value.AsDouble() );
+        if (!AssertInputDouble(var_value, "initial", var_type)) return false;
+        new_resource->SetInitial( var_value.AsDouble() );
       }
       else if (var_name == "geometry") {
-	if (!new_resource->SetGeometry( var_value )) {
+        if (!new_resource->SetGeometry( var_value )) {
           cerr << "Error: In " << var_type << "," << var_value << 
-	          " unknown geometry" << endl;
+          " unknown geometry" << endl;
           return false;
         }
       }
       else if (var_name == "inflowx1" || var_name == "inflowx") {
-	if (!AssertInputInt(var_value, "inflowX1", var_type)) return false;
-	new_resource->SetInflowX1( var_value.AsInt() );
+        if (!AssertInputInt(var_value, "inflowX1", var_type)) return false;
+        new_resource->SetInflowX1( var_value.AsInt() );
       }
       else if (var_name == "inflowx2") {
-	if (!AssertInputInt(var_value, "inflowX2", var_type)) return false;
-	new_resource->SetInflowX2( var_value.AsInt() );
+        if (!AssertInputInt(var_value, "inflowX2", var_type)) return false;
+        new_resource->SetInflowX2( var_value.AsInt() );
       }
       else if (var_name == "inflowy1" || var_name == "inflowy") {
-	if (!AssertInputInt(var_value, "inflowY1", var_type)) return false;
-	new_resource->SetInflowY1( var_value.AsInt() );
+        if (!AssertInputInt(var_value, "inflowY1", var_type)) return false;
+        new_resource->SetInflowY1( var_value.AsInt() );
       }
       else if (var_name == "inflowy2") {
-	if (!AssertInputInt(var_value, "inflowY2", var_type)) return false;
-	new_resource->SetInflowY2( var_value.AsInt() );
+        if (!AssertInputInt(var_value, "inflowY2", var_type)) return false;
+        new_resource->SetInflowY2( var_value.AsInt() );
       }
       else if (var_name == "outflowx1" || var_name == "outflowx") {
-	if (!AssertInputInt(var_value, "outflowX1", var_type)) return false;
-	new_resource->SetOutflowX1( var_value.AsInt() );
+        if (!AssertInputInt(var_value, "outflowX1", var_type)) return false;
+        new_resource->SetOutflowX1( var_value.AsInt() );
       }
       else if (var_name == "outflowx2") {
-	if (!AssertInputInt(var_value, "outflowX2", var_type)) return false;
-	new_resource->SetOutflowX2( var_value.AsInt() );
+        if (!AssertInputInt(var_value, "outflowX2", var_type)) return false;
+        new_resource->SetOutflowX2( var_value.AsInt() );
       }
       else if (var_name == "outflowy1" || var_name == "outflowy") {
-	if (!AssertInputInt(var_value, "outflowY1", var_type)) return false;
-	new_resource->SetOutflowY1( var_value.AsInt() );
+        if (!AssertInputInt(var_value, "outflowY1", var_type)) return false;
+        new_resource->SetOutflowY1( var_value.AsInt() );
       }
       else if (var_name == "outflowy2") {
-	if (!AssertInputInt(var_value, "outflowY2", var_type)) return false;
-	new_resource->SetOutflowY2( var_value.AsInt() );
+        if (!AssertInputInt(var_value, "outflowY2", var_type)) return false;
+        new_resource->SetOutflowY2( var_value.AsInt() );
       }
       else if (var_name == "xdiffuse") {
-	if (!AssertInputDouble(var_value, "xdiffuse", var_type)) return false;
-	new_resource->SetXDiffuse( var_value.AsDouble() );
+        if (!AssertInputDouble(var_value, "xdiffuse", var_type)) return false;
+        new_resource->SetXDiffuse( var_value.AsDouble() );
       }
       else if (var_name == "xgravity") {
-	if (!AssertInputDouble(var_value, "xgravity", var_type)) return false;
-	new_resource->SetXGravity( var_value.AsDouble() );
+        if (!AssertInputDouble(var_value, "xgravity", var_type)) return false;
+        new_resource->SetXGravity( var_value.AsDouble() );
       }
       else if (var_name == "ydiffuse") {
-	if (!AssertInputDouble(var_value, "ydiffuse", var_type)) return false;
-	new_resource->SetYDiffuse( var_value.AsDouble() );
+        if (!AssertInputDouble(var_value, "ydiffuse", var_type)) return false;
+        new_resource->SetYDiffuse( var_value.AsDouble() );
       }
       else if (var_name == "ygravity") {
-	if (!AssertInputDouble(var_value, "ygravity", var_type)) return false;
-	new_resource->SetYGravity( var_value.AsDouble() );
+        if (!AssertInputDouble(var_value, "ygravity", var_type)) return false;
+        new_resource->SetYGravity( var_value.AsDouble() );
       }
       else {
-	cerr << "Error: Unknown variable '" << var_name
-	     << "' in resource '" << name << "'" << endl;
-	return false;
+        cerr << "Error: Unknown variable '" << var_name
+        << "' in resource '" << name << "'" << endl;
+        return false;
       }
     }
-
+    
     // If there are valid values for X/Y1's but not for X/Y2's assume that 
     // the user is interested only in one point and set the X/Y2's to the
     // same value as 
-
+    
     if (new_resource->GetInflowX1()>-99 && new_resource->GetInflowX2()==-99){
-         new_resource->SetInflowX2(new_resource->GetInflowX1());
+      new_resource->SetInflowX2(new_resource->GetInflowX1());
     }
     if (new_resource->GetInflowY1()>-99 && new_resource->GetInflowY2()==-99){
-         new_resource->SetInflowY2(new_resource->GetInflowY1());
+      new_resource->SetInflowY2(new_resource->GetInflowY1());
     }
     if (new_resource->GetOutflowX1()>-99 && new_resource->GetOutflowX2()==-99) {
-         new_resource->SetOutflowX2(new_resource->GetOutflowX1());
+      new_resource->SetOutflowX2(new_resource->GetOutflowX1());
     }
     if (new_resource->GetOutflowY1()>-99 && new_resource->GetOutflowY2()==-99) {
-         new_resource->SetOutflowY2(new_resource->GetOutflowY1());
+      new_resource->SetOutflowY2(new_resource->GetOutflowY1());
     }
   }
-
+  
   return true;
 }
 
@@ -388,26 +388,26 @@
     cerr << "Error: Each reaction must include a name and trigger." << endl;
     return false;
   }
-
+  
   // Load in the reaction name
   const cString name = desc.PopWord();
   cReaction * new_reaction = reaction_lib.AddReaction(name);
-
+  
   // If only a name was present, assume this reaction is a pre-declaration.
   if (desc.GetSize() == 0) {
     return true;
   }
-
+  
   // Make sure this reaction hasn't already been loaded with a different
   // definition.
   if (new_reaction->GetTask() != NULL) {
     cerr << "Error: Re-defining reaction '" << name << "'." << endl;
     return false;
   }
-
+  
   // Finish loading in this reaction.
   const cString trigger = desc.PopWord();
-
+  
   // Load the task trigger
   cTaskEntry * cur_task = task_lib.AddTask(trigger);
   if (cur_task == NULL) {
@@ -415,23 +415,23 @@
     return false;
   }
   new_reaction->SetTask(cur_task);      // Attack task to reaction.
-
+  
   while (desc.GetSize()) {
     cString desc_entry = desc.PopWord();      // Get the next argument
     cString entry_type = desc_entry.Pop(':'); // Determine argument type
     entry_type.ToLower();                     // Make case insensitive.
-
+    
     // Determine the type of each argument and process it.
     if (entry_type == "process") {
       if (LoadReactionProcess(new_reaction, desc_entry) == false) {
-	cerr << "...failed in loading reaction-process..." << endl;
-	return false;
+        cerr << "...failed in loading reaction-process..." << endl;
+        return false;
       }
     }
     else if (entry_type == "requisite") {
       if (LoadReactionRequisite(new_reaction, desc_entry) == false) {
-	cerr << "...failed in loading reaction-requisite..." << endl;
-	return false;
+        cerr << "...failed in loading reaction-requisite..." << endl;
+        return false;
       }
     }
     else {
@@ -441,7 +441,7 @@
       return false;
     }
   }
-
+  
   return true;
 }
 
@@ -452,18 +452,18 @@
     cerr << "Error: Each mutation must include a name, trigger, scope, type, and rate." << endl;
     return false;
   }
-
+  
   // Load in the mutation info
   const cString name = desc.PopWord().ToLower();
   const cString trigger = desc.PopWord().ToLower();
   const cString scope = desc.PopWord().ToLower();
   const cString type = desc.PopWord().ToLower();
   const double rate = desc.PopWord().AsDouble();
-
+  
   int trig_id = -1;
   int scope_id = -1;
   int type_id = -1;
-
+  
   if (trigger == "none") trig_id = nMutation::TRIGGER_NONE;
   else if (trigger == "update") trig_id = nMutation::TRIGGER_UPDATE;
   else if (trigger == "divide") trig_id = nMutation::TRIGGER_DIVIDE;
@@ -475,7 +475,7 @@
     cerr << "Error: Unknown mutation trigger '" << trigger << "'." << endl;
     return false;
   }
-
+  
   if (scope == "genome") scope_id = nMutation::SCOPE_GENOME;
   else if (scope == "local") scope_id = nMutation::SCOPE_LOCAL;
   else if (scope == "prop") scope_id = nMutation::SCOPE_PROP;
@@ -485,7 +485,7 @@
     cerr << "Error: Unknown mutation scope '" << scope << "'." << endl;
     return false;
   }
-
+  
   if (type == "point") type_id = nMutation::TYPE_POINT;
   else if (type == "insert") type_id = nMutation::TYPE_INSERT;
   else if (type == "delete") type_id = nMutation::TYPE_DELETE;
@@ -497,48 +497,48 @@
     cerr << "Error: Unknown mutation type '" << type << "'." << endl;
     return false;
   }
-
+  
   // Lets do a few checks for legal combinations...
   if (trig_id == nMutation::TRIGGER_NONE) {
     cerr << "Warning: Mutations with trigger 'none' will never occur." << endl;
   }
-
+  
   if (scope_id == nMutation::SCOPE_LOCAL || scope_id == nMutation::SCOPE_PROP) {
     if (trig_id == nMutation::TRIGGER_DIVIDE) {
       cerr << "Error: Offspring after divide have no " << scope
-	   << " for mutations." << endl;
+      << " for mutations." << endl;
       return false;
     }
     if (trig_id == nMutation::TRIGGER_UPDATE ||
-	trig_id == nMutation::TRIGGER_PARENT) {
+        trig_id == nMutation::TRIGGER_PARENT) {
       cerr << "Warning: Mutation trigger " << trigger
-	   << "has no natural positions; IP used." << endl;
+      << "has no natural positions; IP used." << endl;
     }
   }
   else {  // Genome-wide scope
     if (type_id == nMutation::TYPE_HEAD_INC ||
-	type_id == nMutation::TYPE_HEAD_DEC ||
-	type_id == nMutation::TYPE_TEMP) {
+        type_id == nMutation::TYPE_HEAD_DEC ||
+        type_id == nMutation::TYPE_TEMP) {
       cerr << "Error: " << scope << " scope not compatible with type "
-	   << type << "." << endl;
+      << type << "." << endl;
       return false;
     }
   }
-
+  
   if (type_id == nMutation::TYPE_TEMP) {
     if (trig_id == nMutation::TRIGGER_UPDATE ||
-	trig_id == nMutation::TRIGGER_DIVIDE ||
-	trig_id == nMutation::TRIGGER_PARENT ||
-	trig_id == nMutation::TRIGGER_WRITE) {
+        trig_id == nMutation::TRIGGER_DIVIDE ||
+        trig_id == nMutation::TRIGGER_PARENT ||
+        trig_id == nMutation::TRIGGER_WRITE) {
       cerr << "Error: " << trigger << " trigger not meaningful with type "
-	   << type << "." << endl;
+      << type << "." << endl;
       return false;
     }
   }
-
+  
   // If we made it this far, it should be safe to build the mutation.
   mutation_lib.AddMutation(name, trig_id, scope_id, type_id, rate);
-
+  
   return true;
 }
 
@@ -546,15 +546,15 @@
 {
   cString item_type = desc.PopWord(); 
   item_type.ToUpper();
-
+  
   cString item_name = desc.PopWord();
-
+  
   cString item_active = desc.PopWord();
   item_active.ToUpper();
-
+  
   bool new_active = true;
   if (item_active == "0" || item_active == "FALSE") new_active = false;
-
+  
   if (item_type == "REACTION") {
     cReaction * cur_reaction = reaction_lib.GetReaction(item_name);
     if (cur_reaction == NULL) {
@@ -568,7 +568,7 @@
     cerr << "Error: Cannot deactivate items of type " << item_type << endl;
     return false;
   }
-
+  
   return true;
 }
 
@@ -576,7 +576,7 @@
 {
   cString type = line.PopWord();      // Determine type of this entry.
   type.ToUpper();                     // Make type case insensitive.
-
+  
   bool load_ok = true;
   if (type == "RESOURCE") load_ok = LoadResource(line);
   else if (type == "REACTION") load_ok = LoadReaction(line);
@@ -591,7 +591,7 @@
     cerr << "...failed in loading '" << type << "'..." << endl;
     return false;
   }
-
+  
   return true;
 }
 
@@ -602,26 +602,26 @@
     cerr << "Error: Failed to load environment '" << filename << "'." << endl;
     return false;
   }
-
+  
   infile.Load();
   infile.Close();
   infile.Compress();
-
+  
   for (int line_id = 0; line_id < infile.GetNumLines(); line_id++) {
     // Load the next line from the file.
     bool load_ok = LoadLine(infile.GetLine(line_id));
     if (load_ok == false) return false;
   }
-
+  
   // Make sure that all pre-declared reactions have been loaded correctly.
   for (int i = 0; i < reaction_lib.GetSize(); i++) {
     if (reaction_lib.GetReaction(i)->GetTask() == NULL) {
       cerr << "Error: Pre-declared reaction '"
-        << reaction_lib.GetReaction(i)->GetName() << "' never defined." << endl;
+      << reaction_lib.GetReaction(i)->GetName() << "' never defined." << endl;
       return false;
     }
   }
-
+  
   return true;
 }
 
@@ -629,12 +629,12 @@
 void cEnvironment::SetupInputs( tArray<int> & input_array ) const
 {
   input_array.Resize(3);
-
+  
   // Set the top 8 bits of the input buffer...
   input_array[0] = 15 << 24;  // 00001111
   input_array[1] = 51 << 24;  // 00110011
   input_array[2] = 85 << 24;  // 01010101
-
+  
   // And randomize the rest...
   for (int i = 0; i < 3; i++) {
     input_array[i] += m_world->GetRandom().GetUInt(1 << 24);
@@ -643,9 +643,9 @@
 
 
 bool cEnvironment::TestInput( cReactionResult & result,
-			      const tBuffer<int> & inputs,
-			      const tBuffer<int> & outputs,
-			      const tArray<double> & resource_count ) const
+                              const tBuffer<int> & inputs,
+                              const tBuffer<int> & outputs,
+                              const tArray<double> & resource_count ) const
 {
   // @CAO nothing for the moment...
   return false;
@@ -653,59 +653,60 @@
 
 
 bool cEnvironment::TestOutput( cReactionResult & result,
-			       const tBuffer<int> & input_buf,
-			       const tBuffer<int> & output_buf,
-			       const tBuffer<int> & send_buf,
-			       const tBuffer<int> & receive_buf,
-			       const tArray<int> & task_count,
-			       const tArray<int> & reaction_count,
-			       const tArray<double> & resource_count,
-			       const tList< tBuffer<int> > & input_buffers,
-			       const tList< tBuffer<int> > & output_buffers) const
+                               const tBuffer<int> & input_buf,
+                               const tBuffer<int> & output_buf,
+                               const tBuffer<int> & send_buf,
+                               const tBuffer<int> & receive_buf,
+                               const tArray<int> & task_count,
+                               const tArray<int> & reaction_count,
+                               const tArray<double> & resource_count,
+                               const tList< tBuffer<int> > & input_buffers,
+                               const tList< tBuffer<int> > & output_buffers) const
 {
   // Do setup for reaction tests...
   cTaskContext* taskctx = task_lib.SetupTests(input_buf, output_buf, input_buffers, output_buffers);
-
+  
   // Loop through all reactions to see if any have been triggered...
   const int num_reactions = reaction_lib.GetSize();
   for (int i = 0; i < num_reactions; i++) {
     cReaction * cur_reaction = reaction_lib.GetReaction(i);
     assert(cur_reaction != NULL);
-
+    
     // Only use active reactions...
     if (cur_reaction->GetActive() == false) continue;
-
+    
     // Examine the task trigger associated with this reaction
     cTaskEntry * cur_task = cur_reaction->GetTask();
     assert(cur_task != NULL);
     const double task_quality = task_lib.TestOutput(*cur_task, taskctx);
     const int task_id = cur_task->GetID();
-
+    
     // If this task wasn't performed, move on to the next one.
     if (task_quality == 0.0) continue;
-
+    
     // Mark this task as performed...
     result.MarkTask(task_id);
-
+    
     // Examine requisites on this reaction
-    if (TestRequisites(cur_reaction->GetRequisites(), task_count[task_id],
-		       reaction_count) == false) {
+    if (TestRequisites(cur_reaction->GetRequisites(), task_count[task_id], reaction_count) == false) {
       continue;
     }
-
+    
     // And lets process it!
     DoProcesses(cur_reaction->GetProcesses(), resource_count, task_quality, result);
-
+    
     // Mark this reaction as occuring...
     result.MarkReaction(cur_reaction->GetID());
   }
+  
+  delete taskctx;
 
   // Loop again to check receive tasks...
   // if (receive_buf.GetSize() != 0)
   {
     // Do setup for reaction tests...
     taskctx = task_lib.SetupTests(receive_buf, output_buf, input_buffers, output_buffers);
-
+    
     for (int i = 0; i < num_reactions; i++) {
       cReaction * cur_reaction = reaction_lib.GetReaction(i);
       assert(cur_reaction != NULL);
@@ -725,136 +726,138 @@
       // Mark this task as performed...
       result.MarkReceiveTask(task_id);
     }
+    delete taskctx;
   }
-
+  
+  
   return result.GetActive();
 }
 
 
-bool cEnvironment::TestRequisites(const tList<cReactionRequisite> & req_list,
-		  int task_count, const tArray<int> & reaction_count) const
+bool cEnvironment::TestRequisites(const tList<cReactionRequisite>& req_list,
+                                  int task_count, const tArray<int>& reaction_count) const
 {
   const int num_reqs = req_list.GetSize();
-
+  
   // If there are no requisites, there is nothing to meet!
   if (num_reqs == 0) return true;
-
-  tConstListIterator<cReactionRequisite> req_it(req_list);
+  
+  tLWConstListIterator<cReactionRequisite> req_it(req_list);
   for (int i = 0; i < num_reqs; i++) {
     // See if this requisite batch can be satisfied.
-    const cReactionRequisite * cur_req = req_it.Next();
+    const cReactionRequisite* cur_req = req_it.Next();
     bool satisfied = true;
-
+    
     // Have all reactions been met?
-    tConstListIterator<cReaction> reaction_it(cur_req->GetReactions());
+    tLWConstListIterator<cReaction> reaction_it(cur_req->GetReactions());
     while (reaction_it.Next() != NULL) {
       int react_id = reaction_it.Get()->GetID();
       if (reaction_count[react_id] == 0) {
-	satisfied = false;
-	break;
+        satisfied = false;
+        break;
       }
     }
     if (satisfied == false) continue;
-
+    
     // Have all no-reactions been met?
-    tConstListIterator<cReaction> noreaction_it(cur_req->GetNoReactions());
+    tLWConstListIterator<cReaction> noreaction_it(cur_req->GetNoReactions());
     while (noreaction_it.Next() != NULL) {
       int react_id = noreaction_it.Get()->GetID();
       if (reaction_count[react_id] != 0) {
-	satisfied = false;
-	break;
+        satisfied = false;
+        break;
       }
     }
     if (satisfied == false) continue;
-
+    
     // Have all task counts been met?
     if (task_count < cur_req->GetMinTaskCount()) continue;
-
+    
     // Have all reactions been met?
     if (task_count >= cur_req->GetMaxTaskCount()) continue;
-
+    
     return true;
   }
-
+  
   return false;
 }
 
 
 void cEnvironment::DoProcesses(const tList<cReactionProcess> & process_list,
-			       const tArray<double> & resource_count,
-			       const double task_quality,
-			       cReactionResult & result) const
+                               const tArray<double> & resource_count,
+                               const double task_quality,
+                               cReactionResult & result) const
 {
   const int num_process = process_list.GetSize();
-
-  tConstListIterator<cReactionProcess> process_it(process_list);
+  
+  tLWConstListIterator<cReactionProcess> process_it(process_list);
   for (int i = 0; i < num_process; i++) {
     // See if this requisite batch can be satisfied.
-    const cReactionProcess * cur_process = process_it.Next();
+    const cReactionProcess* cur_process = process_it.Next();
     const double max_consumed = cur_process->GetMaxNumber();
     const double min_consumed = cur_process->GetMinNumber();
-
+    
     // Determine resource consumption
     double consumed = 0.0;
-    cResource * in_resource = cur_process->GetResource();
-
+    cResource* in_resource = cur_process->GetResource();
+    
     // Test if infinite resource
     if (in_resource == NULL) {
       consumed = max_consumed;
     }
-
+    
     // Otherwise we're using a finite resource
     else {
       const int res_id = in_resource->GetID();
-
+      
       consumed = resource_count[res_id] - result.GetConsumed(res_id);
       consumed *= cur_process->GetMaxFraction();
-
+      
       // Make sure we're not above the maximum consumption.
       if (consumed > max_consumed) consumed = max_consumed;
-
+      
       // Test if we are below the minimum consumption.
       if (consumed < min_consumed) consumed = 0.0;
-
+      
       // If we don't actually have any resource to consume stop here.
       if (consumed == 0.0) continue;
-
+      
       // Mark in the results the resource consumed.
       result.Consume(res_id, consumed);
     }
-
+    
     // Calculate the bonus
     double bonus = consumed * cur_process->GetValue() * task_quality;
-
+    
     switch (cur_process->GetType()) {
-    case nReaction::PROCTYPE_ADD:
-      result.AddBonus(bonus);
-      break;
-    case nReaction::PROCTYPE_MULT:
-      result.MultBonus(bonus);
-      break;
-    case nReaction::PROCTYPE_POW:
-      result.MultBonus( pow(2.0, bonus) );
-      break;
-    default:
-      assert(false);  // Should not get here!
-      break;
+      case nReaction::PROCTYPE_ADD:
+        result.AddBonus(bonus);
+        break;
+      case nReaction::PROCTYPE_MULT:
+        result.MultBonus(bonus);
+        break;
+      case nReaction::PROCTYPE_POW:
+        result.MultBonus( pow(2.0, bonus) );
+        break;
+      default:
+        assert(false);  // Should not get here!
+        break;
     };
-
+    
     // Determine detection events
     cResource * detected = cur_process->GetDetect();
     if (detected != NULL) {
       const int detected_id = detected->GetID();
       const double real_amount = resource_count[detected_id];
       double estimated_amount =
-	   m_world->GetRandom().GetRandNormal(real_amount, cur_process->GetDetectionError()*real_amount);
+        m_world->GetRandom().GetRandNormal(real_amount, cur_process->GetDetectionError()*real_amount);
       if (estimated_amount < cur_process->GetDetectionThreshold()) {
-	result.Detect(detected_id, 0.0);		
+        result.Detect(detected_id, 0.0);		
       } else {
         result.Detect(detected_id, estimated_amount);
       }
     }
-
+    
     // Determine byproducts
     cResource * product = cur_process->GetProduct();
     if (product != NULL) {
@@ -862,13 +865,13 @@
       double product_size = consumed * cur_process->GetConversion();
       result.Produce(product_id, product_size);
     }
-
+    
     // Determine what instructions should be run...
     const int inst_id = cur_process->GetInstID();
     if (inst_id >= 0) {
       result.AddInst(inst_id);
     }
-
+    
     result.Lethal(cur_process->GetLethal());
   }
 }

Modified: development/source/main/cInstSet.h
===================================================================
--- development/source/main/cInstSet.h	2006-03-11 18:06:56 UTC (rev 502)
+++ development/source/main/cInstSet.h	2006-03-12 04:27:38 UTC (rev 503)
@@ -109,7 +109,8 @@
 
   int GetNopMod(const cInstruction & inst) const
   {
-    return m_inst_lib->GetNopMod(m_lib_nopmod_map[inst.GetOp()]);
+    int nopmod = m_lib_nopmod_map[inst.GetOp()];
+    return m_inst_lib->GetNopMod(nopmod);
   }
 
   cInstruction GetRandomInst() const;

Modified: development/source/main/cWorld.h
===================================================================
--- development/source/main/cWorld.h	2006-03-11 18:06:56 UTC (rev 502)
+++ development/source/main/cWorld.h	2006-03-12 04:27:38 UTC (rev 503)
@@ -45,7 +45,7 @@
   cStats* m_stats;
   cWorldDriver* m_driver;
 
-  cRandom m_rng;
+  cRandomMT m_rng;
   
   bool m_test_on_div;     // flag derived from a collection of configuration settings
   bool m_test_sterilize;  // flag derived from a collection of configuration settings

Modified: development/source/tools/cRandom.cc
===================================================================
--- development/source/tools/cRandom.cc	2006-03-11 18:06:56 UTC (rev 502)
+++ development/source/tools/cRandom.cc	2006-03-12 04:27:38 UTC (rev 503)
@@ -22,41 +22,36 @@
 // Constants //////////////////////////////////////////////////////////////////
 
 // Statistical Approximation
-const unsigned int cRandom::_BINOMIAL_TO_NORMAL=50;    //if < n*p*(1-p)
-const unsigned int cRandom::_BINOMIAL_TO_POISSON=1000; //if < n
+const unsigned int cRandom::_BINOMIAL_TO_NORMAL = 50;    //if < n*p*(1-p)
+const unsigned int cRandom::_BINOMIAL_TO_POISSON = 1000; //if < n
 
 // Engine
-const unsigned int cRandom::_RAND_MBIG=1000000000;
-const unsigned int cRandom::_RAND_MSEED=161803398;
+const unsigned int cRandom::_RAND_MBIG = 1000000000;
+const unsigned int cRandom::_RAND_MSEED = 161803398;
 
 // Number Generation
-const double cRandom::_RAND_FAC=(1.0/_RAND_MBIG);
-const double cRandom::_RAND_mP_FAC=(_RAND_MBIG/1000);
-const double cRandom::_RAND_uP_FAC=(_RAND_MBIG/1000000);
+const double cRandom::_RAND_FAC = (1.0/_RAND_MBIG);
+const double cRandom::_RAND_mP_FAC = (_RAND_MBIG/1000);
+const double cRandom::_RAND_uP_FAC = (_RAND_MBIG/1000000);
 
 
 // Constructor and setup //////////////////////////////////////////////////////
 
-cRandom::cRandom(const int in_seed) :
- seed(0),
- original_seed(0),
- inext(0),
- inextp(0),
- use_count(0),
- expRV(0)
-  {
-    for( int i=0; i<56; ++i ){
-      ma[i] = 0;
-    }
-    ResetSeed(in_seed);  // Calls init()
+cRandom::cRandom(const int in_seed)
+: seed(0), original_seed(0), inext(0), inextp(0), expRV(0)
+{
+  for (int i = 0; i < 56; ++i) {
+    ma[i] = 0;
   }
+  ResetSeed(in_seed);  // Calls init()
+}
 
 
-void cRandom::ResetSeed(const int in_seed){
-  //if( in_seed<0 ){  // @TCC - make 0 also be seeded with time * pid
+void cRandom::ResetSeed(const int in_seed)
+{
   original_seed = in_seed;
   
-  if( in_seed<=0 ){
+  if (in_seed <= 0) {
     int seed_time = (int) time(NULL);
 #ifdef MSVC_COMPILER
     int seed_pid = (int) _getpid(); 
@@ -64,20 +59,26 @@
     int seed_pid = (int) getpid(); 
 #endif
     seed = seed_time ^ (seed_pid << 8);
-  }
-  else {
+  } else {
     seed = in_seed;
   }
   
-  if( seed < 0 ) seed*=-1;
-  seed%=_RAND_MSEED;
+  if (seed < 0) seed *= -1;
+  seed %= _RAND_MSEED;
 
   init();
-  initStatFunctions();
 }
 
+void cRandomMT::ResetSeed(const int in_seed)
+{
+  pthread_mutex_lock(&m_mutex);
+  cRandom::ResetSeed(in_seed);
+  pthread_mutex_unlock(&m_mutex);
+}
 
-void cRandom::init(){
+
+void cRandom::init()
+{
   int mj, mk, ii, i;
 
   // Clear variables
@@ -110,79 +111,121 @@
 
   inext = 0;
   inextp = 31;
-}
 
-void cRandom::initStatFunctions(){
   // Setup variables used by Statistical Distribution functions
-  expRV=-log(GetDouble());
+  expRV = -log(cRandom::Get() * _RAND_FAC);
 }
-  
 
+unsigned int cRandom::Get()
+{
+  if (++inext == 56) inext = 0;
+  if (++inextp == 56) inextp = 0;
+  assert(inext < 56);
+  assert(inextp < 56);
+  int mj = ma[inext] - ma[inextp];
+  if (mj < 0) mj += _RAND_MBIG;
+  ma[inext] = mj;
+  return mj;
+}
+
+unsigned int cRandomMT::Get()
+{
+  pthread_mutex_lock(&m_mutex);
+  unsigned int value = cRandom::Get();
+  pthread_mutex_unlock(&m_mutex);
+  return value;
+}
+
 // Statistical functions //////////////////////////////////////////////////////
 
-double cRandom::GetRandNormal(){
+double cRandom::GetRandNormal()
+{
   // Draw from a Unit Normal Dist
   // Using Rejection Method and saving of initial exponential random variable
   double expRV2;
-  while( 1 ){
-    expRV2=-log(GetDouble());
-    expRV-=(expRV2-1)*(expRV2-1)/2;
-    if( expRV>0 ) break;  
-    expRV=-log(GetDouble());
+  while (1) {
+    expRV2 = -log(GetDouble());
+    expRV -= (expRV2-1)*(expRV2-1)/2;
+    if (expRV > 0) break;  
+    expRV = -log(GetDouble());
   }
-  if( P(.5) ) 
+  if (P(.5)) 
     return expRV2;
   else
     return -expRV2;
 }
 
-unsigned int cRandom::GetRandPoisson(const double mean){
+double cRandomMT::GetRandNormal()
+{
+  // Draw from a Unit Normal Dist
+  // Using Rejection Method and saving of initial exponential random variable
+  double expRV2;
+  
+  pthread_mutex_lock(&m_mutex);
+  while (1) {
+    expRV2 = -log(cRandom::Get() * _RAND_FAC);
+    expRV -= (expRV2-1)*(expRV2-1)/2;
+    if (expRV > 0) break;
+    expRV = -log(cRandom::Get() * _RAND_FAC);
+  }
+  pthread_mutex_unlock(&m_mutex);
+  
+  if (P(.5)) 
+    return expRV2;
+  else
+    return -expRV2;
+}
+
+unsigned int cRandom::GetRandPoisson(const double mean)
+{
   // Draw from a Poisson Dist with mean
   // if cannot calculate, returns UINT_MAX
   // Uses Rejection Method
-  unsigned int k=0;
-  double a=exp(-mean);
-  double u=GetDouble();
-  if( a <=0 ) return UINT_MAX; // cannot calculate, so return UINT_MAX
-  while( u>=a ){
-    u*=GetDouble();
+  unsigned int k = 0;
+  double a = exp(-mean);
+  double u = GetDouble();
+  if (a <= 0) return UINT_MAX; // cannot calculate, so return UINT_MAX
+  while (u >= a) {
+    u *= GetDouble();
     ++k;
   }
   return k;
 }
 
-unsigned int cRandom::GetFullRandBinomial(const double n, const double p){
+unsigned int cRandom::GetFullRandBinomial(const double n, const double p)
+{
   // Actually try n Bernoulli events with probability p
-  unsigned int k=0;
-  for( unsigned int i=0; i<n; ++i )
-    if( P(p) ) k++;
+  unsigned int k = 0;
+  for (unsigned int i = 0; i < n; ++i) if (P(p)) k++;
   return k;
 }
 
-unsigned int cRandom::GetRandBinomial(const double n, const double p){
+unsigned int cRandom::GetRandBinomial(const double n, const double p)
+{
   // Approximate Binomial if appropriate
   // if np(1-p) is large, use a Normal approx
-  if( n*p*(1-p) >= _BINOMIAL_TO_NORMAL ){
-    return (unsigned int)(GetRandNormal(n*p,n*p*(1-p))+.5);
+  if (n * p * (1 - p) >= _BINOMIAL_TO_NORMAL) {
+    return static_cast<unsigned int>(GetRandNormal(n * p, n * p * (1 - p)) + 0.5);
   }
   // elseif n is large, use a Poisson approx
-  if( n >= _BINOMIAL_TO_POISSON ){
-    unsigned int k=GetRandPoisson(n,p);
-    if( k < UINT_MAX ) // if approx worked
+  if (n >= _BINOMIAL_TO_POISSON) {
+    unsigned int k = GetRandPoisson(n, p);
+    if (k < UINT_MAX) // if approx worked
       return k;
   }
   // otherwise, actually generate the randBinomial
-  return GetFullRandBinomial(n,p);
+  return GetFullRandBinomial(n, p);
 }
 
 
-bool cRandom::Choose(int num_in, tArray<int> & out_array){
+bool cRandom::Choose(int num_in, tArray<int>& out_array)
+{
   // If you ask for more than you pass in...
-  assert ( num_in >= out_array.GetSize() );
+  assert(num_in >= out_array.GetSize());
 
   if (num_in == out_array.GetSize()) {
     // init array to 0's
-    for(int i = 0; i < out_array.GetSize(); i++)  out_array[i] = i;
+    for (int i = 0; i < out_array.GetSize(); i++)  out_array[i] = i;
     return true;
   }
 
@@ -190,14 +233,14 @@
   // @CAO this could be done a lot faster when choose size is close to
   // full size.  However we need to rememebr to watch out for larger num_in
   while (choice_num < out_array.GetSize()) {
-    int next = (int) GetUInt(num_in);
+    int next = static_cast<int>(GetUInt(num_in));
 
     // See if this choice is ok to use...
     bool ok = true;
     for (int i = 0; i < choice_num; i++) {
       if (out_array[i] == next) {
-	ok = false;
-	break;
+        ok = false;
+        break;
       }
     }
 

Modified: development/source/tools/cRandom.h
===================================================================
--- development/source/tools/cRandom.h	2006-03-11 18:06:56 UTC (rev 502)
+++ development/source/tools/cRandom.h	2006-03-12 04:27:38 UTC (rev 503)
@@ -14,6 +14,7 @@
 #include <time.h>
 #include <limits.h>
 #include <math.h>
+#include <pthread.h>
 
 /**
  * A versatile and fast pseudo random number generator.
@@ -23,14 +24,13 @@
 
 class cRandom
 {
-private:
+protected:
   // Internal memebers
   int seed;
   int original_seed;
   int inext;
   int inextp;
   int ma[56];
-  int use_count;
   
   // Constants ////////////////////////////////////////////////////////////////
   // Statistical Approximation
@@ -50,11 +50,10 @@
   
   // Internal functions
   void init();	// Setup  (called by ResetSeed(in_seed);
-  void initStatFunctions();
   
   // Basic Random number
   // Returns a random number [0,_RAND_MBIG)
-  inline unsigned int Get();
+  virtual unsigned int Get();
   
 public:
   /**
@@ -64,10 +63,8 @@
    * seed from the actual system time.
    **/
   cRandom(const int in_seed = -1);
+  virtual ~cRandom() { ; }
   
-  inline int GetUseCount() { return use_count; }
-  
-  
   /**
    * @return The seed that was actually used to start the random sequence.
    **/
@@ -85,7 +82,7 @@
    * A negative seed means that the random number generator gets its
    * seed from the actual system time.
    **/
-  void ResetSeed(const int new_seed);
+  virtual void ResetSeed(const int new_seed);
   
   
   // Random Number Generation /////////////////////////////////////////////////
@@ -167,7 +164,7 @@
   /**
    * Generate a random variable drawn from a unit normal distribution.
    **/
-  double GetRandNormal();
+  virtual double GetRandNormal();
   /**
    * Generate a random variable drawn from a distribution with given
    * mean and variance.
@@ -209,16 +206,24 @@
   unsigned int GetRandBinomial(const double n, const double p); // Approx
 };
 
-inline unsigned int cRandom::Get()
+
+class cRandomMT : public cRandom
 {
-  if (++inext == 56) inext = 0;
-  if (++inextp == 56) inextp = 0;
-  int mj = ma[inext] - ma[inextp];
-  if (mj < 0) mj += _RAND_MBIG;
-  ma[inext] = mj;
-  return mj;
-}
+private:
+  pthread_mutex_t m_mutex;
+  
+  unsigned int Get();
 
+public:
+  cRandomMT(const int in_seed = -1) : cRandom(in_seed) { pthread_mutex_init(&m_mutex, NULL); }
+  ~cRandomMT() { pthread_mutex_destroy(&m_mutex); }
+
+  void ResetSeed(const int in_seed);
+
+  double GetRandNormal();
+};
+
+
 inline unsigned int cRandom::MutateByte(unsigned int value)
 {
   int byte_pos = 8 * GetUInt(4);
@@ -249,4 +254,5 @@
   return value;
 }
 
+
 #endif

Modified: development/source/tools/tList.h
===================================================================
--- development/source/tools/tList.h	2006-03-11 18:06:56 UTC (rev 502)
+++ development/source/tools/tList.h	2006-03-12 04:27:38 UTC (rev 503)
@@ -108,10 +108,41 @@
   bool AtEnd() const;
 };
 
+template <class T> class tLWConstListIterator : public tBaseIterator<T>
+{
+  friend class tList<T>;
+private:
+  const tList<T>& list;
+  const tListNode<T>* node;
+  
+  const tList<T>& GetConstList() { return list; }
+  const tListNode<T>* GetConstNode() { return node; }
+
+public:
+  explicit tLWConstListIterator(const tList<T>& _list) : list(_list), node(&(_list.root)) { ; }
+  explicit tLWConstListIterator(const tList<T>& _list, const tListNode<T>* start_node) : list(_list), node(start_node) { ; }
+  ~tLWConstListIterator() { ; }
+  
+  void Set(tListNode<T>* in_node) { node = in_node; }
+  void Reset();
+  
+  const T* Get();
+  const T* Next();
+  const T* Prev();
+  const T* GetConst() { return Get(); }
+  const T* NextConst() { return Next(); }
+  const T* PrevConst() { return Prev(); }
+  bool Find(const T* test_data);
+  
+  bool AtRoot() const;
+  bool AtEnd() const;
+};
+
 template <class T> class tList {
   friend class tBaseIterator<T>;
   friend class tListIterator<T>;
   friend class tConstListIterator<T>;
+  friend class tLWConstListIterator<T>;
 protected:
     tListNode<T> root;                     // Data root
   int size;
@@ -550,4 +581,47 @@
   return (node->next == &(list.root));
 }
 
+/////////////////////////
+//  tLWConstListIterator
+
+template <class T> void tLWConstListIterator<T>::Reset()
+{
+  node = &(list.root);
+}
+
+template <class T> const T* tLWConstListIterator<T>::Get()
+{
+  return node->data;
+}
+
+template <class T> const T* tLWConstListIterator<T>::Next()
+{
+  node = node->next;
+  return node->data;
+}
+
+template <class T> const T* tLWConstListIterator<T>::Prev()
+{
+  node = node->prev;
+  return node->data;
+}
+
+template <class T> bool tLWConstListIterator<T>::Find(const T* test_data)
+{
+  for (node = list.root.next; node != &(list.root); node = node->next) {
+    if (node->data == test_data) return true;
+  }
+  return false;
+}
+
+template <class T> bool tLWConstListIterator<T>::AtRoot() const
+{
+  return (node == &(list.root));
+}
+
+template <class T> bool tLWConstListIterator<T>::AtEnd() const
+{
+  return (node->next == &(list.root));
+}
+
 #endif




More information about the Avida-cvs mailing list