Przeglądaj źródła

GeomVertexReader/Writer should not hold lock

David Rose 20 lat temu
rodzic
commit
384f9ff0b0

+ 4 - 1
panda/src/gobj/geomVertexData.cxx

@@ -1891,8 +1891,11 @@ make_array_writers() {
   nassertv(!_got_array_writers);
 
   _array_writers.reserve(_cdata->_arrays.size());
-  GeomVertexData::Arrays::const_iterator ai;
+  GeomVertexData::Arrays::iterator ai;
   for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
+    if ((*ai)->get_ref_count() > 1) {
+      (*ai) = new GeomVertexArrayData(*(*ai));
+    }
     _array_writers.push_back(new GeomVertexArrayDataPipelineWriter(*ai, _force_to_0, _current_thread));
   }
 

+ 74 - 77
panda/src/gobj/geomVertexReader.I

@@ -27,9 +27,8 @@
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 GeomVertexReader() :
-  _data_reader(NULL),
-  _array_reader(NULL),
-  _owns_reader(false)
+  _vertex_data(NULL),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
 }
@@ -42,9 +41,8 @@ GeomVertexReader() :
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexData *vertex_data) :
-  _data_reader(new GeomVertexDataPipelineReader(vertex_data, Thread::get_current_thread())),
-  _array_reader(NULL),
-  _owns_reader(true)
+  _vertex_data(vertex_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
 }
@@ -58,9 +56,8 @@ GeomVertexReader(const GeomVertexData *vertex_data) :
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexData *vertex_data, const string &name) :
-  _data_reader(new GeomVertexDataPipelineReader(vertex_data, Thread::get_current_thread())),
-  _array_reader(NULL),
-  _owns_reader(true)
+  _vertex_data(vertex_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
   set_column(name);
@@ -75,10 +72,9 @@ GeomVertexReader(const GeomVertexData *vertex_data, const string &name) :
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexData *vertex_data, 
-                 const InternalName *name) :
-  _data_reader(new GeomVertexDataPipelineReader(vertex_data, Thread::get_current_thread())),
-  _array_reader(NULL),
-  _owns_reader(true)
+                   const InternalName *name) :
+  _vertex_data(vertex_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
   set_column(name);
@@ -92,9 +88,8 @@ GeomVertexReader(const GeomVertexData *vertex_data,
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexArrayData *array_data) :
-  _data_reader(NULL),
-  _array_reader(new GeomVertexArrayDataPipelineReader(array_data, Thread::get_current_thread())),
-  _owns_reader(true)
+  _array_data(array_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
 }
@@ -107,9 +102,8 @@ GeomVertexReader(const GeomVertexArrayData *array_data) :
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexArrayData *array_data, int column) :
-  _data_reader(NULL),
-  _array_reader(new GeomVertexArrayDataPipelineReader(array_data, Thread::get_current_thread())),
-  _owns_reader(true)
+  _array_data(array_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
   set_column(column);
@@ -123,28 +117,29 @@ GeomVertexReader(const GeomVertexArrayData *array_data, int column) :
 //               reader specifically to process the named data type.
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
-GeomVertexReader(const GeomVertexDataPipelineReader *data_reader, 
+GeomVertexReader(const GeomVertexDataPipelineReader *data_reader,
                  const InternalName *name) :
-  _data_reader(data_reader),
-  _array_reader(NULL),
-  _owns_reader(false)
+  _vertex_data(data_reader->get_object()),
+  _current_thread(data_reader->get_current_thread())
 {
   initialize();
-  set_column(name);
+  const GeomVertexFormat *format = data_reader->get_format();
+  set_vertex_column(format->get_array_with(name),
+                    format->get_column(name),
+                    data_reader);
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexReader::Copy Constructor
 //       Access: Published
-//  Description: The copy constructor steals ownership of the reader
-//               pointer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexReader &copy) :
-  _data_reader(copy._data_reader),
+  _vertex_data(copy._vertex_data),
   _array(copy._array),
-  _array_reader(copy._array_reader),
-  _owns_reader(copy._owns_reader),
+  _array_data(copy._array_data),
+  _current_thread(copy._current_thread),
   _packer(copy._packer),
   _stride(copy._stride),
   _pointer_begin(copy._pointer_begin),
@@ -152,33 +147,25 @@ GeomVertexReader(const GeomVertexReader &copy) :
   _pointer(copy._pointer),
   _start_row(copy._start_row)
 {
-  ((GeomVertexReader &)copy)._owns_reader = false;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexReader::Copy Assignment Operator
 //       Access: Published
-//  Description: The copy constructor steals ownership of the reader
-//               pointer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexReader::
 operator = (const GeomVertexReader &copy) {
-  if (_owns_reader) {
-    clear_reader();
-  }
-
-  _data_reader = copy._data_reader;
+  _vertex_data = copy._vertex_data;
   _array = copy._array;
-  _array_reader = copy._array_reader;
-  _owns_reader = copy._owns_reader;
+  _array_data = copy._array_data;
+  _current_thread = copy._current_thread;
   _packer = copy._packer;
   _stride = copy._stride;
   _pointer_begin = copy._pointer_begin;
   _pointer_end = copy._pointer_end;
   _pointer = copy._pointer;
   _start_row = copy._start_row;
-
-  ((GeomVertexReader &)copy)._owns_reader = false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -188,9 +175,6 @@ operator = (const GeomVertexReader &copy) {
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 ~GeomVertexReader() {
-  if (_owns_reader) {
-    clear_reader();
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -202,10 +186,7 @@ INLINE GeomVertexReader::
 ////////////////////////////////////////////////////////////////////
 INLINE const GeomVertexData *GeomVertexReader::
 get_vertex_data() const {
-  if (_data_reader != (GeomVertexDataPipelineReader *)NULL) {
-    return _data_reader->get_object();
-  }
-  return NULL;
+  return _vertex_data;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -216,7 +197,18 @@ get_vertex_data() const {
 ////////////////////////////////////////////////////////////////////
 INLINE const GeomVertexArrayData *GeomVertexReader::
 get_array_data() const {
-  return _array_reader->get_object();
+  return _array_data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexReader::get_current_thread
+//       Access: Published
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+INLINE Thread *GeomVertexReader::
+get_current_thread() const {
+  return _current_thread;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -234,12 +226,18 @@ get_array_data() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomVertexReader::
 set_column(int column) {
-  if (_data_reader != (const GeomVertexDataPipelineReader *)NULL) {
-    return set_column(_data_reader->get_format()->get_array_with(column),
-                      _data_reader->get_format()->get_column(column));
+  if (_vertex_data != (const GeomVertexData *)NULL) {
+    GeomVertexDataPipelineReader reader(_vertex_data, _current_thread);
+    reader.check_array_readers();
+    const GeomVertexFormat *format = reader.get_format();
+    return set_vertex_column(format->get_array_with(column),
+                             format->get_column(column),
+                             &reader);
   }
-  if (_array_reader != (const GeomVertexArrayDataPipelineReader *)NULL) {
-    return set_column(0, _array_reader->get_array_format()->get_column(column));
+  if (_array_data != (const GeomVertexArrayData *)NULL) {
+    GeomVertexArrayDataPipelineReader reader(_array_data, _current_thread);
+    return set_array_column(reader.get_array_format()->get_column(column),
+                            &reader);
   }
   return false;
 }
@@ -277,12 +275,18 @@ set_column(const string &name) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomVertexReader::
 set_column(const InternalName *name) {
-  if (_data_reader != (const GeomVertexDataPipelineReader *)NULL) {
-    return set_column(_data_reader->get_format()->get_array_with(name),
-                      _data_reader->get_format()->get_column(name));
+  if (_vertex_data != (const GeomVertexData *)NULL) {
+    GeomVertexDataPipelineReader reader(_vertex_data, _current_thread);
+    reader.check_array_readers();
+    const GeomVertexFormat *format = reader.get_format();
+    return set_vertex_column(format->get_array_with(name),
+                             format->get_column(name),
+                             &reader);
   }
-  if (_array_reader != (const GeomVertexArrayDataPipelineReader *)NULL) {
-    return set_column(0, _array_reader->get_array_format()->get_column(name));
+  if (_array_data != (const GeomVertexArrayData *)NULL) {
+    GeomVertexArrayDataPipelineReader reader(_array_data, _current_thread);
+    return set_array_column(reader.get_array_format()->get_column(name),
+                            &reader);
   }
 
   return false;
@@ -500,16 +504,9 @@ get_packer() const {
 //               and sets the internal pointer to the indicated row.
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexReader::
-set_pointer(int row) {
-  if (_data_reader != (const GeomVertexDataPipelineReader *)NULL) {
-    const GeomVertexArrayDataPipelineReader *array_reader = _data_reader->get_array_reader(_array);
-    _pointer_begin = array_reader->get_data();
-    _pointer_end = _pointer_begin + array_reader->get_data_size_bytes();
-
-  } else {
-    _pointer_begin = _array_reader->get_data();
-    _pointer_end = _pointer_begin + _array_reader->get_data_size_bytes();
-  }
+set_pointer(int row, const GeomVertexArrayDataPipelineReader *array_reader) {
+  _pointer_begin = array_reader->get_data();
+  _pointer_end = _pointer_begin + array_reader->get_data_size_bytes();
   quick_set_pointer(row);
 }
 
@@ -525,11 +522,11 @@ quick_set_pointer(int row) {
   nassertv(has_column());
 
 #ifdef _DEBUG
-  if (_data_reader != (const GeomVertexDataPipelineReader *)NULL) {
-    const GeomVertexArrayDataPipelineReader *array_reader = _data_reader->get_array_reader(_array);
-    nassertv(_pointer_begin == array_reader->get_data());
+  if (_vertex_data != (const GeomVertexData *)NULL) {
+    const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
+    nassertv(_pointer_begin == array_data->get_data());
   } else {
-    nassertv(_pointer_begin == _array_reader->get_data());
+    nassertv(_pointer_begin == _array_data->get_data());
   }
 #endif
 
@@ -546,11 +543,11 @@ INLINE const unsigned char *GeomVertexReader::
 inc_pointer() {
 #ifdef _DEBUG
   nassertr(_pointer < _pointer_end, empty_buffer);
-  if (_data_reader != (const GeomVertexDataPipelineReader *)NULL){ 
-    const GeomVertexArrayDataPipelineReader *array_reader = _data_reader->get_array_reader(_array);
-    nassertr(_pointer >= array_reader->get_data().p() && _pointer < array_reader->get_data().p() + array_reader->get_data_size_bytes(), empty_buffer);
+  if (_vertex_data != (const GeomVertexData *)NULL){ 
+    const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
+    nassertr(_pointer >= array_data->get_data().p() && _pointer < array_data->get_data().p() + array_data->get_data_size_bytes(), empty_buffer);
   } else {
-    nassertr(_pointer >= _array_reader->get_data().p() && _pointer < _array_reader->get_data().p() + _array_reader->get_data_size_bytes(), empty_buffer);
+    nassertr(_pointer >= _array_data->get_data().p() && _pointer < _array_data->get_data().p() + _array_data->get_data_size_bytes(), empty_buffer);
   }
 #endif
 

+ 53 - 41
panda/src/gobj/geomVertexReader.cxx

@@ -40,11 +40,6 @@ const unsigned char GeomVertexReader::empty_buffer[100] = { 0 };
 ////////////////////////////////////////////////////////////////////
 bool GeomVertexReader::
 set_column(int array, const GeomVertexColumn *column) {
-  if (_data_reader == (const GeomVertexDataPipelineReader *)NULL &&
-      _array_reader == (const GeomVertexArrayDataPipelineReader *)NULL) {
-    return false;
-  }
-
   if (column == (const GeomVertexColumn *)NULL) {
     // Clear the data type.
     _array = -1;
@@ -56,25 +51,18 @@ set_column(int array, const GeomVertexColumn *column) {
     return false;
   }
 
-  if (_data_reader != (const GeomVertexDataPipelineReader *)NULL) {
-#ifndef NDEBUG
-    _array = -1;
-    _packer = NULL;
-    nassertr(array >= 0 && array < _data_reader->get_num_arrays(), false);
-#endif
-    _array = array;
-    const GeomVertexArrayDataPipelineReader *array_reader = _data_reader->get_array_reader(_array);
-    _stride = array_reader->get_array_format()->get_stride();
-
-  } else {
-    _stride = _array_reader->get_array_format()->get_stride();
+  if (_vertex_data != (const GeomVertexData *)NULL) {
+    GeomVertexDataPipelineReader reader(_vertex_data, _current_thread);
+    reader.check_array_readers();
+    return set_vertex_column(array, column, &reader);
+  }
+  if (_array_data != (const GeomVertexArrayData *)NULL) {
+    GeomVertexArrayDataPipelineReader reader(_array_data, _current_thread);
+    return set_array_column(column, &reader);
   }
 
-  _packer = column->_packer;
-  
-  set_pointer(_start_row);
-  
-  return true;
+  // No data is associated with the Reader.
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -103,10 +91,6 @@ output(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 void GeomVertexReader::
 initialize() {
-  if (_data_reader != (const GeomVertexDataPipelineReader *)NULL) {
-    _data_reader->check_array_readers();
-  }
-
   _array = 0;
   _packer = NULL;
   _pointer_begin = NULL;
@@ -116,23 +100,51 @@ initialize() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: GeomVertexReader::clear_reader
+//     Function: GeomVertexReader::set_vertex_column
 //       Access: Private
-//  Description: Destructs the GeomVertexDataPipelineReader, when
-//               necessary, for instance when this object destructs.
+//  Description: Internal method to set the column to column from the
+//               indicated array, assuming we have a GeomVertexData
 ////////////////////////////////////////////////////////////////////
-void GeomVertexReader::
-clear_reader() {
-  nassertv(_owns_reader);
+bool GeomVertexReader::
+set_vertex_column(int array, const GeomVertexColumn *column,
+                  const GeomVertexDataPipelineReader *data_reader) {
+  nassertr(column != (const GeomVertexColumn *)NULL, false);
+  nassertr(_vertex_data != (const GeomVertexData *)NULL, false);
 
-  if (_data_reader != (const GeomVertexDataPipelineReader *)NULL) {
-    delete (GeomVertexDataPipelineReader *)_data_reader;
-    _data_reader = NULL;
-  } else {
-    nassertv(_array_reader != (const GeomVertexArrayDataPipelineReader *)NULL);
-    delete (GeomVertexArrayDataPipelineReader *)_array_reader;
-    _array_reader = NULL;
-  }
+#ifndef NDEBUG
+  _array = -1;
+  _packer = NULL;
+  nassertr(array >= 0 && array < _vertex_data->get_num_arrays(), false);
+#endif
+
+  _array = array;
+  const GeomVertexArrayDataPipelineReader *array_reader = 
+    data_reader->get_array_reader(_array);
+  _stride = array_reader->get_array_format()->get_stride();
+
+  _packer = column->_packer;
+  set_pointer(_start_row, array_reader);
+  
+  return true;
+}
 
-  _owns_reader = false;
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexReader::set_array_column
+//       Access: Private
+//  Description: Internal method to set the column to column from the
+//               indicated array, assuming we have a
+//               GeomVertexArrayData.
+////////////////////////////////////////////////////////////////////
+bool GeomVertexReader::
+set_array_column(const GeomVertexColumn *column,
+                 const GeomVertexArrayDataPipelineReader *array_reader) {
+  nassertr(column != (const GeomVertexColumn *)NULL, false);
+  nassertr(_array_data != (const GeomVertexArrayData *)NULL, false);
+
+  _stride = array_reader->get_array_format()->get_stride();
+
+  _packer = column->_packer;
+  set_pointer(_start_row, array_reader);
+  
+  return true;
 }

+ 11 - 5
panda/src/gobj/geomVertexReader.h

@@ -80,6 +80,7 @@ PUBLISHED:
 
   INLINE const GeomVertexData *get_vertex_data() const;
   INLINE const GeomVertexArrayData *get_array_data() const;
+  INLINE Thread *get_current_thread() const;
 
   INLINE bool set_column(int column);
   INLINE bool set_column(const string &name);
@@ -113,22 +114,27 @@ protected:
 
 private:
   void initialize();
-  void clear_reader();
 
-  INLINE void set_pointer(int row);
+  INLINE void set_pointer(int row, 
+                          const GeomVertexArrayDataPipelineReader *array_reader);
   INLINE void quick_set_pointer(int row);
   INLINE const unsigned char *inc_pointer();
 
+  bool set_vertex_column(int array, const GeomVertexColumn *column,
+                         const GeomVertexDataPipelineReader *data_reader);
+  bool set_array_column(const GeomVertexColumn *column,
+                        const GeomVertexArrayDataPipelineReader *array_reader);
+
   // It is important that we only store *one* of the following two
   // pointers.  If we are storing a GeomVertexData/array index, we
   // must not keep a pointer to the particular ArrayData we are
   // working on (if we do, it may result in an extra copy of the data
   // due to holding the reference count).
-  const GeomVertexDataPipelineReader *_data_reader;
+  CPT(GeomVertexData) _vertex_data;
   int _array;
-  const GeomVertexArrayDataPipelineReader *_array_reader;
-  bool _owns_reader;
+  CPT(GeomVertexArrayData) _array_data;
 
+  Thread *_current_thread;
   GeomVertexColumn::Packer *_packer;
   int _stride;
 

+ 81 - 78
panda/src/gobj/geomVertexWriter.I

@@ -27,9 +27,8 @@
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 GeomVertexWriter() :
-  _data_writer(NULL),
-  _array_writer(NULL),
-  _owns_writer(false)
+  _vertex_data(NULL),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
 }
@@ -42,9 +41,8 @@ GeomVertexWriter() :
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexData *vertex_data) :
-  _data_writer(new GeomVertexDataPipelineWriter(vertex_data, true, Thread::get_current_thread())),
-  _array_writer(NULL),
-  _owns_writer(true)
+  _vertex_data(vertex_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
 }
@@ -58,9 +56,8 @@ GeomVertexWriter(GeomVertexData *vertex_data) :
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexData *vertex_data, const string &name) :
-  _data_writer(new GeomVertexDataPipelineWriter(vertex_data, true, Thread::get_current_thread())),
-  _array_writer(NULL),
-  _owns_writer(true)
+  _vertex_data(vertex_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
   set_column(name);
@@ -75,9 +72,8 @@ GeomVertexWriter(GeomVertexData *vertex_data, const string &name) :
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexData *vertex_data, const InternalName *name) :
-  _data_writer(new GeomVertexDataPipelineWriter(vertex_data, true, Thread::get_current_thread())),
-  _array_writer(NULL),
-  _owns_writer(true)
+  _vertex_data(vertex_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
   set_column(name);
@@ -91,9 +87,8 @@ GeomVertexWriter(GeomVertexData *vertex_data, const InternalName *name) :
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexArrayData *array_data) :
-  _data_writer(NULL),
-  _array_writer(new GeomVertexArrayDataPipelineWriter(array_data, true, Thread::get_current_thread())),
-  _owns_writer(true)
+  _array_data(array_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
 }
@@ -106,9 +101,8 @@ GeomVertexWriter(GeomVertexArrayData *array_data) :
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexArrayData *array_data, int column) :
-  _data_writer(NULL),
-  _array_writer(new GeomVertexArrayDataPipelineWriter(array_data, true, Thread::get_current_thread())),
-  _owns_writer(true)
+  _array_data(array_data),
+  _current_thread(Thread::get_current_thread())
 {
   initialize();
   set_column(column);
@@ -122,28 +116,29 @@ GeomVertexWriter(GeomVertexArrayData *array_data, int column) :
 //               writer specifically to process the named data type.
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
-GeomVertexWriter(GeomVertexDataPipelineWriter *data_writer, 
+GeomVertexWriter(GeomVertexDataPipelineWriter *data_writer,
                  const InternalName *name) :
-  _data_writer(data_writer),
-  _array_writer(NULL),
-  _owns_writer(false)
+  _vertex_data(data_writer->get_object()),
+  _current_thread(data_writer->get_current_thread())
 {
   initialize();
-  set_column(name);
+  const GeomVertexFormat *format = data_writer->get_format();
+  set_vertex_column(format->get_array_with(name),
+                    format->get_column(name),
+                    data_writer);
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexWriter::Copy Constructor
 //       Access: Published
-//  Description: The copy constructor steals ownership of the writer
-//               pointer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 GeomVertexWriter(const GeomVertexWriter &copy) :
-  _data_writer(copy._data_writer),
+  _vertex_data(copy._vertex_data),
   _array(copy._array),
-  _array_writer(copy._array_writer),
-  _owns_writer(copy._owns_writer),
+  _array_data(copy._array_data),
+  _current_thread(copy._current_thread),
   _packer(copy._packer),
   _stride(copy._stride),
   _pointer_begin(copy._pointer_begin),
@@ -151,29 +146,25 @@ GeomVertexWriter(const GeomVertexWriter &copy) :
   _pointer(copy._pointer),
   _start_row(copy._start_row)
 {
-  ((GeomVertexWriter &)copy)._owns_writer = false;
 }
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomVertexWriter::Copy Assignment Operator
 //       Access: Published
-//  Description: The copy constructor steals ownership of the writer
-//               pointer.
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
 operator = (const GeomVertexWriter &copy) {
-  _data_writer = copy._data_writer;
+  _vertex_data = copy._vertex_data;
   _array = copy._array;
-  _array_writer = copy._array_writer;
-  _owns_writer = copy._owns_writer;
+  _array_data = copy._array_data;
+  _current_thread = copy._current_thread;
   _packer = copy._packer;
   _stride = copy._stride;
   _pointer_begin = copy._pointer_begin;
   _pointer_end = copy._pointer_end;
   _pointer = copy._pointer;
   _start_row = copy._start_row;
-
-  ((GeomVertexWriter &)copy)._owns_writer = false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -183,9 +174,6 @@ operator = (const GeomVertexWriter &copy) {
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 ~GeomVertexWriter() {
-  if (_owns_writer) {
-    clear_writer();
-  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -197,10 +185,7 @@ INLINE GeomVertexWriter::
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexData *GeomVertexWriter::
 get_vertex_data() const {
-  if (_data_writer != (GeomVertexDataPipelineWriter *)NULL) {
-    return _data_writer->get_object();
-  }
-  return NULL;
+  return _vertex_data;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -211,7 +196,18 @@ get_vertex_data() const {
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexArrayData *GeomVertexWriter::
 get_array_data() const {
-  return _array_writer->get_object();
+  return _array_data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexWriter::get_current_thread
+//       Access: Published
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+INLINE Thread *GeomVertexWriter::
+get_current_thread() const {
+  return _current_thread;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -229,12 +225,18 @@ get_array_data() const {
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomVertexWriter::
 set_column(int column) {
-  if (_data_writer != (GeomVertexDataPipelineWriter *)NULL) {
-    return set_column(_data_writer->get_format()->get_array_with(column),
-                      _data_writer->get_format()->get_column(column));
+  if (_vertex_data != (GeomVertexData *)NULL) {
+    GeomVertexDataPipelineWriter writer(_vertex_data, true, _current_thread);
+    writer.check_array_writers();
+    const GeomVertexFormat *format = writer.get_format();
+    return set_vertex_column(format->get_array_with(column),
+                             format->get_column(column),
+                             &writer);
   }
-  if (_array_writer != (GeomVertexArrayDataPipelineWriter *)NULL) {
-    return set_column(0, _array_writer->get_array_format()->get_column(column));
+  if (_array_data != (GeomVertexArrayData *)NULL) {
+    GeomVertexArrayDataPipelineWriter writer(_array_data, true, _current_thread);
+    return set_array_column(writer.get_array_format()->get_column(column),
+                            &writer);
   }
   return false;
 }
@@ -272,14 +274,19 @@ set_column(const string &name) {
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomVertexWriter::
 set_column(const InternalName *name) {
-  if (_data_writer != (GeomVertexDataPipelineWriter *)NULL) {
-    return set_column(_data_writer->get_format()->get_array_with(name),
-                      _data_writer->get_format()->get_column(name));
+  if (_vertex_data != (GeomVertexData *)NULL) {
+    GeomVertexDataPipelineWriter writer(_vertex_data, true, _current_thread);
+    writer.check_array_writers();
+    const GeomVertexFormat *format = writer.get_format();
+    return set_vertex_column(format->get_array_with(name),
+                             format->get_column(name),
+                             &writer);
   }
-  if (_array_writer != (GeomVertexArrayDataPipelineWriter *)NULL) {
-    return set_column(0, _array_writer->get_array_format()->get_column(name));
+  if (_array_data != (GeomVertexArrayData *)NULL) {
+    GeomVertexArrayDataPipelineWriter writer(_array_data, true, _current_thread);
+    return set_array_column(writer.get_array_format()->get_column(name),
+                            &writer);
   }
-
   return false;
 }
 
@@ -801,17 +808,9 @@ get_packer() const {
 //               and sets the internal pointer to the indicated row.
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexWriter::
-set_pointer(int row) {
-  if (_data_writer != (const GeomVertexDataPipelineWriter *)NULL) {
-    _data_writer->modify_array(_array);
-    GeomVertexArrayDataPipelineWriter *array_data = _data_writer->get_array_writer(_array);
-    _pointer_begin = array_data->modify_data();
-    _pointer_end = _pointer_begin + array_data->get_data_size_bytes();
-
-  } else {
-    _pointer_begin = _array_writer->modify_data();
-    _pointer_end = _pointer_begin + _array_writer->get_data_size_bytes();
-  }
+set_pointer(int row, GeomVertexArrayDataPipelineWriter *array_writer) {
+  _pointer_begin = array_writer->modify_data();
+  _pointer_end = _pointer_begin + array_writer->get_data_size_bytes();
   quick_set_pointer(row);
 }
 
@@ -827,11 +826,11 @@ quick_set_pointer(int row) {
   nassertv(has_column());
 
 #ifdef _DEBUG
-  if (_data_writer != (const GeomVertexDataPipelineWriter *)NULL) {
-    GeomVertexArrayDataPipelineWriter *array_writer = _data_writer->get_array_writer(_array);
-    nassertv(_pointer_begin == array_writer->get_data());
+  if (_vertex_data != (const GeomVertexData *)NULL) {
+    const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
+    nassertv(_pointer_begin == array_data->get_data());
   } else {
-    nassertv(_pointer_begin == _array_writer->get_data());
+    nassertv(_pointer_begin == _array_data->get_data());
   }
 #endif
 
@@ -848,11 +847,11 @@ INLINE unsigned char *GeomVertexWriter::
 inc_pointer() {
 #ifdef _DEBUG
   nassertr(_pointer < _pointer_end, empty_buffer);
-  if (_data_writer != (GeomVertexDataPipelineWriter *)NULL){ 
-    GeomVertexArrayDataPipelineWriter *array_writer = _data_writer->get_array_writer(_array);
-    nassertr(_pointer >= array_writer->get_data().p() && _pointer < array_writer->get_data().p() + array_writer->get_data_size_bytes(), empty_buffer);
+  if (_vertex_data != (GeomVertexData *)NULL){ 
+    const GeomVertexArrayData *array_data = _vertex_data->get_array(_array);
+    nassertr(_pointer >= array_data->get_data().p() && _pointer < array_data->get_data().p() + array_data->get_data_size_bytes(), empty_buffer);
   } else {
-    nassertr(_pointer >= _array_writer->get_data().p() && _pointer < _array_writer->get_data().p() + _array_writer->get_data_size_bytes(), empty_buffer);
+    nassertr(_pointer >= _array_data->get_data().p() && _pointer < _array_data->get_data().p() + _array_data->get_data_size_bytes(), empty_buffer);
   }
 #endif
 
@@ -874,12 +873,16 @@ inc_add_pointer() {
   if (_pointer >= _pointer_end) {
     // Reset the data pointer.
     int write_row = get_write_row();
-    if (_data_writer != (GeomVertexDataPipelineWriter *)NULL) {
-      _data_writer->set_num_rows(max(write_row + 1, _data_writer->get_num_rows()));
+    if (_vertex_data != (GeomVertexData *)NULL) {
+      GeomVertexDataPipelineWriter writer(_vertex_data, true, _current_thread);
+      writer.check_array_writers();
+      writer.set_num_rows(max(write_row + 1, writer.get_num_rows()));
+      set_pointer(write_row, writer.get_array_writer(_array));
     } else {
-      _array_writer->set_num_rows(max(write_row + 1, _array_writer->get_num_rows()));
+      GeomVertexArrayDataPipelineWriter writer(_array_data, true, _current_thread);
+      writer.set_num_rows(max(write_row + 1, writer.get_num_rows()));
+      set_pointer(write_row, &writer);
     }
-    set_pointer(write_row);
   }
   return inc_pointer();
 }

+ 55 - 38
panda/src/gobj/geomVertexWriter.cxx

@@ -40,8 +40,8 @@ unsigned char GeomVertexWriter::empty_buffer[100] = { 0 };
 ////////////////////////////////////////////////////////////////////
 bool GeomVertexWriter::
 set_column(int array, const GeomVertexColumn *column) {
-  if (_data_writer == (GeomVertexDataPipelineWriter *)NULL &&
-      _array_writer == (GeomVertexArrayDataPipelineWriter *)NULL) {
+  if (_vertex_data == (GeomVertexData *)NULL &&
+      _array_data == (GeomVertexArrayData *)NULL) {
     return false;
   }
 
@@ -56,25 +56,18 @@ set_column(int array, const GeomVertexColumn *column) {
     return false;
   }
 
-  if (_data_writer != (GeomVertexDataPipelineWriter *)NULL) {
-#ifndef NDEBUG
-    _array = -1;
-    _packer = NULL;
-    nassertr(array >= 0 && array < _data_writer->get_num_arrays(), false);
-#endif
-    _array = array;
-    GeomVertexArrayDataPipelineWriter *array_writer =_data_writer->get_array_writer(_array);
-    _stride = array_writer->get_array_format()->get_stride();
-
-  } else {
-    _stride = _array_writer->get_array_format()->get_stride();
+  if (_vertex_data != (GeomVertexData *)NULL) {
+    GeomVertexDataPipelineWriter writer(_vertex_data, true, _current_thread);
+    writer.check_array_writers();
+    return set_vertex_column(array, column, &writer);
+  }
+  if (_array_data != (GeomVertexArrayData *)NULL) {
+    GeomVertexArrayDataPipelineWriter writer(_array_data, true, _current_thread);
+    return set_array_column(column, &writer);
   }
 
-  _packer = column->_packer;
-  
-  set_pointer(_start_row);
-  
-  return true;
+  // No data is associated with the Writer.
+  return false;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -103,10 +96,6 @@ output(ostream &out) const {
 ////////////////////////////////////////////////////////////////////
 void GeomVertexWriter::
 initialize() {
-  if (_data_writer != (const GeomVertexDataPipelineWriter *)NULL) {
-    _data_writer->check_array_writers();
-  }
-
   _array = 0;
   _packer = NULL;
   _pointer_begin = NULL;
@@ -116,23 +105,51 @@ initialize() {
 }
 
 ////////////////////////////////////////////////////////////////////
-//     Function: GeomVertexWriter::clear_writer
+//     Function: GeomVertexWriter::set_vertex_column
 //       Access: Private
-//  Description: Destructs the GeomVertexDataPipelineWriter, when
-//               necessary, for instance when this object destructs.
+//  Description: Internal method to set the column to column from the
+//               indicated array, assuming we have a GeomVertexData
 ////////////////////////////////////////////////////////////////////
-void GeomVertexWriter::
-clear_writer() {
-  nassertv(_owns_writer);
+bool GeomVertexWriter::
+set_vertex_column(int array, const GeomVertexColumn *column,
+                  GeomVertexDataPipelineWriter *data_writer) {
+  nassertr(column != (const GeomVertexColumn *)NULL, false);
+  nassertr(_vertex_data != (GeomVertexData *)NULL, false);
 
-  if (_data_writer != (GeomVertexDataPipelineWriter *)NULL) {
-    delete _data_writer;
-    _data_writer = NULL;
-  } else {
-    nassertv(_array_writer != (GeomVertexArrayDataPipelineWriter *)NULL);
-    delete _array_writer;
-    _array_writer = NULL;
-  }
+#ifndef NDEBUG
+  _array = -1;
+  _packer = NULL;
+  nassertr(array >= 0 && array < _vertex_data->get_num_arrays(), false);
+#endif
+
+  _array = array;
+  GeomVertexArrayDataPipelineWriter *array_writer = 
+    data_writer->get_array_writer(_array);
+  _stride = array_writer->get_array_format()->get_stride();
 
-  _owns_writer = false;
+  _packer = column->_packer;
+  set_pointer(_start_row, array_writer);
+  
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GeomVertexWriter::set_array_column
+//       Access: Private
+//  Description: Internal method to set the column to column from the
+//               indicated array, assuming we have a
+//               GeomVertexArrayData.
+////////////////////////////////////////////////////////////////////
+bool GeomVertexWriter::
+set_array_column(const GeomVertexColumn *column,
+                 GeomVertexArrayDataPipelineWriter *array_writer) {
+  nassertr(column != (const GeomVertexColumn *)NULL, false);
+  nassertr(_array_data != (GeomVertexArrayData *)NULL, false);
+
+  _stride = array_writer->get_array_format()->get_stride();
+
+  _packer = column->_packer;
+  set_pointer(_start_row, array_writer);
+  
+  return true;
 }

+ 11 - 5
panda/src/gobj/geomVertexWriter.h

@@ -93,6 +93,7 @@ PUBLISHED:
 
   INLINE GeomVertexData *get_vertex_data() const;
   INLINE GeomVertexArrayData *get_array_data() const;
+  INLINE Thread *get_current_thread() const;
 
   INLINE bool set_column(int column);
   INLINE bool set_column(const string &name);
@@ -150,23 +151,28 @@ private:
   class Writer;
 
   void initialize();
-  void clear_writer();
 
-  INLINE void set_pointer(int row);
+  INLINE void set_pointer(int row, 
+                          GeomVertexArrayDataPipelineWriter *array_writer);
   INLINE void quick_set_pointer(int row);
   INLINE unsigned char *inc_pointer();
   INLINE unsigned char *inc_add_pointer();
 
+  bool set_vertex_column(int array, const GeomVertexColumn *column,
+                         GeomVertexDataPipelineWriter *data_writer);
+  bool set_array_column(const GeomVertexColumn *column,
+                        GeomVertexArrayDataPipelineWriter *array_writer);
+
   // It is important that we only store *one* of the following two
   // pointers.  If we are storing a GeomVertexData/array index, we
   // must not keep a pointer to the particular ArrayData we are
   // working on (if we do, it may result in an extra copy of the data
   // due to holding the reference count).
-  GeomVertexDataPipelineWriter *_data_writer;
+  PT(GeomVertexData) _vertex_data;
   int _array;
-  GeomVertexArrayDataPipelineWriter *_array_writer;
-  bool _owns_writer;
+  PT(GeomVertexArrayData) _array_data;
 
+  Thread *_current_thread;
   GeomVertexColumn::Packer *_packer;
   int _stride;