[Avida-SVN] r2940 - in development: . Avida.xcodeproj source/tools

brysonda at myxo.css.msu.edu brysonda at myxo.css.msu.edu
Wed Nov 12 21:10:39 PST 2008


Author: brysonda
Date: 2008-11-13 00:10:38 -0500 (Thu, 13 Nov 2008)
New Revision: 2940

Added:
   development/source/tools/cRCObject.cc
   development/source/tools/cRCObject.h
   development/source/tools/tRCPtr.h
Modified:
   development/Avida.xcodeproj/project.pbxproj
   development/CMakeLists.txt
   development/source/tools/cString.cc
   development/source/tools/cString.h
   development/source/tools/tAutoRelease.h
Log:
First pass implementation of cRCObject and tRCPtr for creating and managing reference counted objects.  Operation should be correct, but not yet thread-safe.

Replace/encapsulate cString's cStringValue reference counting with cRCObject.

Modified: development/Avida.xcodeproj/project.pbxproj
===================================================================
--- development/Avida.xcodeproj/project.pbxproj	2008-11-13 02:00:06 UTC (rev 2939)
+++ development/Avida.xcodeproj/project.pbxproj	2008-11-13 05:10:38 UTC (rev 2940)
@@ -34,6 +34,8 @@
 		56F555E70C3B402A00E2E929 /* viewer-text.cc in Sources */ = {isa = PBXBuildFile; fileRef = 56F555E40C3B402A00E2E929 /* viewer-text.cc */; };
 		700E2996085A1F6000CF158A /* avida in CopyFiles */ = {isa = PBXBuildFile; fileRef = DCC3164D07626CF3008F7A48 /* avida */; };
 		700E2B87085DE54400CF158A /* avida-viewer in CopyFiles */ = {isa = PBXBuildFile; fileRef = 700E2B83085DE50C00CF158A /* avida-viewer */; };
+		70211A5D0ECBD531004A293A /* cRCObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 70211A5B0ECBD531004A293A /* cRCObject.h */; };
+		70211A5E0ECBD531004A293A /* cRCObject.cc in Sources */ = {isa = PBXBuildFile; fileRef = 70211A5C0ECBD531004A293A /* cRCObject.cc */; };
 		7023EC3A0C0A431B00362B9C /* avida.cc in Sources */ = {isa = PBXBuildFile; fileRef = DCC3109C0762539E008F7A48 /* avida.cc */; };
 		7023EC3B0C0A431B00362B9C /* cActionLibrary.cc in Sources */ = {isa = PBXBuildFile; fileRef = 708051BA0A1F66B400CBB8B6 /* cActionLibrary.cc */; };
 		7023EC3C0C0A431B00362B9C /* cAnalyze.cc in Sources */ = {isa = PBXBuildFile; fileRef = 70422A1C091B141000A5E67F /* cAnalyze.cc */; };
@@ -407,6 +409,9 @@
 		701D93E6094CBF71008B845F /* cDefaultAnalyzeDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cDefaultAnalyzeDriver.h; sourceTree = "<group>"; };
 		701D93E7094CBF71008B845F /* cDefaultAnalyzeDriver.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cDefaultAnalyzeDriver.cc; sourceTree = "<group>"; };
 		701EF27E0BEA5D2300DAE168 /* main.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = main.cc; sourceTree = "<group>"; };
+		70211A5B0ECBD531004A293A /* cRCObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cRCObject.h; sourceTree = "<group>"; };
+		70211A5C0ECBD531004A293A /* cRCObject.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cRCObject.cc; sourceTree = "<group>"; };
+		70211A6C0ECBDB72004A293A /* tRCPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tRCPtr.h; sourceTree = "<group>"; };
 		7023EC330C0A426900362B9C /* libavida-core.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libavida-core.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 		7027621909D73E5900741717 /* cOrgSourceMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cOrgSourceMessage.h; sourceTree = "<group>"; };
 		7027621A09D73E7700741717 /* cOrgSinkMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cOrgSinkMessage.h; sourceTree = "<group>"; };
@@ -1647,6 +1652,9 @@
 				70EFD65E0D975B5E00FAD32A /* cConstBurstSchedule.h */,
 				70EFD65F0D975B5E00FAD32A /* cConstBurstSchedule.cc */,
 				70B984B40EBB71B500A828B1 /* tDataCommandManager.h */,
+				70211A5B0ECBD531004A293A /* cRCObject.h */,
+				70211A5C0ECBD531004A293A /* cRCObject.cc */,
+				70211A6C0ECBDB72004A293A /* tRCPtr.h */,
 			);
 			path = tools;
 			sourceTree = "<group>";
@@ -1706,6 +1714,7 @@
 			files = (
 				2A57A4000D6B954D00FC54C7 /* cProbDemeProbSchedule.h in Headers */,
 				709A1EEB0EB6C42D006090AF /* cOrgMovementPredicate.h in Headers */,
+				70211A5D0ECBD531004A293A /* cRCObject.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -2060,6 +2069,7 @@
 				70BB2AE20EA5303F008269D2 /* cDriverStatusConduit.cc in Sources */,
 				709A1EEC0EB6C42D006090AF /* cResourceHistory.cc in Sources */,
 				70E60C4B0EC0088300718740 /* cGenotypeBatch.cc in Sources */,
+				70211A5E0ECBD531004A293A /* cRCObject.cc in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

Modified: development/CMakeLists.txt
===================================================================
--- development/CMakeLists.txt	2008-11-13 02:00:06 UTC (rev 2939)
+++ development/CMakeLists.txt	2008-11-13 05:10:38 UTC (rev 2940)
@@ -296,6 +296,7 @@
   ${TOOLS_DIR}/cProbDemeProbSchedule.cc
   ${TOOLS_DIR}/cProbSchedule.cc
   ${TOOLS_DIR}/cRandom.cc
+  ${TOOLS_DIR}/cRCObject.cc
   ${TOOLS_DIR}/cRunningAverage.cc
   ${TOOLS_DIR}/cSchedule.cc
   ${TOOLS_DIR}/cString.cc

Added: development/source/tools/cRCObject.cc
===================================================================
--- development/source/tools/cRCObject.cc	                        (rev 0)
+++ development/source/tools/cRCObject.cc	2008-11-13 05:10:38 UTC (rev 2940)
@@ -0,0 +1,27 @@
+/*
+ *  cRCObject.cc
+ *  Avida
+ *
+ *  Created by David on 11/12/08.
+ *  Copyright 2008 Michigan State University. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; version 2
+ *  of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#include "cRCObject.h"
+
+cRCObject::~cRCObject() { ; }

Added: development/source/tools/cRCObject.h
===================================================================
--- development/source/tools/cRCObject.h	                        (rev 0)
+++ development/source/tools/cRCObject.h	2008-11-13 05:10:38 UTC (rev 2940)
@@ -0,0 +1,49 @@
+/*
+ *  cRCObject.h
+ *  Avida
+ *
+ *  Created by David on 11/12/08.
+ *  Copyright 2008 Michigan State University. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; version 2
+ *  of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef cRCObject_h
+#define cRCObject_h
+
+
+class cRCObject
+{
+private:
+  volatile int m_ref_count;
+  volatile bool m_exclusive;
+  
+public:
+  cRCObject() : m_ref_count(0), m_exclusive(false) { ; }
+  cRCObject(const cRCObject&) : m_ref_count(0), m_exclusive(false) { ; }
+  virtual ~cRCObject() = 0;
+  
+  cRCObject& operator=(const cRCObject&) { return *this; }
+  
+  void AddReference() { m_ref_count++; }
+  void RemoveReference() { if (--m_ref_count == 0) delete this; }
+  
+  bool SetExclusive() { if (!(m_ref_count > 1)) m_exclusive = true; return m_exclusive; }
+  bool IsExclusive() { return m_exclusive; }
+};
+
+#endif

Modified: development/source/tools/cString.cc
===================================================================
--- development/source/tools/cString.cc	2008-11-13 02:00:06 UTC (rev 2939)
+++ development/source/tools/cString.cc	2008-11-13 05:10:38 UTC (rev 2940)
@@ -34,24 +34,24 @@
 
 // ** class cStringData **
 // -- Constructors --
-cString::cStringData::cStringData(int in_size) : m_refs(1), m_size(in_size), m_data(new char[m_size + 1])
+cString::cStringData::cStringData(int in_size) : m_size(in_size), m_data(new char[m_size + 1])
 {
   assert(m_data != NULL); // Memory Allocation Error: Out of Memory
   m_data[0] = '\0';
   m_data[m_size] = '\0';
 }
 
-cString::cStringData::cStringData(int in_size, const char* in) : m_refs(1), m_size(in_size), m_data(new char[m_size + 1])
+cString::cStringData::cStringData(int in_size, const char* in) : m_size(in_size), m_data(new char[m_size + 1])
 {
   assert(m_data != NULL); // Memory Allocation Error: Out of Memory
   for (short i = 0; i < m_size; i++) m_data[i] = in[i];
   m_data[m_size] = '\0';
 }
 
-cString::cStringData::cStringData(const cStringData& in) : m_refs(1), m_size(in.GetSize()), m_data(new char[m_size + 1])
+cString::cStringData::cStringData(const cStringData& in) : cRCObject(*this), m_size(in.GetSize()), m_data(new char[m_size + 1])
 {
   assert(m_data != NULL); // Memory Allocation Error: Out of Memory
-  for (short i = 0; i < m_size; i++)  m_data[i] = in[i];
+  for (int i = 0; i < m_size; i++)  m_data[i] = in[i];
   m_data[m_size] = '\0';
 }
 
@@ -605,8 +605,8 @@
   assert (in_size == 0 || in != NULL); // NULL input string
   
   // Allocate a new string
-  cStringData * new_value = new cStringData(GetSize()+in_size);
-  assert (new_value != NULL);       // Memory Allocation Error: Out of Memory
+  tRCPtr<cStringData> new_value(new cStringData(GetSize() + in_size));
+  assert (new_value);       // Memory Allocation Error: Out of Memory
   for(int i=0; i<GetSize(); ++i ) { // Copy self up to pos
     (*new_value)[i] = this->operator[](i);
   }
@@ -614,7 +614,7 @@
     assert(in[i] != '\0');          // Input String Contains '\\0' or too Short
     (*new_value)[i+GetSize()] = in[i];
   }
-  TakeValue(new_value);             // Reassing data to new data
+  value = new_value;             // Reassign data to new data
   return(*this);
 }
 
@@ -637,8 +637,8 @@
   
   // Allocate a new string
   const int new_size = GetSize() + in_size - excise;
-  cStringData * new_value = new cStringData(new_size);
-  assert (new_value != NULL);  // Memory Allocation Error: Out of Memory
+  tRCPtr<cStringData> new_value(new cStringData(new_size));
+  assert (new_value);  // Memory Allocation Error: Out of Memory
   
   for(int i = 0; i < pos; ++i ){             // Copy self up to pos
     (*new_value)[i] = this->operator[](i);
@@ -651,8 +651,8 @@
     (*new_value)[i+in_size-excise] = this->operator[](i);
   }
   
-  TakeValue(new_value);                      // Reassing data to new data
-  return(*this);
+  value = new_value;                      // Reassign data to new data
+  return *this;
 }
 
 
@@ -671,8 +671,8 @@
   
   // Allocate a new string
   const int new_size = GetSize() - excise;
-  cStringData * new_value = new cStringData(new_size);
-  assert (new_value != NULL);  // Memory Allocation Error: Out of Memory
+  tRCPtr<cStringData> new_value(new cStringData(new_size));
+  assert (new_value);  // Memory Allocation Error: Out of Memory
   
   for(int i = 0; i < pos; i++){             // Copy self up to pos
     (*new_value)[i] = this->operator[](i);
@@ -681,7 +681,7 @@
     (*new_value)[i-excise] = this->operator[](i);
   }
   
-  TakeValue(new_value);                      // Reassing data to new data
+  value = new_value;                      // Reassign data to new data
   return out_string;
 }
 

Modified: development/source/tools/cString.h
===================================================================
--- development/source/tools/cString.h	2008-11-13 02:00:06 UTC (rev 2939)
+++ development/source/tools/cString.h	2008-11-13 05:10:38 UTC (rev 2940)
@@ -32,6 +32,9 @@
 #include <cstring>
 #include <cassert>
 
+#include "cRCObject.h"
+#include "tRCPtr.h"
+
 #if USE_tMemTrack
 # ifndef tMemTrack_h
 #  include "tMemTrack.h"
@@ -39,7 +42,6 @@
 #endif
 
 #define MAX_STRING_LENGTH 4096
-#define MAX_STRING_REF_COUNT 32767
 #define CONTINUE_LINE_CHAR '\\'
 
 /**
@@ -82,15 +84,13 @@
   friend class cCharProxy;  // Telling rvalue vs lvalue ....
 
   // cStringData -- Holds the actual data and is reference count --
-  class cStringData
+  class cStringData : public cRCObject
   {
     // NOTE: Terminating NULL is always there (you can't assign!!)
   private:
-    short m_refs;   // Number of references
     int m_size;   // size of data (NOT INCLUDING TRAILING NULL)
     char* m_data;
     
-    
     cStringData(); // @not_implemented
 
   public:
@@ -100,7 +100,6 @@
 
     ~cStringData()
     {
-      assert(m_refs == 0);  // Deleting cStringData with References!!
       delete [] m_data;
     }
 
@@ -132,58 +131,41 @@
       assert(index != m_size);  // Cannot Change Terminating NULL
       return m_data[index];
     }
-
-    bool IsShared() { return (m_refs > 1); }
-    bool AtMaxRefs() { return (m_refs >= MAX_STRING_REF_COUNT); }
-
-    short RemoveRef()
-    {
-      assert(m_refs > 0);  // Reference count corrupted
-      return (--m_refs);
-    }
-
-    cStringData* NewRef() { ++m_refs; return this; }
   };
 
 public:
   static const int MAX_LENGTH;
 
-  cString(const char* in = "") : value(new cStringData(strlen(in), in))
+  cString(const char* in_str = "") : value(new cStringData(strlen(in_str), in_str))
   {
-    assert( in != NULL );     // NULL input string
-    assert( value != NULL );  // Memory Allocation Error: Out of Memory
+    assert( in_str != NULL );     // NULL input string
+    assert( value );  // Memory Allocation Error: Out of Memory
   }
   cString(const char* in, int in_size) : value(new cStringData(in_size, in))
   {
     assert(in_size >= 0);
     assert( in != NULL );     // NULL input string
-    assert( value != NULL );  // Memory Allocation Error: Out of Memory
+    assert( value );  // Memory Allocation Error: Out of Memory
   }
   explicit cString(const int size) : value(new cStringData(size))
   {
-    assert( value != NULL );    // Memory Allocation Error: Out of Memory
+    assert( value );    // Memory Allocation Error: Out of Memory
   }
-  cString(const cString& in) { CopyString(in); }
+  cString(const cString& in_str) :value(in_str.value) { ; }
 
-  ~cString() { if (value->RemoveRef() == 0) delete value; }
+  ~cString() { ; }
 
 
   // Cast to const char *
   operator const char* () const { return value->GetData(); }
 
   // Assignment Operators
-  cString& operator=(const cString & in)
-  {
-    if( value->RemoveRef() == 0 ) delete value;
-    CopyString(in);
-    return *this; 
-  }
+  cString& operator=(const cString& in_str) { value = in_str.value; return *this; }
   cString& operator=(const char* in)
   {
     assert( in != NULL ); // NULL input string
-    if( value->RemoveRef() == 0 ) delete value;
     value = new cStringData(strlen(in),in);
-    assert(value != NULL);  // Memory Allocation Error: Out of Memory
+    assert(value);  // Memory Allocation Error: Out of Memory
     return *this;
   }
   
@@ -588,21 +570,6 @@
 protected:
   // -- Internal Functions --
 
-  void CopyString(const cString & in) {
-    if (in.value->AtMaxRefs() == true) {
-      cStringData * old_data = in.value;
-      old_data->RemoveRef();  // remove our reference count
-      // Copy the _value_ of the old reference. (we need to const-cast here...)
-      ( (cString &) in ).value = new cStringData(*old_data);
-    }
-    value = in.value->NewRef();
-  }
-
-  void TakeValue(cStringData * new_ref){     // If you made new_value!
-    if( value->RemoveRef() == 0 ) delete value;
-    value = new_ref;
-  }
-
   // Methods that take input string size (unsafe to call from outside)
   cString & AppendStr(const int in_size, const char * in);  // Optimized
   cString & InsertStr(const int in_size, const char * in,
@@ -611,7 +578,7 @@
 
   // -- Internal Data --
 protected:
-  cStringData * value;
+  tRCPtr<cStringData> value;
 
 // }}} End Internals
 };
@@ -629,8 +596,7 @@
 
 void cString::CopyOnWrite()
 {
-  if (value->IsShared()) {  // if it is shared
-    value->RemoveRef();     // remove our reference count
+  if (!value->SetExclusive()) {  // if it is shared
     value = new cStringData(*value);  // make own copy of value
   }
 }

Modified: development/source/tools/tAutoRelease.h
===================================================================
--- development/source/tools/tAutoRelease.h	2008-11-13 02:00:06 UTC (rev 2939)
+++ development/source/tools/tAutoRelease.h	2008-11-13 05:10:38 UTC (rev 2940)
@@ -46,7 +46,8 @@
   inline bool IsNull() const { return !(m_value); }
   
   //! Access the contents
-  inline T& operator*() { return *m_value; }
+  inline T* operator->() const { return m_value; }
+  inline T& operator*() const { return *m_value; }
   
   //! Take control of the contents
   inline T* Release() { T* value = m_value; m_value = NULL; return value; }

Added: development/source/tools/tRCPtr.h
===================================================================
--- development/source/tools/tRCPtr.h	                        (rev 0)
+++ development/source/tools/tRCPtr.h	2008-11-13 05:10:38 UTC (rev 2940)
@@ -0,0 +1,75 @@
+/*
+ *  tRCPtr.h
+ *  Avida
+ *
+ *  Created by David on 11/12/08.
+ *  Copyright 2008 Michigan State University. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; version 2
+ *  of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
+
+#ifndef tRCPtr_h
+#define tRCPtr_h
+
+template<class T> class tRCPtr
+{
+private:
+  T* m_ptr;
+  
+  void handleNewPointer();
+
+public:
+  tRCPtr(T* ptr = NULL) : m_ptr(ptr) { handleNewPointer(); }
+  tRCPtr(const tRCPtr& rhs) : m_ptr(rhs.m_ptr) { handleNewPointer(); }
+  ~tRCPtr() { if (m_ptr) m_ptr->RemoveReference(); }
+  
+  tRCPtr& operator=(const tRCPtr& rhs);
+  
+  inline bool operator!() const { return !m_ptr; }
+  inline operator bool() const { return !operator!(); }
+  
+  inline T* operator->() const { return m_ptr; }
+  inline T& operator*() const { return *m_ptr; }
+  
+  template<class S> inline S* operator->() const { return m_ptr; }
+  template<class S> inline S& operator->() const { return *m_ptr; }
+  
+  template<class S> operator tRCPtr<S>() { return tRCPtr<S>(m_ptr); }
+};
+
+template<class T> inline void tRCPtr<T>::handleNewPointer()
+{
+  if (!m_ptr) return;
+  
+  if (m_ptr->IsExclusive()) m_ptr = new T(*m_ptr);
+  
+  m_ptr->AddReference();
+}
+
+template<class T> tRCPtr<T>& tRCPtr<T>::operator=(const tRCPtr& rhs)
+{
+  if (m_ptr != rhs.m_ptr) {
+    T* old_ptr = m_ptr;
+    m_ptr = rhs.m_ptr;
+    handleNewPointer();
+    if (old_ptr) old_ptr->RemoveReference();
+  }
+  
+  return *this;
+}
+
+#endif




More information about the Avida-cvs mailing list