Browse Source

preserve current_thread instead of pipeline_stage in PipelineReader objects

David Rose 19 years ago
parent
commit
ce3afa5f53
39 changed files with 870 additions and 508 deletions
  1. 15 8
      panda/src/gobj/geom.I
  2. 11 11
      panda/src/gobj/geom.cxx
  3. 3 3
      panda/src/gobj/geom.h
  4. 66 17
      panda/src/gobj/geomPrimitive.I
  5. 0 44
      panda/src/gobj/geomPrimitive.cxx
  6. 4 4
      panda/src/gobj/geomPrimitive.h
  7. 33 19
      panda/src/gobj/geomVertexArrayData.I
  8. 5 5
      panda/src/gobj/geomVertexArrayData.h
  9. 33 21
      panda/src/gobj/geomVertexData.I
  10. 5 5
      panda/src/gobj/geomVertexData.cxx
  11. 6 6
      panda/src/gobj/geomVertexData.h
  12. 5 5
      panda/src/gobj/geomVertexReader.I
  13. 5 5
      panda/src/gobj/geomVertexWriter.I
  14. 33 5
      panda/src/pipeline/cycleDataReader.I
  15. 5 1
      panda/src/pipeline/cycleDataReader.h
  16. 32 4
      panda/src/pipeline/cycleDataStageReader.I
  17. 4 1
      panda/src/pipeline/cycleDataStageReader.h
  18. 42 10
      panda/src/pipeline/cycleDataStageWriter.I
  19. 7 2
      panda/src/pipeline/cycleDataStageWriter.h
  20. 48 22
      panda/src/pipeline/cycleDataWriter.I
  21. 8 2
      panda/src/pipeline/cycleDataWriter.h
  22. 45 0
      panda/src/pipeline/mutexDebug.I
  23. 2 0
      panda/src/pipeline/mutexDebug.h
  24. 58 54
      panda/src/pipeline/pipelineCycler.I
  25. 12 11
      panda/src/pipeline/pipelineCycler.h
  26. 57 56
      panda/src/pipeline/pipelineCyclerDummyImpl.I
  27. 14 14
      panda/src/pipeline/pipelineCyclerDummyImpl.h
  28. 48 48
      panda/src/pipeline/pipelineCyclerTrivialImpl.I
  29. 18 14
      panda/src/pipeline/pipelineCyclerTrivialImpl.h
  30. 85 69
      panda/src/pipeline/pipelineCyclerTrueImpl.I
  31. 4 4
      panda/src/pipeline/pipelineCyclerTrueImpl.cxx
  32. 16 12
      panda/src/pipeline/pipelineCyclerTrueImpl.h
  33. 61 2
      panda/src/pipeline/reMutexDirect.I
  34. 50 16
      panda/src/pipeline/reMutexDirect.cxx
  35. 7 3
      panda/src/pipeline/reMutexDirect.h
  36. 15 0
      panda/src/pipeline/reMutexHolder.I
  37. 3 0
      panda/src/pipeline/reMutexHolder.h
  38. 3 3
      panda/src/putil/bamReader.cxx
  39. 2 2
      panda/src/putil/bamWriter.cxx

+ 15 - 8
panda/src/gobj/geom.I

@@ -467,15 +467,17 @@ CData(const Geom::CData &copy) :
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomPipelineReader::
 INLINE GeomPipelineReader::
-GeomPipelineReader(const Geom *object, int pipeline_stage) :
+GeomPipelineReader(const Geom *object, Thread *current_thread) :
   _object(object),
   _object(object),
-  _pipeline_stage(pipeline_stage),
-  _cdata(object->_cycler.read_stage(pipeline_stage))
+  _current_thread(current_thread),
+  _cdata(object->_cycler.read(current_thread))
 {
 {
+#ifdef _DEBUG
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   nassertv(_cdata->test_ref_count_nonzero());
   nassertv(_cdata->test_ref_count_nonzero());
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
+#endif // _DEBUG
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -505,13 +507,18 @@ operator = (const GeomPipelineReader &) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomPipelineReader::
 INLINE GeomPipelineReader::
 ~GeomPipelineReader() {
 ~GeomPipelineReader() {
+#ifdef _DEBUG
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   nassertv(_cdata->test_ref_count_nonzero());
   nassertv(_cdata->test_ref_count_nonzero());
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
-  _object->_cycler.release_read_stage(_pipeline_stage, _cdata);
+#endif // _DEBUG
+  _object->_cycler.release_read(_cdata);
+
+#ifdef _DEBUG
   _object = NULL;
   _object = NULL;
   _cdata = NULL;
   _cdata = NULL;
+#endif  // _DEBUG
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -525,13 +532,13 @@ get_object() const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GeomPipelineReader::get_pipeline_stage
+//     Function: GeomPipelineReader::get_current_thread
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE int GeomPipelineReader::
-get_pipeline_stage() const {
-  return _pipeline_stage;
+INLINE Thread *GeomPipelineReader::
+get_current_thread() const {
+  return _current_thread;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 11 - 11
panda/src/gobj/geom.cxx

@@ -685,9 +685,9 @@ transform_vertices(const LMatrix4f &mat) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool Geom::
 bool Geom::
 check_valid() const {
 check_valid() const {
-  int pipeline_stage = Thread::get_current_pipeline_stage();
-  GeomPipelineReader geom_reader(this, pipeline_stage);
-  GeomVertexDataPipelineReader data_reader(geom_reader.get_vertex_data(), pipeline_stage);
+  Thread *current_thread = Thread::get_current_thread();
+  GeomPipelineReader geom_reader(this, current_thread);
+  GeomVertexDataPipelineReader data_reader(geom_reader.get_vertex_data(), current_thread);
   data_reader.check_array_readers();
   data_reader.check_array_readers();
   return geom_reader.check_valid(&data_reader);
   return geom_reader.check_valid(&data_reader);
 }
 }
@@ -702,9 +702,9 @@ check_valid() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool Geom::
 bool Geom::
 check_valid(const GeomVertexData *vertex_data) const {
 check_valid(const GeomVertexData *vertex_data) const {
-  int pipeline_stage = Thread::get_current_pipeline_stage();
-  GeomPipelineReader geom_reader(this, pipeline_stage);
-  GeomVertexDataPipelineReader data_reader(vertex_data, pipeline_stage);
+  Thread *current_thread = Thread::get_current_thread();
+  GeomPipelineReader geom_reader(this, current_thread);
+  GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
   data_reader.check_array_readers();
   data_reader.check_array_readers();
   return geom_reader.check_valid(&data_reader);
   return geom_reader.check_valid(&data_reader);
 }
 }
@@ -931,11 +931,11 @@ prepare_now(PreparedGraphicsObjects *prepared_objects,
 void Geom::
 void Geom::
 draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
 draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
      const GeomVertexData *vertex_data) const {
      const GeomVertexData *vertex_data) const {
-  int pipeline_stage = Thread::get_current_pipeline_stage();
-  GeomPipelineReader geom_reader(this, pipeline_stage);
+  Thread *current_thread = Thread::get_current_thread();
+  GeomPipelineReader geom_reader(this, current_thread);
   geom_reader.check_usage_hint();
   geom_reader.check_usage_hint();
 
 
-  GeomVertexDataPipelineReader data_reader(vertex_data, pipeline_stage);
+  GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
   data_reader.check_array_readers();
   data_reader.check_array_readers();
 
 
   geom_reader.draw(gsg, munger, &data_reader);
   geom_reader.draw(gsg, munger, &data_reader);
@@ -1343,7 +1343,7 @@ check_valid(const GeomVertexDataPipelineReader *data_reader) const {
        pi != _cdata->_primitives.end();
        pi != _cdata->_primitives.end();
        ++pi) {
        ++pi) {
     const GeomPrimitive *primitive = (*pi);
     const GeomPrimitive *primitive = (*pi);
-    GeomPrimitivePipelineReader reader(primitive, _pipeline_stage);
+    GeomPrimitivePipelineReader reader(primitive, _current_thread);
     reader.check_minmax();
     reader.check_minmax();
     if (!reader.check_valid(data_reader)) {
     if (!reader.check_valid(data_reader)) {
       return false;
       return false;
@@ -1368,7 +1368,7 @@ draw(GraphicsStateGuardianBase *gsg, const GeomMunger *munger,
          pi != _cdata->_primitives.end();
          pi != _cdata->_primitives.end();
          ++pi) {
          ++pi) {
       const GeomPrimitive *primitive = (*pi);
       const GeomPrimitive *primitive = (*pi);
-      GeomPrimitivePipelineReader reader(primitive, _pipeline_stage);
+      GeomPrimitivePipelineReader reader(primitive, _current_thread);
       if (reader.get_num_vertices() != 0) {
       if (reader.get_num_vertices() != 0) {
         reader.check_minmax();
         reader.check_minmax();
         primitive->draw(gsg, &reader);
         primitive->draw(gsg, &reader);

+ 3 - 3
panda/src/gobj/geom.h

@@ -302,7 +302,7 @@ private:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GeomPipelineReader : public GeomEnums {
 class EXPCL_PANDA GeomPipelineReader : public GeomEnums {
 public:
 public:
-  INLINE GeomPipelineReader(const Geom *object, int pipeline_stage);
+  INLINE GeomPipelineReader(const Geom *object, Thread *current_thread);
 private:
 private:
   INLINE GeomPipelineReader(const GeomPipelineReader &copy);
   INLINE GeomPipelineReader(const GeomPipelineReader &copy);
   INLINE void operator = (const GeomPipelineReader &copy);
   INLINE void operator = (const GeomPipelineReader &copy);
@@ -312,7 +312,7 @@ public:
   ALLOC_DELETED_CHAIN(GeomPipelineReader);
   ALLOC_DELETED_CHAIN(GeomPipelineReader);
 
 
   INLINE const Geom *get_object() const;
   INLINE const Geom *get_object() const;
-  INLINE int get_pipeline_stage() const;
+  INLINE Thread *get_current_thread() const;
 
 
   INLINE void check_usage_hint() const;
   INLINE void check_usage_hint() const;
 
 
@@ -333,7 +333,7 @@ public:
 
 
 private:
 private:
   const Geom *_object;
   const Geom *_object;
-  int _pipeline_stage;
+  Thread *_current_thread;
   const Geom::CData *_cdata;
   const Geom::CData *_cdata;
 };
 };
 
 

+ 66 - 17
panda/src/gobj/geomPrimitive.I

@@ -111,7 +111,7 @@ is_composite() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomPrimitive::
 INLINE bool GeomPrimitive::
 is_indexed() const {
 is_indexed() const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   return reader.is_indexed();
   return reader.is_indexed();
 }
 }
 
 
@@ -126,7 +126,7 @@ is_indexed() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitive::
 INLINE int GeomPrimitive::
 get_first_vertex() const {
 get_first_vertex() const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   return reader.get_first_vertex();
   return reader.get_first_vertex();
 }
 }
 
 
@@ -138,7 +138,7 @@ get_first_vertex() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitive::
 INLINE int GeomPrimitive::
 get_num_vertices() const {
 get_num_vertices() const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   return reader.get_num_vertices();
   return reader.get_num_vertices();
 }
 }
 
 
@@ -149,7 +149,7 @@ get_num_vertices() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitive::
 INLINE int GeomPrimitive::
 get_vertex(int i) const {
 get_vertex(int i) const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   return reader.get_vertex(i);
   return reader.get_vertex(i);
 }
 }
 
 
@@ -162,7 +162,7 @@ get_vertex(int i) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitive::
 INLINE int GeomPrimitive::
 get_num_primitives() const {
 get_num_primitives() const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   return reader.get_num_primitives();
   return reader.get_num_primitives();
 }
 }
 
 
@@ -214,7 +214,7 @@ get_primitive_num_faces(int n) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitive::
 INLINE int GeomPrimitive::
 get_min_vertex() const {
 get_min_vertex() const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   reader.check_minmax();
   reader.check_minmax();
   return reader.get_min_vertex();
   return reader.get_min_vertex();
 }
 }
@@ -227,7 +227,7 @@ get_min_vertex() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitive::
 INLINE int GeomPrimitive::
 get_max_vertex() const {
 get_max_vertex() const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   reader.check_minmax();
   reader.check_minmax();
   return reader.get_max_vertex();
   return reader.get_max_vertex();
 }
 }
@@ -267,10 +267,10 @@ get_modified() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomPrimitive::
 INLINE bool GeomPrimitive::
 check_valid(const GeomVertexData *vertex_data) const {
 check_valid(const GeomVertexData *vertex_data) const {
-  int pipeline_stage = Thread::get_current_pipeline_stage();
-  GeomPrimitivePipelineReader reader(this, pipeline_stage);
+  Thread *current_thread = Thread::get_current_thread();
+  GeomPrimitivePipelineReader reader(this, current_thread);
   reader.check_minmax();
   reader.check_minmax();
-  GeomVertexDataPipelineReader data_reader(vertex_data, pipeline_stage);
+  GeomVertexDataPipelineReader data_reader(vertex_data, current_thread);
   data_reader.check_array_readers();
   data_reader.check_array_readers();
   return reader.check_valid(&data_reader);
   return reader.check_valid(&data_reader);
 }
 }
@@ -299,7 +299,7 @@ get_vertices() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomPrimitive::
 INLINE int GeomPrimitive::
 get_index_stride() const {
 get_index_stride() const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   return reader.get_index_stride();
   return reader.get_index_stride();
 }
 }
 
 
@@ -346,7 +346,7 @@ get_ends() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const GeomVertexArrayData *GeomPrimitive::
 INLINE const GeomVertexArrayData *GeomPrimitive::
 get_mins() const {
 get_mins() const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   reader.check_minmax();
   reader.check_minmax();
   return reader.get_mins();
   return reader.get_mins();
 }
 }
@@ -364,7 +364,7 @@ get_mins() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const GeomVertexArrayData *GeomPrimitive::
 INLINE const GeomVertexArrayData *GeomPrimitive::
 get_maxs() const {
 get_maxs() const {
-  GeomPrimitivePipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomPrimitivePipelineReader reader(this, Thread::get_current_thread());
   reader.check_minmax();
   reader.check_minmax();
   return reader.get_maxs();
   return reader.get_maxs();
 }
 }
@@ -468,6 +468,29 @@ CData(const GeomPrimitive::CData &copy) :
   _max_vertex(copy._max_vertex)
   _max_vertex(copy._max_vertex)
 {
 {
 }
 }
+////////////////////////////////////////////////////////////////////
+//     Function: GeomPrimitivePipelineReader::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE GeomPrimitivePipelineReader::
+GeomPrimitivePipelineReader(const GeomPrimitive *object, 
+                            Thread *current_thread) :
+  _object(object),
+  _current_thread(current_thread),
+  _cdata(object->_cycler.read(current_thread)),
+  _vertices_reader(NULL)
+{
+  nassertv(_object->test_ref_count_nonzero());
+#ifdef DO_PIPELINING
+  nassertv(_cdata->test_ref_count_nonzero());
+#endif  // DO_PIPELINING
+  if (_cdata->_vertices != (GeomVertexArrayData *)NULL) {
+    _vertices_reader =
+      new GeomVertexArrayDataPipelineReader(_cdata->_vertices, _current_thread);
+    nassertv(_vertices_reader->get_object() == _cdata->_vertices);
+  }
+}
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::Copy Constructor
 //     Function: GeomPrimitivePipelineReader::Copy Constructor
@@ -489,6 +512,32 @@ operator = (const GeomPrimitivePipelineReader &) {
   nassertv(false);
   nassertv(false);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GeomPrimitivePipelineReader::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE GeomPrimitivePipelineReader::
+~GeomPrimitivePipelineReader() {
+  if (_vertices_reader != (GeomVertexArrayDataPipelineReader *)NULL) {
+    nassertv(_vertices_reader->get_object() == _cdata->_vertices);
+    delete _vertices_reader;
+  }
+#ifdef _DEBUG
+  nassertv(_object->test_ref_count_nonzero());
+#ifdef DO_PIPELINING
+  nassertv(_cdata->test_ref_count_nonzero());
+#endif  // DO_PIPELINING
+#endif // _DEBUG
+  _object->_cycler.release_read(_cdata);
+
+#ifdef _DEBUG
+  _vertices_reader = NULL;
+  _object = NULL;
+  _cdata = NULL;
+#endif  // _DEBUG
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_object
 //     Function: GeomPrimitivePipelineReader::get_object
 //       Access: Public
 //       Access: Public
@@ -500,13 +549,13 @@ get_object() const {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GeomPrimitivePipelineReader::get_pipeline_stage
+//     Function: GeomPrimitivePipelineReader::get_current_thread
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE int GeomPrimitivePipelineReader::
-get_pipeline_stage() const {
-  return _pipeline_stage;
+INLINE Thread *GeomPrimitivePipelineReader::
+get_current_thread() const {
+  return _current_thread;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 0 - 44
panda/src/gobj/geomPrimitive.cxx

@@ -1483,50 +1483,6 @@ fillin(DatagramIterator &scan, BamReader *manager) {
   _got_minmax = false;
   _got_minmax = false;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: GeomPrimitivePipelineReader::Constructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-GeomPrimitivePipelineReader::
-GeomPrimitivePipelineReader(const GeomPrimitive *object, 
-                            int pipeline_stage) :
-  _object(object),
-  _pipeline_stage(pipeline_stage),
-  _cdata(object->_cycler.read_stage(pipeline_stage)),
-  _vertices_reader(NULL)
-{
-  nassertv(_object->test_ref_count_nonzero());
-#ifdef DO_PIPELINING
-  nassertv(_cdata->test_ref_count_nonzero());
-#endif  // DO_PIPELINING
-  if (_cdata->_vertices != (GeomVertexArrayData *)NULL) {
-    _vertices_reader =
-      new GeomVertexArrayDataPipelineReader(_cdata->_vertices, _pipeline_stage);
-    nassertv(_vertices_reader->get_object() == _cdata->_vertices);
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GeomPrimitivePipelineReader::Destructor
-//       Access: Public
-//  Description:
-////////////////////////////////////////////////////////////////////
-GeomPrimitivePipelineReader::
-~GeomPrimitivePipelineReader() {
-  if (_vertices_reader != (GeomVertexArrayDataPipelineReader *)NULL) {
-    nassertv(_vertices_reader->get_object() == _cdata->_vertices);
-    delete _vertices_reader;
-    _vertices_reader = NULL;
-  }
-  nassertv(_object->test_ref_count_nonzero());
-#ifdef DO_PIPELINING
-  nassertv(_cdata->test_ref_count_nonzero());
-#endif  // DO_PIPELINING
-  _object->_cycler.release_read_stage(_pipeline_stage, _cdata);
-  _object = NULL;
-  _cdata = NULL;
-}
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GeomPrimitivePipelineReader::get_first_vertex
 //     Function: GeomPrimitivePipelineReader::get_first_vertex

+ 4 - 4
panda/src/gobj/geomPrimitive.h

@@ -296,17 +296,17 @@ private:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GeomPrimitivePipelineReader : public GeomEnums {
 class EXPCL_PANDA GeomPrimitivePipelineReader : public GeomEnums {
 public:
 public:
-  GeomPrimitivePipelineReader(const GeomPrimitive *object, int pipeline_stage);
+  INLINE GeomPrimitivePipelineReader(const GeomPrimitive *object, Thread *current_thread);
 private:
 private:
   INLINE GeomPrimitivePipelineReader(const GeomPrimitivePipelineReader &copy);
   INLINE GeomPrimitivePipelineReader(const GeomPrimitivePipelineReader &copy);
   INLINE void operator = (const GeomPrimitivePipelineReader &copy);
   INLINE void operator = (const GeomPrimitivePipelineReader &copy);
 
 
 public:
 public:
-  ~GeomPrimitivePipelineReader();
+  INLINE ~GeomPrimitivePipelineReader();
   ALLOC_DELETED_CHAIN(GeomPrimitivePipelineReader);
   ALLOC_DELETED_CHAIN(GeomPrimitivePipelineReader);
 
 
   INLINE const GeomPrimitive *get_object() const;
   INLINE const GeomPrimitive *get_object() const;
-  INLINE int get_pipeline_stage() const;
+  INLINE Thread *get_current_thread() const;
 
 
   INLINE void check_minmax() const;
   INLINE void check_minmax() const;
 
 
@@ -331,7 +331,7 @@ public:
   
   
 private:
 private:
   const GeomPrimitive *_object;
   const GeomPrimitive *_object;
-  int _pipeline_stage;
+  Thread *_current_thread;
   const GeomPrimitive::CData *_cdata;
   const GeomPrimitive::CData *_cdata;
   GeomVertexArrayDataPipelineReader *_vertices_reader;
   GeomVertexArrayDataPipelineReader *_vertices_reader;
 };
 };

+ 33 - 19
panda/src/gobj/geomVertexArrayData.I

@@ -62,7 +62,7 @@ has_column(const InternalName *name) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomVertexArrayData::
 INLINE int GeomVertexArrayData::
 get_num_rows() const {
 get_num_rows() const {
-  GeomVertexArrayDataPipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomVertexArrayDataPipelineReader reader(this, Thread::get_current_thread());
   return reader.get_num_rows();
   return reader.get_num_rows();
 }
 }
 
 
@@ -89,7 +89,7 @@ get_num_rows() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomVertexArrayData::
 INLINE bool GeomVertexArrayData::
 set_num_rows(int n) {
 set_num_rows(int n) {
-  GeomVertexArrayDataPipelineWriter writer(this, Thread::get_current_pipeline_stage(), true);
+  GeomVertexArrayDataPipelineWriter writer(this, true, Thread::get_current_thread());
   return writer.set_num_rows(n);
   return writer.set_num_rows(n);
 }
 }
 
 
@@ -154,7 +154,7 @@ get_data() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE PTA_uchar GeomVertexArrayData::
 INLINE PTA_uchar GeomVertexArrayData::
 modify_data() {
 modify_data() {
-  GeomVertexArrayDataPipelineWriter writer(this, Thread::get_current_pipeline_stage(), true);
+  GeomVertexArrayDataPipelineWriter writer(this, true, Thread::get_current_thread());
   return writer.modify_data();
   return writer.modify_data();
 }
 }
 
 
@@ -170,7 +170,7 @@ modify_data() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexArrayData::
 INLINE void GeomVertexArrayData::
 set_data(CPTA_uchar array) {
 set_data(CPTA_uchar array) {
-  GeomVertexArrayDataPipelineWriter writer(this, Thread::get_current_pipeline_stage(), true);
+  GeomVertexArrayDataPipelineWriter writer(this, true, Thread::get_current_thread());
   writer.set_data(array);
   writer.set_data(array);
 }
 }
 
 
@@ -205,22 +205,22 @@ CData(const GeomVertexArrayData::CData &copy) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexArrayDataPipelineBase::
 INLINE GeomVertexArrayDataPipelineBase::
 GeomVertexArrayDataPipelineBase(GeomVertexArrayData *object, 
 GeomVertexArrayDataPipelineBase(GeomVertexArrayData *object, 
-                                int pipeline_stage,
+                                Thread *current_thread,
                                 GeomVertexArrayData::CData *cdata) :
                                 GeomVertexArrayData::CData *cdata) :
   _object(object),
   _object(object),
-  _pipeline_stage(pipeline_stage),
+  _current_thread(current_thread),
   _cdata(cdata)
   _cdata(cdata)
 {
 {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GeomVertexArrayDataPipelineBase::get_pipeline_stage
+//     Function: GeomVertexArrayDataPipelineBase::get_current_thread
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE int GeomVertexArrayDataPipelineBase::
-get_pipeline_stage() const {
-  return _pipeline_stage;
+INLINE Thread *GeomVertexArrayDataPipelineBase::
+get_current_thread() const {
+  return _current_thread;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -290,15 +290,17 @@ get_modified() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexArrayDataPipelineReader::
 INLINE GeomVertexArrayDataPipelineReader::
 GeomVertexArrayDataPipelineReader(const GeomVertexArrayData *object, 
 GeomVertexArrayDataPipelineReader(const GeomVertexArrayData *object, 
-                                  int pipeline_stage) :
+                                  Thread *current_thread) :
   GeomVertexArrayDataPipelineBase((GeomVertexArrayData *)object,
   GeomVertexArrayDataPipelineBase((GeomVertexArrayData *)object,
-                                  pipeline_stage,
-                                  (GeomVertexArrayData::CData *)object->_cycler.read_stage(pipeline_stage))
+                                  current_thread,
+                                  (GeomVertexArrayData::CData *)object->_cycler.read(current_thread))
 {
 {
+#ifdef _DEBUG
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   nassertv(_cdata->test_ref_count_nonzero());
   nassertv(_cdata->test_ref_count_nonzero());
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
+#endif // _DEBUG
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -330,13 +332,18 @@ operator = (const GeomVertexArrayDataPipelineReader &) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexArrayDataPipelineReader::
 INLINE GeomVertexArrayDataPipelineReader::
 ~GeomVertexArrayDataPipelineReader() {
 ~GeomVertexArrayDataPipelineReader() {
+#ifdef _DEBUG
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   nassertv(_cdata->test_ref_count_nonzero());
   nassertv(_cdata->test_ref_count_nonzero());
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
-  _object->_cycler.release_read_stage(_pipeline_stage, _cdata);
+#endif // _DEBUG
+  _object->_cycler.release_read(_cdata);
+
+#ifdef _DEBUG
   _object = NULL;
   _object = NULL;
   _cdata = NULL;
   _cdata = NULL;
+#endif  // _DEBUG
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -355,15 +362,17 @@ get_object() const {
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexArrayDataPipelineWriter::
 INLINE GeomVertexArrayDataPipelineWriter::
-GeomVertexArrayDataPipelineWriter(GeomVertexArrayData *object, 
-                                  int pipeline_stage, bool force_to_0) :
-  GeomVertexArrayDataPipelineBase(object, pipeline_stage,
-                                  object->_cycler.write_stage_upstream(pipeline_stage, force_to_0))
+GeomVertexArrayDataPipelineWriter(GeomVertexArrayData *object, bool force_to_0,
+                                  Thread *current_thread) :
+  GeomVertexArrayDataPipelineBase(object, current_thread,
+                                  object->_cycler.write_upstream(force_to_0, current_thread))
 {
 {
+#ifdef _DEBUG
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   nassertv(_cdata->test_ref_count_nonzero());
   nassertv(_cdata->test_ref_count_nonzero());
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
+#endif // _DEBUG
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -395,13 +404,18 @@ operator = (const GeomVertexArrayDataPipelineWriter &) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexArrayDataPipelineWriter::
 INLINE GeomVertexArrayDataPipelineWriter::
 ~GeomVertexArrayDataPipelineWriter() {
 ~GeomVertexArrayDataPipelineWriter() {
+#ifdef _DEBUG
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   nassertv(_cdata->test_ref_count_nonzero());
   nassertv(_cdata->test_ref_count_nonzero());
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
-  _object->_cycler.release_write_stage(_pipeline_stage, _cdata);
+#endif // _DEBUG
+  _object->_cycler.release_write(_cdata);
+
+#ifdef _DEBUG
   _object = NULL;
   _object = NULL;
   _cdata = NULL;
   _cdata = NULL;
+#endif  // _DEBUG
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 5 - 5
panda/src/gobj/geomVertexArrayData.h

@@ -190,11 +190,11 @@ private:
 class EXPCL_PANDA GeomVertexArrayDataPipelineBase : public GeomEnums {
 class EXPCL_PANDA GeomVertexArrayDataPipelineBase : public GeomEnums {
 protected:
 protected:
   INLINE GeomVertexArrayDataPipelineBase(GeomVertexArrayData *object, 
   INLINE GeomVertexArrayDataPipelineBase(GeomVertexArrayData *object, 
-                                         int pipeline_stage,
+                                         Thread *current_thread,
                                          GeomVertexArrayData::CData *cdata);
                                          GeomVertexArrayData::CData *cdata);
 
 
 public:
 public:
-  INLINE int get_pipeline_stage() const;
+  INLINE Thread *get_current_thread() const;
 
 
   INLINE const GeomVertexArrayFormat *get_array_format() const;
   INLINE const GeomVertexArrayFormat *get_array_format() const;
 
 
@@ -206,7 +206,7 @@ public:
 
 
 protected:
 protected:
   GeomVertexArrayData *_object;
   GeomVertexArrayData *_object;
-  int _pipeline_stage;
+  Thread *_current_thread;
   GeomVertexArrayData::CData *_cdata;
   GeomVertexArrayData::CData *_cdata;
 };
 };
 
 
@@ -217,7 +217,7 @@ protected:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GeomVertexArrayDataPipelineReader : public GeomVertexArrayDataPipelineBase {
 class EXPCL_PANDA GeomVertexArrayDataPipelineReader : public GeomVertexArrayDataPipelineBase {
 public:
 public:
-  INLINE GeomVertexArrayDataPipelineReader(const GeomVertexArrayData *object, int pipeline_stage);
+  INLINE GeomVertexArrayDataPipelineReader(const GeomVertexArrayData *object, Thread *current_thread);
 private:
 private:
   INLINE GeomVertexArrayDataPipelineReader(const GeomVertexArrayDataPipelineReader &copy);
   INLINE GeomVertexArrayDataPipelineReader(const GeomVertexArrayDataPipelineReader &copy);
   INLINE void operator = (const GeomVertexArrayDataPipelineReader &copy);
   INLINE void operator = (const GeomVertexArrayDataPipelineReader &copy);
@@ -236,7 +236,7 @@ public:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GeomVertexArrayDataPipelineWriter : public GeomVertexArrayDataPipelineBase {
 class EXPCL_PANDA GeomVertexArrayDataPipelineWriter : public GeomVertexArrayDataPipelineBase {
 public:
 public:
-  INLINE GeomVertexArrayDataPipelineWriter(GeomVertexArrayData *object, int pipeline_stage, bool force_to_0);
+  INLINE GeomVertexArrayDataPipelineWriter(GeomVertexArrayData *object, bool force_to_0, Thread *current_thread);
 private:
 private:
   INLINE GeomVertexArrayDataPipelineWriter(const GeomVertexArrayDataPipelineWriter &copy);
   INLINE GeomVertexArrayDataPipelineWriter(const GeomVertexArrayDataPipelineWriter &copy);
   INLINE void operator = (const GeomVertexArrayDataPipelineWriter &copy);
   INLINE void operator = (const GeomVertexArrayDataPipelineWriter &copy);

+ 33 - 21
panda/src/gobj/geomVertexData.I

@@ -83,7 +83,7 @@ has_column(const InternalName *name) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomVertexData::
 INLINE int GeomVertexData::
 get_num_rows() const {
 get_num_rows() const {
-  GeomVertexDataPipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomVertexDataPipelineReader reader(this, Thread::get_current_thread());
   reader.check_array_readers();
   reader.check_array_readers();
   return reader.get_num_rows();
   return reader.get_num_rows();
 }
 }
@@ -115,7 +115,7 @@ get_num_rows() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE bool GeomVertexData::
 INLINE bool GeomVertexData::
 set_num_rows(int n) {
 set_num_rows(int n) {
-  GeomVertexDataPipelineWriter writer(this, Thread::get_current_pipeline_stage(), true);
+  GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
   writer.check_array_writers();
   writer.check_array_writers();
   return writer.set_num_rows(n);
   return writer.set_num_rows(n);
 }
 }
@@ -163,7 +163,7 @@ get_array(int i) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexArrayData *GeomVertexData::
 INLINE GeomVertexArrayData *GeomVertexData::
 modify_array(int i) {
 modify_array(int i) {
-  GeomVertexDataPipelineWriter writer(this, Thread::get_current_pipeline_stage(), true);
+  GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
   return writer.modify_array(i);
   return writer.modify_array(i);
 }
 }
 
 
@@ -181,7 +181,7 @@ modify_array(int i) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void GeomVertexData::
 INLINE void GeomVertexData::
 set_array(int i, const GeomVertexArrayData *array) {
 set_array(int i, const GeomVertexArrayData *array) {
-  GeomVertexDataPipelineWriter writer(this, Thread::get_current_pipeline_stage(), true);
+  GeomVertexDataPipelineWriter writer(this, true, Thread::get_current_thread());
   writer.set_array(i, array);
   writer.set_array(i, array);
 }
 }
 
 
@@ -288,7 +288,7 @@ clear_slider_table() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE int GeomVertexData::
 INLINE int GeomVertexData::
 get_num_bytes() const {
 get_num_bytes() const {
-  GeomVertexDataPipelineReader reader(this, Thread::get_current_pipeline_stage());
+  GeomVertexDataPipelineReader reader(this, Thread::get_current_thread());
   return reader.get_num_bytes();
   return reader.get_num_bytes();
 }
 }
 
 
@@ -482,22 +482,22 @@ CData(const GeomVertexData::CData &copy) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexDataPipelineBase::
 INLINE GeomVertexDataPipelineBase::
 GeomVertexDataPipelineBase(GeomVertexData *object, 
 GeomVertexDataPipelineBase(GeomVertexData *object, 
-                             int pipeline_stage,
-                             GeomVertexData::CData *cdata) :
+                           Thread *current_thread,
+                           GeomVertexData::CData *cdata) :
   _object(object),
   _object(object),
-  _pipeline_stage(pipeline_stage),
+  _current_thread(current_thread),
   _cdata(cdata)
   _cdata(cdata)
 {
 {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GeomVertexDataPipelineBase::get_pipeline_stage
+//     Function: GeomVertexDataPipelineBase::get_current_thread
 //       Access: Public
 //       Access: Public
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE int GeomVertexDataPipelineBase::
-get_pipeline_stage() const {
-  return _pipeline_stage;
+INLINE Thread *GeomVertexDataPipelineBase::
+get_current_thread() const {
+  return _current_thread;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -598,9 +598,9 @@ get_modified() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexDataPipelineReader::
 INLINE GeomVertexDataPipelineReader::
 GeomVertexDataPipelineReader(const GeomVertexData *object, 
 GeomVertexDataPipelineReader(const GeomVertexData *object, 
-                             int pipeline_stage) :
-  GeomVertexDataPipelineBase((GeomVertexData *)object, pipeline_stage,
-                             (GeomVertexData::CData *)object->_cycler.read_stage(pipeline_stage)),
+                             Thread *current_thread) :
+  GeomVertexDataPipelineBase((GeomVertexData *)object, current_thread,
+                             (GeomVertexData::CData *)object->_cycler.read(current_thread)),
   _got_array_readers(false)
   _got_array_readers(false)
 {
 {
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
@@ -641,13 +641,18 @@ INLINE GeomVertexDataPipelineReader::
   if (_got_array_readers) {
   if (_got_array_readers) {
     delete_array_readers();
     delete_array_readers();
   }
   }
+#ifdef _DEBUG
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   nassertv(_cdata->test_ref_count_nonzero());
   nassertv(_cdata->test_ref_count_nonzero());
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
-  _object->_cycler.release_read_stage(_pipeline_stage, _cdata);
+#endif // _DEBUG
+  _object->_cycler.release_read(_cdata);
+
+#ifdef _DEBUG
   _object = NULL;
   _object = NULL;
   _cdata = NULL;
   _cdata = NULL;
+#endif  // _DEBUG
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -735,17 +740,19 @@ has_color() const {
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexDataPipelineWriter::
 INLINE GeomVertexDataPipelineWriter::
-GeomVertexDataPipelineWriter(GeomVertexData *object, 
-                             int pipeline_stage, bool force_to_0) :
-  GeomVertexDataPipelineBase(object, pipeline_stage,
-                             object->_cycler.write_stage_upstream(pipeline_stage, force_to_0)),
+GeomVertexDataPipelineWriter(GeomVertexData *object, bool force_to_0, 
+                             Thread *current_thread) :
+  GeomVertexDataPipelineBase(object, current_thread,
+                             object->_cycler.write_upstream(force_to_0, current_thread)),
   _force_to_0(force_to_0),
   _force_to_0(force_to_0),
   _got_array_writers(false)
   _got_array_writers(false)
 {
 {
+#ifdef _DEBUG
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   nassertv(_cdata->test_ref_count_nonzero());
   nassertv(_cdata->test_ref_count_nonzero());
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
+#endif // _DEBUG
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -780,13 +787,18 @@ INLINE GeomVertexDataPipelineWriter::
   if (_got_array_writers) {
   if (_got_array_writers) {
     delete_array_writers();
     delete_array_writers();
   }
   }
+#ifdef _DEBUG
   nassertv(_object->test_ref_count_nonzero());
   nassertv(_object->test_ref_count_nonzero());
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   nassertv(_cdata->test_ref_count_nonzero());
   nassertv(_cdata->test_ref_count_nonzero());
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING
-  _object->_cycler.release_write_stage(_pipeline_stage, _cdata);
+#endif // _DEBUG
+  _object->_cycler.release_write(_cdata);
+
+#ifdef _DEBUG
   _object = NULL;
   _object = NULL;
   _cdata = NULL;
   _cdata = NULL;
+#endif  // _DEBUG
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 5 - 5
panda/src/gobj/geomVertexData.cxx

@@ -1713,7 +1713,7 @@ make_array_readers() {
   _array_readers.reserve(_cdata->_arrays.size());
   _array_readers.reserve(_cdata->_arrays.size());
   GeomVertexData::Arrays::const_iterator ai;
   GeomVertexData::Arrays::const_iterator ai;
   for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
   for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
-    _array_readers.push_back(new GeomVertexArrayDataPipelineReader(*ai, _pipeline_stage));
+    _array_readers.push_back(new GeomVertexArrayDataPipelineReader(*ai, _current_thread));
   }
   }
 
 
   _got_array_readers = true;
   _got_array_readers = true;
@@ -1778,7 +1778,7 @@ set_num_rows(int n) {
       if (_cdata->_arrays[i]->get_ref_count() > 1) {
       if (_cdata->_arrays[i]->get_ref_count() > 1) {
         delete _array_writers[i];
         delete _array_writers[i];
         _cdata->_arrays[i] = new GeomVertexArrayData(*_cdata->_arrays[i]);
         _cdata->_arrays[i] = new GeomVertexArrayData(*_cdata->_arrays[i]);
-        _array_writers[i] = new GeomVertexArrayDataPipelineWriter(_cdata->_arrays[i], _pipeline_stage, _force_to_0);
+        _array_writers[i] = new GeomVertexArrayDataPipelineWriter(_cdata->_arrays[i], _force_to_0, _current_thread);
       }
       }
       if (_cdata->_arrays[i]->has_column(InternalName::get_color())) {
       if (_cdata->_arrays[i]->has_column(InternalName::get_color())) {
         color_array = i;
         color_array = i;
@@ -1856,7 +1856,7 @@ modify_array(int i) {
 
 
   if (_got_array_writers) {
   if (_got_array_writers) {
     delete _array_writers[i];
     delete _array_writers[i];
-    _array_writers[i] = new GeomVertexArrayDataPipelineWriter(_cdata->_arrays[i], _pipeline_stage, _force_to_0);
+    _array_writers[i] = new GeomVertexArrayDataPipelineWriter(_cdata->_arrays[i], _force_to_0, _current_thread);
   }
   }
 
 
   return _cdata->_arrays[i];
   return _cdata->_arrays[i];
@@ -1877,7 +1877,7 @@ set_array(int i, const GeomVertexArrayData *array) {
 
 
   if (_got_array_writers) {
   if (_got_array_writers) {
     delete _array_writers[i];
     delete _array_writers[i];
-    _array_writers[i] = new GeomVertexArrayDataPipelineWriter(_cdata->_arrays[i], _pipeline_stage, _force_to_0);
+    _array_writers[i] = new GeomVertexArrayDataPipelineWriter(_cdata->_arrays[i], _force_to_0, _current_thread);
   }
   }
 }
 }
 
 
@@ -1893,7 +1893,7 @@ make_array_writers() {
   _array_writers.reserve(_cdata->_arrays.size());
   _array_writers.reserve(_cdata->_arrays.size());
   GeomVertexData::Arrays::const_iterator ai;
   GeomVertexData::Arrays::const_iterator ai;
   for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
   for (ai = _cdata->_arrays.begin(); ai != _cdata->_arrays.end(); ++ai) {
-    _array_writers.push_back(new GeomVertexArrayDataPipelineWriter(*ai, _pipeline_stage, _force_to_0));
+    _array_writers.push_back(new GeomVertexArrayDataPipelineWriter(*ai, _force_to_0, _current_thread));
   }
   }
 
 
   _got_array_writers = true;
   _got_array_writers = true;

+ 6 - 6
panda/src/gobj/geomVertexData.h

@@ -307,11 +307,11 @@ private:
 class EXPCL_PANDA GeomVertexDataPipelineBase : public GeomEnums {
 class EXPCL_PANDA GeomVertexDataPipelineBase : public GeomEnums {
 protected:
 protected:
   INLINE GeomVertexDataPipelineBase(GeomVertexData *object, 
   INLINE GeomVertexDataPipelineBase(GeomVertexData *object, 
-                                    int pipeline_stage,
+                                    Thread *current_thread,
                                     GeomVertexData::CData *cdata);
                                     GeomVertexData::CData *cdata);
 
 
 public:
 public:
-  INLINE int get_pipeline_stage() const;
+  INLINE Thread *get_current_thread() const;
 
 
   INLINE const GeomVertexFormat *get_format() const;
   INLINE const GeomVertexFormat *get_format() const;
   INLINE bool has_column(const InternalName *name) const;
   INLINE bool has_column(const InternalName *name) const;
@@ -327,7 +327,7 @@ public:
 
 
 protected:
 protected:
   GeomVertexData *_object;
   GeomVertexData *_object;
-  int _pipeline_stage;
+  Thread *_current_thread;
   GeomVertexData::CData *_cdata;
   GeomVertexData::CData *_cdata;
 };
 };
 
 
@@ -338,7 +338,7 @@ protected:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GeomVertexDataPipelineReader : public GeomVertexDataPipelineBase {
 class EXPCL_PANDA GeomVertexDataPipelineReader : public GeomVertexDataPipelineBase {
 public:
 public:
-  INLINE GeomVertexDataPipelineReader(const GeomVertexData *object, int pipeline_stage);
+  INLINE GeomVertexDataPipelineReader(const GeomVertexData *object, Thread *current_thread);
 private:
 private:
   INLINE GeomVertexDataPipelineReader(const GeomVertexDataPipelineReader &copy);
   INLINE GeomVertexDataPipelineReader(const GeomVertexDataPipelineReader &copy);
   INLINE void operator = (const GeomVertexDataPipelineReader &copy);
   INLINE void operator = (const GeomVertexDataPipelineReader &copy);
@@ -390,8 +390,8 @@ private:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA GeomVertexDataPipelineWriter : public GeomVertexDataPipelineBase {
 class EXPCL_PANDA GeomVertexDataPipelineWriter : public GeomVertexDataPipelineBase {
 public:
 public:
-  INLINE GeomVertexDataPipelineWriter(GeomVertexData *object, int pipeline_stage,
-                                      bool force_to_0);
+  INLINE GeomVertexDataPipelineWriter(GeomVertexData *object, bool force_to_0,
+                                      Thread *current_thread);
 private:
 private:
   INLINE GeomVertexDataPipelineWriter(const GeomVertexDataPipelineWriter &copy);
   INLINE GeomVertexDataPipelineWriter(const GeomVertexDataPipelineWriter &copy);
   INLINE void operator = (const GeomVertexDataPipelineWriter &copy);
   INLINE void operator = (const GeomVertexDataPipelineWriter &copy);

+ 5 - 5
panda/src/gobj/geomVertexReader.I

@@ -42,7 +42,7 @@ GeomVertexReader() :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexData *vertex_data) :
 GeomVertexReader(const GeomVertexData *vertex_data) :
-  _data_reader(new GeomVertexDataPipelineReader(vertex_data, Thread::get_current_pipeline_stage())),
+  _data_reader(new GeomVertexDataPipelineReader(vertex_data, Thread::get_current_thread())),
   _array_reader(NULL),
   _array_reader(NULL),
   _owns_reader(true)
   _owns_reader(true)
 {
 {
@@ -58,7 +58,7 @@ GeomVertexReader(const GeomVertexData *vertex_data) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexReader::
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexData *vertex_data, const string &name) :
 GeomVertexReader(const GeomVertexData *vertex_data, const string &name) :
-  _data_reader(new GeomVertexDataPipelineReader(vertex_data, Thread::get_current_pipeline_stage())),
+  _data_reader(new GeomVertexDataPipelineReader(vertex_data, Thread::get_current_thread())),
   _array_reader(NULL),
   _array_reader(NULL),
   _owns_reader(true)
   _owns_reader(true)
 {
 {
@@ -76,7 +76,7 @@ GeomVertexReader(const GeomVertexData *vertex_data, const string &name) :
 INLINE GeomVertexReader::
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexData *vertex_data, 
 GeomVertexReader(const GeomVertexData *vertex_data, 
                  const InternalName *name) :
                  const InternalName *name) :
-  _data_reader(new GeomVertexDataPipelineReader(vertex_data, Thread::get_current_pipeline_stage())),
+  _data_reader(new GeomVertexDataPipelineReader(vertex_data, Thread::get_current_thread())),
   _array_reader(NULL),
   _array_reader(NULL),
   _owns_reader(true)
   _owns_reader(true)
 {
 {
@@ -93,7 +93,7 @@ GeomVertexReader(const GeomVertexData *vertex_data,
 INLINE GeomVertexReader::
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexArrayData *array_data) :
 GeomVertexReader(const GeomVertexArrayData *array_data) :
   _data_reader(NULL),
   _data_reader(NULL),
-  _array_reader(new GeomVertexArrayDataPipelineReader(array_data, Thread::get_current_pipeline_stage())),
+  _array_reader(new GeomVertexArrayDataPipelineReader(array_data, Thread::get_current_thread())),
   _owns_reader(true)
   _owns_reader(true)
 {
 {
   initialize();
   initialize();
@@ -108,7 +108,7 @@ GeomVertexReader(const GeomVertexArrayData *array_data) :
 INLINE GeomVertexReader::
 INLINE GeomVertexReader::
 GeomVertexReader(const GeomVertexArrayData *array_data, int column) :
 GeomVertexReader(const GeomVertexArrayData *array_data, int column) :
   _data_reader(NULL),
   _data_reader(NULL),
-  _array_reader(new GeomVertexArrayDataPipelineReader(array_data, Thread::get_current_pipeline_stage())),
+  _array_reader(new GeomVertexArrayDataPipelineReader(array_data, Thread::get_current_thread())),
   _owns_reader(true)
   _owns_reader(true)
 {
 {
   initialize();
   initialize();

+ 5 - 5
panda/src/gobj/geomVertexWriter.I

@@ -42,7 +42,7 @@ GeomVertexWriter() :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexData *vertex_data) :
 GeomVertexWriter(GeomVertexData *vertex_data) :
-  _data_writer(new GeomVertexDataPipelineWriter(vertex_data, Thread::get_current_pipeline_stage(), true)),
+  _data_writer(new GeomVertexDataPipelineWriter(vertex_data, true, Thread::get_current_thread())),
   _array_writer(NULL),
   _array_writer(NULL),
   _owns_writer(true)
   _owns_writer(true)
 {
 {
@@ -58,7 +58,7 @@ GeomVertexWriter(GeomVertexData *vertex_data) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexData *vertex_data, const string &name) :
 GeomVertexWriter(GeomVertexData *vertex_data, const string &name) :
-  _data_writer(new GeomVertexDataPipelineWriter(vertex_data, Thread::get_current_pipeline_stage(), true)),
+  _data_writer(new GeomVertexDataPipelineWriter(vertex_data, true, Thread::get_current_thread())),
   _array_writer(NULL),
   _array_writer(NULL),
   _owns_writer(true)
   _owns_writer(true)
 {
 {
@@ -75,7 +75,7 @@ GeomVertexWriter(GeomVertexData *vertex_data, const string &name) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE GeomVertexWriter::
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexData *vertex_data, const InternalName *name) :
 GeomVertexWriter(GeomVertexData *vertex_data, const InternalName *name) :
-  _data_writer(new GeomVertexDataPipelineWriter(vertex_data, Thread::get_current_pipeline_stage(), true)),
+  _data_writer(new GeomVertexDataPipelineWriter(vertex_data, true, Thread::get_current_thread())),
   _array_writer(NULL),
   _array_writer(NULL),
   _owns_writer(true)
   _owns_writer(true)
 {
 {
@@ -92,7 +92,7 @@ GeomVertexWriter(GeomVertexData *vertex_data, const InternalName *name) :
 INLINE GeomVertexWriter::
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexArrayData *array_data) :
 GeomVertexWriter(GeomVertexArrayData *array_data) :
   _data_writer(NULL),
   _data_writer(NULL),
-  _array_writer(new GeomVertexArrayDataPipelineWriter(array_data, Thread::get_current_pipeline_stage(), true)),
+  _array_writer(new GeomVertexArrayDataPipelineWriter(array_data, true, Thread::get_current_thread())),
   _owns_writer(true)
   _owns_writer(true)
 {
 {
   initialize();
   initialize();
@@ -107,7 +107,7 @@ GeomVertexWriter(GeomVertexArrayData *array_data) :
 INLINE GeomVertexWriter::
 INLINE GeomVertexWriter::
 GeomVertexWriter(GeomVertexArrayData *array_data, int column) :
 GeomVertexWriter(GeomVertexArrayData *array_data, int column) :
   _data_writer(NULL),
   _data_writer(NULL),
-  _array_writer(new GeomVertexArrayDataPipelineWriter(array_data, Thread::get_current_pipeline_stage(), true)),
+  _array_writer(new GeomVertexArrayDataPipelineWriter(array_data, true, Thread::get_current_thread())),
   _owns_writer(true)
   _owns_writer(true)
 {
 {
   initialize();
   initialize();

+ 33 - 5
panda/src/pipeline/cycleDataReader.I

@@ -27,10 +27,12 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataReader<CycleDataType>::
 INLINE CycleDataReader<CycleDataType>::
-CycleDataReader(const PipelineCycler<CycleDataType> &cycler) :
-  _cycler(&cycler)
+CycleDataReader(const PipelineCycler<CycleDataType> &cycler,
+                Thread *current_thread) :
+  _cycler(&cycler),
+  _current_thread(current_thread)
 {
 {
-  _pointer = _cycler->read();
+  _pointer = _cycler->read(_current_thread);
   nassertv(_pointer != (const CycleDataType *)NULL);
   nassertv(_pointer != (const CycleDataType *)NULL);
 }
 }
 
 
@@ -43,6 +45,7 @@ template<class CycleDataType>
 INLINE CycleDataReader<CycleDataType>::
 INLINE CycleDataReader<CycleDataType>::
 CycleDataReader(const CycleDataReader<CycleDataType> &copy) :
 CycleDataReader(const CycleDataReader<CycleDataType> &copy) :
   _cycler(copy._cycler),
   _cycler(copy._cycler),
+  _current_thread(copy._current_thread),
   _pointer(copy._pointer)
   _pointer(copy._pointer)
 {
 {
   nassertv(_pointer != (const CycleDataType *)NULL);
   nassertv(_pointer != (const CycleDataType *)NULL);
@@ -58,6 +61,7 @@ template<class CycleDataType>
 INLINE void CycleDataReader<CycleDataType>::
 INLINE void CycleDataReader<CycleDataType>::
 operator = (const CycleDataReader<CycleDataType> &copy) {
 operator = (const CycleDataReader<CycleDataType> &copy) {
   nassertv(_pointer == (CycleDataType *)NULL);
   nassertv(_pointer == (CycleDataType *)NULL);
+  nassertv(_current_thread == copy._current_thread);
 
 
   _cycler = copy._cycler;
   _cycler = copy._cycler;
   _pointer = copy._pointer;
   _pointer = copy._pointer;
@@ -124,6 +128,18 @@ take_pointer() {
   return pointer;
   return pointer;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CycleDataReader::get_current_thread (full)
+//       Access: Public
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+template<class CycleDataType>
+INLINE Thread *CycleDataReader<CycleDataType>::
+get_current_thread() const {
+  return _current_thread;
+}
+
 #else  // !DO_PIPELINING
 #else  // !DO_PIPELINING
 // This is the trivial, do-nothing implementation.
 // This is the trivial, do-nothing implementation.
 
 
@@ -134,8 +150,8 @@ take_pointer() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataReader<CycleDataType>::
 INLINE CycleDataReader<CycleDataType>::
-CycleDataReader(const PipelineCycler<CycleDataType> &cycler) {
-  _pointer = cycler.read();
+CycleDataReader(const PipelineCycler<CycleDataType> &cycler, Thread *) {
+  _pointer = cycler.cheat();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -211,4 +227,16 @@ take_pointer() {
   return _pointer;
   return _pointer;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CycleDataReader::get_current_thread (trivial)
+//       Access: Public
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+template<class CycleDataType>
+INLINE Thread *CycleDataReader<CycleDataType>::
+get_current_thread() const {
+  return Thread::get_current_thread();
+}
+
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING

+ 5 - 1
panda/src/pipeline/cycleDataReader.h

@@ -23,6 +23,7 @@
 
 
 #include "cycleData.h"
 #include "cycleData.h"
 #include "pipelineCycler.h"
 #include "pipelineCycler.h"
+#include "thread.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : CycleDataReader
 //       Class : CycleDataReader
@@ -39,7 +40,8 @@
 template<class CycleDataType>
 template<class CycleDataType>
 class CycleDataReader {
 class CycleDataReader {
 public:
 public:
-  INLINE CycleDataReader(const PipelineCycler<CycleDataType> &cycler);
+  INLINE CycleDataReader(const PipelineCycler<CycleDataType> &cycler,
+                         Thread *current_thread = Thread::get_current_thread());
   INLINE CycleDataReader(const CycleDataReader<CycleDataType> &copy);
   INLINE CycleDataReader(const CycleDataReader<CycleDataType> &copy);
   INLINE void operator = (const CycleDataReader<CycleDataType> &copy);
   INLINE void operator = (const CycleDataReader<CycleDataType> &copy);
 
 
@@ -49,11 +51,13 @@ public:
   INLINE operator const CycleDataType * () const;
   INLINE operator const CycleDataType * () const;
 
 
   INLINE const CycleDataType *take_pointer();
   INLINE const CycleDataType *take_pointer();
+  INLINE Thread *get_current_thread() const;
 
 
 private:
 private:
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   // This is the data stored for a real pipelining implementation.
   // This is the data stored for a real pipelining implementation.
   const PipelineCycler<CycleDataType> *_cycler;
   const PipelineCycler<CycleDataType> *_cycler;
+  Thread *_current_thread;
   const CycleDataType *_pointer;
   const CycleDataType *_pointer;
   CycleDataType *_write_pointer;
   CycleDataType *_write_pointer;
 #else  // !DO_PIPELINING
 #else  // !DO_PIPELINING

+ 32 - 4
panda/src/pipeline/cycleDataStageReader.I

@@ -29,11 +29,12 @@
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataStageReader<CycleDataType>::
 INLINE CycleDataStageReader<CycleDataType>::
 CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler,
 CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler,
-                     int stage) :
+                     int stage, Thread *current_thread) :
   _cycler(&cycler),
   _cycler(&cycler),
+  _current_thread(current_thread),
   _stage(stage)
   _stage(stage)
 {
 {
-  _pointer = _cycler->read_stage(_stage);
+  _pointer = _cycler->read_stage(_stage, _current_thread);
   nassertv(_pointer != (const CycleDataType *)NULL);
   nassertv(_pointer != (const CycleDataType *)NULL);
 }
 }
 
 
@@ -46,6 +47,7 @@ template<class CycleDataType>
 INLINE CycleDataStageReader<CycleDataType>::
 INLINE CycleDataStageReader<CycleDataType>::
 CycleDataStageReader(const CycleDataStageReader<CycleDataType> &copy) :
 CycleDataStageReader(const CycleDataStageReader<CycleDataType> &copy) :
   _cycler(copy._cycler),
   _cycler(copy._cycler),
+  _current_thread(copy._current_thread),
   _pointer(copy._pointer),
   _pointer(copy._pointer),
   _stage(copy._stage)
   _stage(copy._stage)
 {
 {
@@ -62,6 +64,7 @@ template<class CycleDataType>
 INLINE void CycleDataStageReader<CycleDataType>::
 INLINE void CycleDataStageReader<CycleDataType>::
 operator = (const CycleDataStageReader<CycleDataType> &copy) {
 operator = (const CycleDataStageReader<CycleDataType> &copy) {
   nassertv(_pointer == (CycleDataType *)NULL);
   nassertv(_pointer == (CycleDataType *)NULL);
+  nassertv(_current_thread == copy._current_thread);
 
 
   _cycler = copy._cycler;
   _cycler = copy._cycler;
   _pointer = copy._pointer;
   _pointer = copy._pointer;
@@ -129,6 +132,18 @@ take_pointer() {
   return pointer;
   return pointer;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CycleDataStageReader::get_current_thread (full)
+//       Access: Public
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+template<class CycleDataType>
+INLINE Thread *CycleDataStageReader<CycleDataType>::
+get_current_thread() const {
+  return _current_thread;
+}
+
 #else  // !DO_PIPELINING
 #else  // !DO_PIPELINING
 // This is the trivial, do-nothing implementation.
 // This is the trivial, do-nothing implementation.
 
 
@@ -139,8 +154,9 @@ take_pointer() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataStageReader<CycleDataType>::
 INLINE CycleDataStageReader<CycleDataType>::
-CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler, int) {
-  _pointer = cycler.read();
+CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler, int,
+                     Thread *) {
+  _pointer = cycler.cheat();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -216,4 +232,16 @@ take_pointer() {
   return _pointer;
   return _pointer;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CycleDataStageReader::get_current_thread (trivial)
+//       Access: Public
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+template<class CycleDataType>
+INLINE Thread *CycleDataStageReader<CycleDataType>::
+get_current_thread() const {
+  return Thread::get_current_thread();
+}
+
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING

+ 4 - 1
panda/src/pipeline/cycleDataStageReader.h

@@ -33,7 +33,8 @@
 template<class CycleDataType>
 template<class CycleDataType>
 class CycleDataStageReader {
 class CycleDataStageReader {
 public:
 public:
-  INLINE CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler, int stage);
+  INLINE CycleDataStageReader(const PipelineCycler<CycleDataType> &cycler, 
+                              int stage, Thread *current_thread = Thread::get_current_thread());
   INLINE CycleDataStageReader(const CycleDataStageReader<CycleDataType> &copy);
   INLINE CycleDataStageReader(const CycleDataStageReader<CycleDataType> &copy);
   INLINE void operator = (const CycleDataStageReader<CycleDataType> &copy);
   INLINE void operator = (const CycleDataStageReader<CycleDataType> &copy);
 
 
@@ -43,11 +44,13 @@ public:
   INLINE operator const CycleDataType * () const;
   INLINE operator const CycleDataType * () const;
 
 
   INLINE const CycleDataType *take_pointer();
   INLINE const CycleDataType *take_pointer();
+  INLINE Thread *get_current_thread() const;
 
 
 private:
 private:
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   // This is the data stored for a real pipelining implementation.
   // This is the data stored for a real pipelining implementation.
   const PipelineCycler<CycleDataType> *_cycler;
   const PipelineCycler<CycleDataType> *_cycler;
+  Thread *_current_thread;
   const CycleDataType *_pointer;
   const CycleDataType *_pointer;
   int _stage;
   int _stage;
 #else  // !DO_PIPELINING
 #else  // !DO_PIPELINING

+ 42 - 10
panda/src/pipeline/cycleDataStageWriter.I

@@ -27,11 +27,13 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataStageWriter<CycleDataType>::
 INLINE CycleDataStageWriter<CycleDataType>::
-CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage) :
+CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
+                     Thread *current_thread) :
   _cycler(&cycler),
   _cycler(&cycler),
+  _current_thread(current_thread),
   _stage(stage)
   _stage(stage)
 {
 {
-  _pointer = _cycler->write_stage(_stage);
+  _pointer = _cycler->write_stage(_stage, _current_thread);
   nassertv(_pointer != (CycleDataType *)NULL);
   nassertv(_pointer != (CycleDataType *)NULL);
 }
 }
 
 
@@ -43,11 +45,12 @@ CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage) :
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataStageWriter<CycleDataType>::
 INLINE CycleDataStageWriter<CycleDataType>::
 CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
 CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
-                     bool force_to_0) :
+                     bool force_to_0, Thread *current_thread) :
   _cycler(&cycler),
   _cycler(&cycler),
+  _current_thread(current_thread),
   _stage(stage)
   _stage(stage)
 {
 {
-  _pointer = _cycler->write_stage_upstream(_stage, force_to_0);
+  _pointer = _cycler->write_stage_upstream(_stage, force_to_0, _current_thread);
   nassertv(_pointer != (CycleDataType *)NULL);
   nassertv(_pointer != (CycleDataType *)NULL);
 }
 }
 
 
@@ -60,6 +63,7 @@ template<class CycleDataType>
 INLINE CycleDataStageWriter<CycleDataType>::
 INLINE CycleDataStageWriter<CycleDataType>::
 CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> &copy) :
 CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> &copy) :
   _cycler(copy._cycler),
   _cycler(copy._cycler),
+  _current_thread(copy._current_thread),
   _pointer(copy._pointer),
   _pointer(copy._pointer),
   _stage(copy._stage)
   _stage(copy._stage)
 {
 {
@@ -76,6 +80,7 @@ template<class CycleDataType>
 INLINE void CycleDataStageWriter<CycleDataType>::
 INLINE void CycleDataStageWriter<CycleDataType>::
 operator = (const CycleDataStageWriter<CycleDataType> &copy) {
 operator = (const CycleDataStageWriter<CycleDataType> &copy) {
   nassertv(_pointer == (CycleDataType *)NULL);
   nassertv(_pointer == (CycleDataType *)NULL);
+  nassertv(_current_thread == copy._current_thread);
 
 
   _cycler = copy._cycler;
   _cycler = copy._cycler;
   _pointer = copy._pointer;
   _pointer = copy._pointer;
@@ -97,9 +102,11 @@ INLINE CycleDataStageWriter<CycleDataType>::
 CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
 CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
                      CycleDataStageReader<CycleDataType> &take_from) :
                      CycleDataStageReader<CycleDataType> &take_from) :
   _cycler(&cycler),
   _cycler(&cycler),
+  _current_thread(take_from.get_current_thread()),
   _stage(stage)
   _stage(stage)
 {
 {
-  _pointer = _cycler->elevate_read_stage(_stage, take_from.take_pointer());
+  _pointer = _cycler->elevate_read_stage(_stage, take_from.take_pointer(),
+                                         _current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -115,10 +122,11 @@ CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
                      CycleDataStageReader<CycleDataType> &take_from,
                      CycleDataStageReader<CycleDataType> &take_from,
                      bool force_to_0) :
                      bool force_to_0) :
   _cycler(&cycler),
   _cycler(&cycler),
+  _current_thread(take_from.get_current_thread()),
   _stage(stage)
   _stage(stage)
 {
 {
   _pointer = _cycler->elevate_read_stage_upstream(_stage, take_from.take_pointer(),
   _pointer = _cycler->elevate_read_stage_upstream(_stage, take_from.take_pointer(),
-                                                  force_to_0);
+                                                  force_to_0, _current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -173,6 +181,18 @@ operator CycleDataType * () {
   return _pointer;
   return _pointer;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CycleDataStageWriter::get_current_thread (full)
+//       Access: Public
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+template<class CycleDataType>
+INLINE Thread *CycleDataStageWriter<CycleDataType>::
+get_current_thread() const {
+  return _current_thread;
+}
+
 #else  // !DO_PIPELINING
 #else  // !DO_PIPELINING
 // This is the trivial, do-nothing implementation.
 // This is the trivial, do-nothing implementation.
 
 
@@ -183,8 +203,8 @@ operator CycleDataType * () {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataStageWriter<CycleDataType>::
 INLINE CycleDataStageWriter<CycleDataType>::
-CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int) {
-  _pointer = cycler.write();
+CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int, Thread *) {
+  _pointer = cycler.cheat();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -194,8 +214,8 @@ CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataStageWriter<CycleDataType>::
 INLINE CycleDataStageWriter<CycleDataType>::
-CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int, bool) {
-  _pointer = cycler.write();
+CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int, bool, Thread *) {
+  _pointer = cycler.cheat();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -298,4 +318,16 @@ operator CycleDataType * () {
   return _pointer;
   return _pointer;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CycleDataStageWriter::get_current_thread (trivial)
+//       Access: Public
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+template<class CycleDataType>
+INLINE Thread *CycleDataStageWriter<CycleDataType>::
+get_current_thread() const {
+  return Thread::get_current_thread();
+}
+
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING

+ 7 - 2
panda/src/pipeline/cycleDataStageWriter.h

@@ -37,9 +37,11 @@
 template<class CycleDataType>
 template<class CycleDataType>
 class CycleDataStageWriter {
 class CycleDataStageWriter {
 public:
 public:
-  INLINE CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage);
   INLINE CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
   INLINE CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
-                              bool force_to_0);
+                              Thread *current_thread = Thread::get_current_thread());
+  INLINE CycleDataStageWriter(PipelineCycler<CycleDataType> &cycler, int stage,
+                              bool force_to_0, Thread *current_thread = Thread::get_current_thread());
+
   INLINE CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> &copy);
   INLINE CycleDataStageWriter(const CycleDataStageWriter<CycleDataType> &copy);
   INLINE void operator = (const CycleDataStageWriter<CycleDataType> &copy);
   INLINE void operator = (const CycleDataStageWriter<CycleDataType> &copy);
 
 
@@ -56,10 +58,13 @@ public:
 
 
   INLINE operator CycleDataType * ();
   INLINE operator CycleDataType * ();
 
 
+  INLINE Thread *get_current_thread() const;
+
 private:
 private:
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   // This is the data stored for a real pipelining implementation.
   // This is the data stored for a real pipelining implementation.
   PipelineCycler<CycleDataType> *_cycler;
   PipelineCycler<CycleDataType> *_cycler;
+  Thread *_current_thread;
   CycleDataType *_pointer;
   CycleDataType *_pointer;
   int _stage;
   int _stage;
 #else  // !DO_PIPELINING
 #else  // !DO_PIPELINING

+ 48 - 22
panda/src/pipeline/cycleDataWriter.I

@@ -27,10 +27,11 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataWriter<CycleDataType>::
 INLINE CycleDataWriter<CycleDataType>::
-CycleDataWriter(PipelineCycler<CycleDataType> &cycler) :
-  _cycler(&cycler)
+CycleDataWriter(PipelineCycler<CycleDataType> &cycler, Thread *current_thread) :
+  _cycler(&cycler),
+  _current_thread(current_thread)
 {
 {
-  _pointer = _cycler->write();
+  _pointer = _cycler->write(_current_thread);
   nassertv(_pointer != (CycleDataType *)NULL);
   nassertv(_pointer != (CycleDataType *)NULL);
 }
 }
 
 
@@ -47,10 +48,12 @@ CycleDataWriter(PipelineCycler<CycleDataType> &cycler) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataWriter<CycleDataType>::
 INLINE CycleDataWriter<CycleDataType>::
-CycleDataWriter(PipelineCycler<CycleDataType> &cycler, bool force_to_0) :
-  _cycler(&cycler)
+CycleDataWriter(PipelineCycler<CycleDataType> &cycler, bool force_to_0,
+                Thread *current_thread) :
+  _cycler(&cycler),
+  _current_thread(current_thread)
 {
 {
-  _pointer = _cycler->write_upstream(force_to_0);
+  _pointer = _cycler->write_upstream(force_to_0, _current_thread);
   nassertv(_pointer != (CycleDataType *)NULL);
   nassertv(_pointer != (CycleDataType *)NULL);
 }
 }
 
 
@@ -63,6 +66,7 @@ template<class CycleDataType>
 INLINE CycleDataWriter<CycleDataType>::
 INLINE CycleDataWriter<CycleDataType>::
 CycleDataWriter(const CycleDataWriter<CycleDataType> &copy) :
 CycleDataWriter(const CycleDataWriter<CycleDataType> &copy) :
   _cycler(copy._cycler),
   _cycler(copy._cycler),
+  _current_thread(copy._current_thread),
   _pointer(copy._pointer)
   _pointer(copy._pointer)
 {
 {
   nassertv(_pointer != (CycleDataType *)NULL);
   nassertv(_pointer != (CycleDataType *)NULL);
@@ -78,6 +82,7 @@ template<class CycleDataType>
 INLINE void CycleDataWriter<CycleDataType>::
 INLINE void CycleDataWriter<CycleDataType>::
 operator = (const CycleDataWriter<CycleDataType> &copy) {
 operator = (const CycleDataWriter<CycleDataType> &copy) {
   nassertv(_pointer == (CycleDataType *)NULL);
   nassertv(_pointer == (CycleDataType *)NULL);
+  nassertv(_current_thread == copy._current_thread);
 
 
   _cycler = copy._cycler;
   _cycler = copy._cycler;
   _pointer = copy._pointer;
   _pointer = copy._pointer;
@@ -97,9 +102,10 @@ template<class CycleDataType>
 INLINE CycleDataWriter<CycleDataType>::
 INLINE CycleDataWriter<CycleDataType>::
 CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
 CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
                 CycleDataReader<CycleDataType> &take_from) :
                 CycleDataReader<CycleDataType> &take_from) :
-  _cycler(&cycler)
+  _cycler(&cycler),
+  _current_thread(take_from.get_current_thread())
 {
 {
-  _pointer = _cycler->elevate_read(take_from.take_pointer());
+  _pointer = _cycler->elevate_read(take_from.take_pointer(), _current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -116,9 +122,11 @@ INLINE CycleDataWriter<CycleDataType>::
 CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
 CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
                 CycleDataReader<CycleDataType> &take_from,
                 CycleDataReader<CycleDataType> &take_from,
 		bool force_to_0) :
 		bool force_to_0) :
-  _cycler(&cycler)
+  _cycler(&cycler),
+  _current_thread(take_from.get_current_thread())
 {
 {
-  _pointer = _cycler->elevate_read_upstream(take_from.take_pointer(), force_to_0);
+  _pointer = _cycler->elevate_read_upstream(take_from.take_pointer(), 
+                                            force_to_0, _current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -173,6 +181,18 @@ operator CycleDataType * () {
   return _pointer;
   return _pointer;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CycleDataWriter::get_current_thread (full)
+//       Access: Public
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+template<class CycleDataType>
+INLINE Thread *CycleDataWriter<CycleDataType>::
+get_current_thread() const {
+  return _current_thread;
+}
+
 #else  // !DO_PIPELINING
 #else  // !DO_PIPELINING
 // This is the trivial, do-nothing implementation.
 // This is the trivial, do-nothing implementation.
 
 
@@ -183,25 +203,19 @@ operator CycleDataType * () {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataWriter<CycleDataType>::
 INLINE CycleDataWriter<CycleDataType>::
-CycleDataWriter(PipelineCycler<CycleDataType> &cycler) {
-  _pointer = cycler.write();
+CycleDataWriter(PipelineCycler<CycleDataType> &cycler, Thread *) {
+  _pointer = cycler.cheat();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: CycleDataWriter::Constructor (full)
+//     Function: CycleDataWriter::Constructor (trivial)
 //       Access: Public
 //       Access: Public
-//  Description: This two-parameter constructor, with a bool parameter
-//               for the second parameter, automatically propagates
-//               the CycleData pointer upstream from the current
-//               stage, either stopping at the first pointer
-//               encountered that's different, going or all the way to
-//               stage 0, according to force_to_0.  See
-//               PipelineCycler::write_upstream().
+//  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataWriter<CycleDataType>::
 INLINE CycleDataWriter<CycleDataType>::
-CycleDataWriter(PipelineCycler<CycleDataType> &cycler, bool) {
-  _pointer = cycler.write();
+CycleDataWriter(PipelineCycler<CycleDataType> &cycler, bool, Thread *) {
+  _pointer = cycler.cheat();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -306,4 +320,16 @@ operator CycleDataType * () {
   return _pointer;
   return _pointer;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CycleDataWriter::get_current_thread (trivial)
+//       Access: Public
+//  Description: Returns the Thread pointer of the currently-executing
+//               thread, as passed to the constructor of this object.
+////////////////////////////////////////////////////////////////////
+template<class CycleDataType>
+INLINE Thread *CycleDataWriter<CycleDataType>::
+get_current_thread() const {
+  return Thread::get_current_thread();
+}
+
 #endif  // DO_PIPELINING
 #endif  // DO_PIPELINING

+ 8 - 2
panda/src/pipeline/cycleDataWriter.h

@@ -24,6 +24,7 @@
 #include "cycleData.h"
 #include "cycleData.h"
 #include "pipelineCycler.h"
 #include "pipelineCycler.h"
 #include "cycleDataReader.h"
 #include "cycleDataReader.h"
+#include "thread.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : CycleDataWriter
 //       Class : CycleDataWriter
@@ -40,8 +41,10 @@
 template<class CycleDataType>
 template<class CycleDataType>
 class CycleDataWriter {
 class CycleDataWriter {
 public:
 public:
-  INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler);
-  INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler, bool force_to_0);
+  INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler,
+                         Thread *current_thread = Thread::get_current_thread());
+  INLINE CycleDataWriter(PipelineCycler<CycleDataType> &cycler, bool force_to_0,
+                         Thread *current_thread = Thread::get_current_thread());
   INLINE CycleDataWriter(const CycleDataWriter<CycleDataType> &copy);
   INLINE CycleDataWriter(const CycleDataWriter<CycleDataType> &copy);
   INLINE void operator = (const CycleDataWriter<CycleDataType> &copy);
   INLINE void operator = (const CycleDataWriter<CycleDataType> &copy);
 
 
@@ -55,10 +58,13 @@ public:
 
 
   INLINE operator CycleDataType * ();
   INLINE operator CycleDataType * ();
 
 
+  INLINE Thread *get_current_thread() const;
+
 private:
 private:
 #ifdef DO_PIPELINING
 #ifdef DO_PIPELINING
   // This is the data stored for a real pipelining implementation.
   // This is the data stored for a real pipelining implementation.
   PipelineCycler<CycleDataType> *_cycler;
   PipelineCycler<CycleDataType> *_cycler;
+  Thread *_current_thread;
   CycleDataType *_pointer;
   CycleDataType *_pointer;
 #else  // !DO_PIPELINING
 #else  // !DO_PIPELINING
   // This is all we need for the trivial, do-nothing implementation.
   // This is all we need for the trivial, do-nothing implementation.

+ 45 - 0
panda/src/pipeline/mutexDebug.I

@@ -60,6 +60,51 @@ lock() const {
   _global_mutex.release();
   _global_mutex.release();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: MutexDebug::lock
+//       Access: Public
+//  Description: This variant on lock() accepts the current thread as
+//               a parameter, if it is already known, as an
+//               optimization.
+////////////////////////////////////////////////////////////////////
+INLINE void MutexDebug::
+lock(Thread *current_thread) const {
+  TAU_PROFILE("void MutexDebug::lock(Thread *)", " ", TAU_USER);
+  nassertv(current_thread == Thread::get_current_thread());
+  // You may only pass a Thread parameter to a ReMutex--that is, to a
+  // mutex whose _allow_recursion flag is true.
+  nassertv(_allow_recursion);
+  lock();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: MutexDebug::elevate_lock
+//       Access: Public
+//  Description: This method increments the lock count, assuming the
+//               calling thread already holds the lock.  After this
+//               call, release() will need to be called one additional
+//               time to release the lock.
+//
+//               This method really performs the same function as
+//               lock(), but it offers a potential (slight)
+//               performance benefit when the calling thread knows
+//               that it already holds the lock.  It is an error to
+//               call this when the calling thread does not hold the
+//               lock.
+////////////////////////////////////////////////////////////////////
+INLINE void MutexDebug::
+elevate_lock() const {
+  TAU_PROFILE("void MutexDebug::elevate_lock()", " ", TAU_USER);
+  // You may only pass call elevate_lock() on a ReMutex--that is, to a
+  // mutex whose _allow_recursion flag is true.
+  nassertv(_allow_recursion);
+
+  // Also, it's an error to call this if the lock is not already held.
+  nassertv(debug_is_locked());
+
+  lock();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: MutexDebug::release
 //     Function: MutexDebug::release
 //       Access: Public
 //       Access: Public

+ 2 - 0
panda/src/pipeline/mutexDebug.h

@@ -43,6 +43,8 @@ private:
 
 
 public:
 public:
   INLINE void lock() const;
   INLINE void lock() const;
+  INLINE void lock(Thread *current_thread) const;
+  INLINE void elevate_lock() const;
   INLINE void release() const;
   INLINE void release() const;
   INLINE bool debug_is_locked() const;
   INLINE bool debug_is_locked() const;
 
 

+ 58 - 54
panda/src/pipeline/pipelineCycler.I

@@ -63,30 +63,30 @@ operator = (const PipelineCycler<CycleDataType> &copy) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE const CycleDataType *PipelineCycler<CycleDataType>::
 INLINE const CycleDataType *PipelineCycler<CycleDataType>::
-read() const {
-  return (const CycleDataType *)PipelineCyclerBase::read();
+read(Thread *current_thread) const {
+  return (const CycleDataType *)PipelineCyclerBase::read(current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::read (dummy or true)
+//     Function: PipelineCycler::write (dummy or true)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::read_stage().
+//  Description: See PipelineCyclerBase::write().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
-INLINE const CycleDataType *PipelineCycler<CycleDataType>::
-read_stage(int n) const {
-  return (const CycleDataType *)PipelineCyclerBase::read_stage(n);
+INLINE CycleDataType *PipelineCycler<CycleDataType>::
+write(Thread *current_thread) {
+  return (CycleDataType *)PipelineCyclerBase::write(current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::write (dummy or true)
+//     Function: PipelineCycler::write_upstream (dummy or true)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::write().
+//  Description: See PipelineCyclerBase::write_upstream().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-write() {
-  return (CycleDataType *)PipelineCyclerBase::write();
+write_upstream(bool force_to_0, Thread *current_thread) {
+  return (CycleDataType *)PipelineCyclerBase::write_upstream(force_to_0, current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -96,8 +96,8 @@ write() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-elevate_read(const CycleDataType *pointer) {
-  return (CycleDataType *)PipelineCyclerBase::elevate_read(pointer);
+elevate_read(const CycleDataType *pointer, Thread *current_thread) {
+  return (CycleDataType *)PipelineCyclerBase::elevate_read(pointer, current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -107,41 +107,44 @@ elevate_read(const CycleDataType *pointer) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-elevate_read_upstream(const CycleDataType *pointer, bool force_to_0) {
-  return (CycleDataType *)PipelineCyclerBase::elevate_read_upstream(pointer, force_to_0);
+elevate_read_upstream(const CycleDataType *pointer, bool force_to_0,
+                      Thread *current_thread) {
+  return (CycleDataType *)PipelineCyclerBase::elevate_read_upstream(pointer, force_to_0, current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::elevate_read_stage (dummy or true)
+//     Function: PipelineCycler::read (dummy or true)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::elevate_read_stage().
+//  Description: See PipelineCyclerBase::read_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
-INLINE CycleDataType *PipelineCycler<CycleDataType>::
-elevate_read_stage(int n, const CycleDataType *pointer) {
-  return (CycleDataType *)PipelineCyclerBase::elevate_read_stage(n, pointer);
+INLINE const CycleDataType *PipelineCycler<CycleDataType>::
+read_stage(int pipeline_stage, Thread *current_thread) const {
+  return (const CycleDataType *)PipelineCyclerBase::read_stage(pipeline_stage, current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::elevate_read_stage_upstream (dummy or true)
+//     Function: PipelineCycler::elevate_read_stage (dummy or true)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::elevate_read_stage_upstream().
+//  Description: See PipelineCyclerBase::elevate_read_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-elevate_read_stage_upstream(int n, const CycleDataType *pointer, bool force_to_0) {
-  return (CycleDataType *)PipelineCyclerBase::elevate_read_stage_upstream(n, pointer, force_to_0);
+elevate_read_stage(int pipeline_stage, const CycleDataType *pointer, 
+                   Thread *current_thread) {
+  return (CycleDataType *)PipelineCyclerBase::elevate_read_stage(pipeline_stage, pointer, current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::write_upstream (dummy or true)
+//     Function: PipelineCycler::elevate_read_stage_upstream (dummy or true)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::write_upstream().
+//  Description: See PipelineCyclerBase::elevate_read_stage_upstream().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-write_upstream(bool force_to_0) {
-  return (CycleDataType *)PipelineCyclerBase::write_upstream(force_to_0);
+elevate_read_stage_upstream(int pipeline_stage, const CycleDataType *pointer, 
+                            bool force_to_0, Thread *current_thread) {
+  return (CycleDataType *)PipelineCyclerBase::elevate_read_stage_upstream(pipeline_stage, pointer, force_to_0, current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -151,8 +154,8 @@ write_upstream(bool force_to_0) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-write_stage(int n) {
-  return (CycleDataType *)PipelineCyclerBase::write_stage(n);
+write_stage(int pipeline_stage, Thread *current_thread) {
+  return (CycleDataType *)PipelineCyclerBase::write_stage(pipeline_stage, current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -162,8 +165,9 @@ write_stage(int n) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-write_stage_upstream(int pipeline_stage, bool force_to_0) {
-  return (CycleDataType *)PipelineCyclerBase::write_stage_upstream(pipeline_stage, force_to_0);
+write_stage_upstream(int pipeline_stage, bool force_to_0, 
+                     Thread *current_thread) {
+  return (CycleDataType *)PipelineCyclerBase::write_stage_upstream(pipeline_stage, force_to_0, current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -230,29 +234,29 @@ operator = (const PipelineCycler<CycleDataType> &copy) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE const CycleDataType *PipelineCycler<CycleDataType>::
 INLINE const CycleDataType *PipelineCycler<CycleDataType>::
-read() const {
+read(Thread *) const {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::read_stage (trivial)
+//     Function: PipelineCycler::write (trivial)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::read_stage().
+//  Description: See PipelineCyclerBase::write().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
-INLINE const CycleDataType *PipelineCycler<CycleDataType>::
-read_stage(int) const {
+INLINE CycleDataType *PipelineCycler<CycleDataType>::
+write(Thread *) {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::write (trivial)
+//     Function: PipelineCycler::write_upstream (trivial)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::write().
+//  Description: See PipelineCyclerBase::write_upstream().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-write() {
+write_upstream(bool, Thread *) {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 
@@ -263,7 +267,7 @@ write() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-elevate_read(const CycleDataType *) {
+elevate_read(const CycleDataType *, Thread *) {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 
@@ -274,40 +278,40 @@ elevate_read(const CycleDataType *) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-elevate_read_upstream(const CycleDataType *, bool) {
+elevate_read_upstream(const CycleDataType *, bool, Thread *) {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::elevate_read_stage (trivial)
+//     Function: PipelineCycler::read_stage (trivial)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::elevate_read_stage().
+//  Description: See PipelineCyclerBase::read_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
-INLINE CycleDataType *PipelineCycler<CycleDataType>::
-elevate_read_stage(int, const CycleDataType *) {
+INLINE const CycleDataType *PipelineCycler<CycleDataType>::
+read_stage(int, Thread *) const {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::elevate_read_stage_upstream (trivial)
+//     Function: PipelineCycler::elevate_read_stage (trivial)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::elevate_read_stage_upstream().
+//  Description: See PipelineCyclerBase::elevate_read_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-elevate_read_stage_upstream(int, const CycleDataType *, bool) {
+elevate_read_stage(int, const CycleDataType *, Thread *) {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: PipelineCycler::write_upstream (trivial)
+//     Function: PipelineCycler::elevate_read_stage_upstream (trivial)
 //       Access: Public
 //       Access: Public
-//  Description: See PipelineCyclerBase::write_upstream().
+//  Description: See PipelineCyclerBase::elevate_read_stage_upstream().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-write_upstream(bool) {
+elevate_read_stage_upstream(int, const CycleDataType *, bool, Thread *) {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 
@@ -318,7 +322,7 @@ write_upstream(bool) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-write_stage(int) {
+write_stage(int, Thread *) {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 
@@ -329,7 +333,7 @@ write_stage(int) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 template<class CycleDataType>
 template<class CycleDataType>
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
 INLINE CycleDataType *PipelineCycler<CycleDataType>::
-write_stage_upstream(int, bool) {
+write_stage_upstream(int, bool, Thread *) {
   return &_typed_data;
   return &_typed_data;
 }
 }
 
 

+ 12 - 11
panda/src/pipeline/pipelineCycler.h

@@ -22,7 +22,7 @@
 #include "pandabase.h"
 #include "pandabase.h"
 #include "pipelineCyclerBase.h"
 #include "pipelineCyclerBase.h"
 #include "cyclerHolder.h"
 #include "cyclerHolder.h"
-#include "thread.h"     // for convenience of code that uses PipelineReader classes
+#include "thread.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : PipelineCycler
 //       Class : PipelineCycler
@@ -63,16 +63,17 @@ public:
   INLINE PipelineCycler(const PipelineCycler<CycleDataType> &copy);
   INLINE PipelineCycler(const PipelineCycler<CycleDataType> &copy);
   INLINE void operator = (const PipelineCycler<CycleDataType> &copy);
   INLINE void operator = (const PipelineCycler<CycleDataType> &copy);
 
 
-  INLINE const CycleDataType *read() const;
-  INLINE const CycleDataType *read_stage(int n) const;
-  INLINE CycleDataType *write();
-  INLINE CycleDataType *elevate_read(const CycleDataType *pointer);
-  INLINE CycleDataType *elevate_read_upstream(const CycleDataType *pointer, bool force_to_0);
-  INLINE CycleDataType *elevate_read_stage(int n, const CycleDataType *pointer);
-  INLINE CycleDataType *elevate_read_stage_upstream(int n, const CycleDataType *pointer, bool force_to_0);
-  INLINE CycleDataType *write_upstream(bool force_to_0);
-  INLINE CycleDataType *write_stage_upstream(int pipeline_stage, bool force_to_0);
-  INLINE CycleDataType *write_stage(int n);
+  INLINE const CycleDataType *read(Thread *current_thread) const;
+  INLINE CycleDataType *write(Thread *current_thread);
+  INLINE CycleDataType *write_upstream(bool force_to_0, Thread *current_thread);
+  INLINE CycleDataType *elevate_read(const CycleDataType *pointer, Thread *current_thread);
+  INLINE CycleDataType *elevate_read_upstream(const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
+
+  INLINE const CycleDataType *read_stage(int pipeline_stage, Thread *current_thread) const;
+  INLINE CycleDataType *elevate_read_stage(int pipeline_stage, const CycleDataType *pointer, Thread *current_thread);
+  INLINE CycleDataType *elevate_read_stage_upstream(int pipeline_stage, const CycleDataType *pointer, bool force_to_0, Thread *current_thread);
+  INLINE CycleDataType *write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread);
+  INLINE CycleDataType *write_stage(int pipeline_stage, Thread *current_thread);
 
 
   INLINE CycleDataType *cheat() const;
   INLINE CycleDataType *cheat() const;
 
 

+ 57 - 56
panda/src/pipeline/pipelineCyclerDummyImpl.I

@@ -80,8 +80,8 @@ INLINE PipelineCyclerDummyImpl::
 //               walking the list of stages.
 //               walking the list of stages.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PipelineCyclerDummyImpl::
 INLINE void PipelineCyclerDummyImpl::
-lock() {
-  TAU_PROFILE("void PipelineCyclerDummyImpl::lock()", " ", TAU_USER);
+lock(Thread *) {
+  TAU_PROFILE("void PipelineCyclerDummyImpl::lock(Thread *)", " ", TAU_USER);
   nassertv(!_locked);
   nassertv(!_locked);
   _locked = true;
   _locked = true;
 }
 }
@@ -111,7 +111,7 @@ release() {
 //               data when this function is called.
 //               data when this function is called.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const CycleData *PipelineCyclerDummyImpl::
 INLINE const CycleData *PipelineCyclerDummyImpl::
-read() const {
+read(Thread *) const {
   TAU_PROFILE("const CycleData *PipelineCyclerDummyImpl::read()", " ", TAU_USER);
   TAU_PROFILE("const CycleData *PipelineCyclerDummyImpl::read()", " ", TAU_USER);
   // This function isn't truly const, but it doesn't change the data
   // This function isn't truly const, but it doesn't change the data
   // in any meaningful way, so we pretend it is.
   // in any meaningful way, so we pretend it is.
@@ -172,7 +172,7 @@ release_read(const CycleData *pointer) const {
 //               stage (but see elevate_read).
 //               stage (but see elevate_read).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerDummyImpl::
 INLINE CycleData *PipelineCyclerDummyImpl::
-write() {
+write(Thread *) {
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::write()", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::write()", " ", TAU_USER);
   _write_count++;
   _write_count++;
 
 
@@ -186,6 +186,42 @@ write() {
   return _data;
   return _data;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PipelineCyclerDummyImpl::write_upstream
+//       Access: Public
+//  Description: This special variant on write() will automatically
+//               propagate changes back to upstream pipeline stages.
+//               If force_to_0 is false, then it propagates back only
+//               as long as the CycleData pointers are equivalent,
+//               guaranteeing that it does not modify upstream data
+//               (other than the modification that will be performed
+//               by the code that returns this pointer).  This is
+//               particularly appropriate for minor updates, where it
+//               doesn't matter much if the update is lost, such as
+//               storing a cached value.
+//
+//               If force_to_0 is dummy, then the CycleData pointer for
+//               the current pipeline stage is propagated all the way
+//               back up to stage 0; after this call, there will be
+//               only one CycleData pointer that is duplicated in all
+//               stages between stage 0 and the current stage.  This
+//               may undo some recent changes that were made
+//               independently at pipeline stage 0 (or any other
+//               upstream stage).  However, it guarantees that the
+//               change that is to be applied at this pipeline stage
+//               will stick.  This is slightly dangerous because of
+//               the risk of losing upstream changes; generally, this
+//               should only be done when you are confident that there
+//               are no upstream changes to be lost (for instance, for
+//               an object that has been recently created).
+////////////////////////////////////////////////////////////////////
+CycleData *PipelineCyclerDummyImpl::
+write_upstream(bool, Thread *) {
+  TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::write_upstream(bool)", " ", TAU_USER);
+  _write_count++;
+  return _data;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PipelineCyclerDummyImpl::elevate_read
 //     Function: PipelineCyclerDummyImpl::elevate_read
 //       Access: Public
 //       Access: Public
@@ -196,7 +232,7 @@ write() {
 //               current stage.
 //               current stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerDummyImpl::
 INLINE CycleData *PipelineCyclerDummyImpl::
-elevate_read(const CycleData *pointer) {
+elevate_read(const CycleData *pointer, Thread *) {
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::elevate_read(const CycleData *)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::elevate_read(const CycleData *)", " ", TAU_USER);
   release_read(pointer);
   release_read(pointer);
   return write();
   return write();
@@ -211,7 +247,7 @@ elevate_read(const CycleData *pointer) {
 //               write_upstream().
 //               write_upstream().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerDummyImpl::
 INLINE CycleData *PipelineCyclerDummyImpl::
-elevate_read_upstream(const CycleData *pointer, bool force_to_0) {
+elevate_read_upstream(const CycleData *pointer, bool force_to_0, Thread *) {
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::elevate_read_upstream(const CycleData *, bool)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::elevate_read_upstream(const CycleData *, bool)", " ", TAU_USER);
   release_read(pointer);
   release_read(pointer);
   return write_upstream(force_to_0);
   return write_upstream(force_to_0);
@@ -270,11 +306,11 @@ get_num_stages() {
 //               data when this function is called.
 //               data when this function is called.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const CycleData *PipelineCyclerDummyImpl::
 INLINE const CycleData *PipelineCyclerDummyImpl::
-read_stage(int n) const {
+read_stage(int pipeline_stage, Thread *) const {
   TAU_PROFILE("const CycleData *PipelineCyclerDummyImpl::read_stage(int)", " ", TAU_USER);
   TAU_PROFILE("const CycleData *PipelineCyclerDummyImpl::read_stage(int)", " ", TAU_USER);
   // This function isn't truly const, but it doesn't change the data
   // This function isn't truly const, but it doesn't change the data
   // in any meaningful way, so we pretend it is.
   // in any meaningful way, so we pretend it is.
-  nassertr(n == 0, NULL);
+  nassertr(pipeline_stage == 0, NULL);
   ((PipelineCyclerDummyImpl *)this)->_read_count++;
   ((PipelineCyclerDummyImpl *)this)->_read_count++;
 
 
   // It's not an error to grab a read pointer while someone else holds
   // It's not an error to grab a read pointer while someone else holds
@@ -289,52 +325,16 @@ read_stage(int n) const {
 //               read_stage().
 //               read_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PipelineCyclerDummyImpl::
 INLINE void PipelineCyclerDummyImpl::
-release_read_stage(int n, const CycleData *pointer) const {
+release_read_stage(int pipeline_stage, const CycleData *pointer) const {
   TAU_PROFILE("void PipelineCyclerDummyImpl::release_read_stage(int, const CycleData *)", " ", TAU_USER);
   TAU_PROFILE("void PipelineCyclerDummyImpl::release_read_stage(int, const CycleData *)", " ", TAU_USER);
   // This function isn't truly const, but it doesn't change the data
   // This function isn't truly const, but it doesn't change the data
   // in any meaningful way, so we pretend it is.
   // in any meaningful way, so we pretend it is.
-  nassertv(n == 0);
+  nassertv(pipeline_stage == 0);
   nassertv(pointer == _data);
   nassertv(pointer == _data);
   nassertv(_read_count > 0);
   nassertv(_read_count > 0);
   ((PipelineCyclerDummyImpl *)this)->_read_count--;
   ((PipelineCyclerDummyImpl *)this)->_read_count--;
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: PipelineCyclerDummyImpl::write_upstream
-//       Access: Public
-//  Description: This special variant on write() will automatically
-//               propagate changes back to upstream pipeline stages.
-//               If force_to_0 is false, then it propagates back only
-//               as long as the CycleData pointers are equivalent,
-//               guaranteeing that it does not modify upstream data
-//               (other than the modification that will be performed
-//               by the code that returns this pointer).  This is
-//               particularly appropriate for minor updates, where it
-//               doesn't matter much if the update is lost, such as
-//               storing a cached value.
-//
-//               If force_to_0 is dummy, then the CycleData pointer for
-//               the current pipeline stage is propagated all the way
-//               back up to stage 0; after this call, there will be
-//               only one CycleData pointer that is duplicated in all
-//               stages between stage 0 and the current stage.  This
-//               may undo some recent changes that were made
-//               independently at pipeline stage 0 (or any other
-//               upstream stage).  However, it guarantees that the
-//               change that is to be applied at this pipeline stage
-//               will stick.  This is slightly dangerous because of
-//               the risk of losing upstream changes; generally, this
-//               should only be done when you are confident that there
-//               are no upstream changes to be lost (for instance, for
-//               an object that has been recently created).
-////////////////////////////////////////////////////////////////////
-CycleData *PipelineCyclerDummyImpl::
-write_upstream(bool) {
-  TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::write_upstream(bool)", " ", TAU_USER);
-  _write_count++;
-  return _data;
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PipelineCyclerDummyImpl::write_stage
 //     Function: PipelineCyclerDummyImpl::write_stage
 //       Access: Public
 //       Access: Public
@@ -346,9 +346,9 @@ write_upstream(bool) {
 //               release_write_stage().
 //               release_write_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerDummyImpl::
 INLINE CycleData *PipelineCyclerDummyImpl::
-write_stage(int n) {
+write_stage(int pipeline_stage, Thread *) {
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::write_stage(int)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::write_stage(int)", " ", TAU_USER);
-  nassertr(n == 0, (CycleData *)NULL);
+  nassertr(pipeline_stage == 0, (CycleData *)NULL);
   _write_count++;
   _write_count++;
   return _data;
   return _data;
 }
 }
@@ -364,9 +364,9 @@ write_stage(int n) {
 //               release_write_stage().
 //               release_write_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerDummyImpl::
 INLINE CycleData *PipelineCyclerDummyImpl::
-write_stage_upstream(int n, bool) {
+write_stage_upstream(int pipeline_stage, bool, Thread *) {
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::write_stage_upstream(int)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::write_stage_upstream(int)", " ", TAU_USER);
-  nassertr(n == 0, (CycleData *)NULL);
+  nassertr(pipeline_stage == 0, (CycleData *)NULL);
   _write_count++;
   _write_count++;
   return _data;
   return _data;
 }
 }
@@ -381,9 +381,9 @@ write_stage_upstream(int n, bool) {
 //               current stage.
 //               current stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerDummyImpl::
 INLINE CycleData *PipelineCyclerDummyImpl::
-elevate_read_stage(int n, const CycleData *pointer) {
+elevate_read_stage(int pipeline_stage, const CycleData *pointer, Thread *) {
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::elevate_read_stage(int, CycleData *)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::elevate_read_stage(int, CycleData *)", " ", TAU_USER);
-  nassertr(n == 0, NULL);
+  nassertr(pipeline_stage == 0, NULL);
   release_read(pointer);
   release_read(pointer);
   return write();
   return write();
 }
 }
@@ -398,9 +398,10 @@ elevate_read_stage(int n, const CycleData *pointer) {
 //               current stage.
 //               current stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerDummyImpl::
 INLINE CycleData *PipelineCyclerDummyImpl::
-elevate_read_stage_upstream(int n, const CycleData *pointer, bool) {
+elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer, 
+                            bool, Thread *) {
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::elevate_read_stage(int, CycleData *)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerDummyImpl::elevate_read_stage(int, CycleData *)", " ", TAU_USER);
-  nassertr(n == 0, NULL);
+  nassertr(pipeline_stage == 0, NULL);
   release_read(pointer);
   release_read(pointer);
   return write();
   return write();
 }
 }
@@ -412,9 +413,9 @@ elevate_read_stage_upstream(int n, const CycleData *pointer, bool) {
 //               write_stage().
 //               write_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PipelineCyclerDummyImpl::
 INLINE void PipelineCyclerDummyImpl::
-release_write_stage(int n, CycleData *pointer) {
+release_write_stage(int pipeline_stage, CycleData *pointer) {
   TAU_PROFILE("void PipelineCyclerDummyImpl::release_write_stage(int, CycleData *)", " ", TAU_USER);
   TAU_PROFILE("void PipelineCyclerDummyImpl::release_write_stage(int, CycleData *)", " ", TAU_USER);
-  nassertv(n == 0 && pointer == _data);
+  nassertv(pipeline_stage == 0 && pointer == _data);
   nassertv(_write_count > 0);
   nassertv(_write_count > 0);
   _write_count--;
   _write_count--;
 }
 }

+ 14 - 14
panda/src/pipeline/pipelineCyclerDummyImpl.h

@@ -52,29 +52,29 @@ public:
   INLINE void operator = (const PipelineCyclerDummyImpl &copy);
   INLINE void operator = (const PipelineCyclerDummyImpl &copy);
   INLINE ~PipelineCyclerDummyImpl();
   INLINE ~PipelineCyclerDummyImpl();
 
 
-  INLINE void lock();
+  INLINE void lock(Thread *current_thread = NULL);
   INLINE void release();
   INLINE void release();
 
 
-  INLINE const CycleData *read() const;
+  INLINE const CycleData *read(Thread *current_thread) const;
   INLINE void increment_read(const CycleData *pointer) const;
   INLINE void increment_read(const CycleData *pointer) const;
   INLINE void release_read(const CycleData *pointer) const;
   INLINE void release_read(const CycleData *pointer) const;
 
 
-  INLINE CycleData *write();
-  INLINE CycleData *elevate_read(const CycleData *pointer);
-  INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0);
+  INLINE CycleData *write(Thread *current_thread);
+  INLINE CycleData *write_upstream(bool force_to_0, Thread *current_thread);
+  INLINE CycleData *elevate_read(const CycleData *pointer, Thread *current_thread);
+  INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0, Thread *current_thread);
   INLINE void increment_write(CycleData *pointer) const;
   INLINE void increment_write(CycleData *pointer) const;
   INLINE void release_write(CycleData *pointer);
   INLINE void release_write(CycleData *pointer);
 
 
   INLINE int get_num_stages();
   INLINE int get_num_stages();
-  INLINE const CycleData *read_stage(int n) const;
-  INLINE void release_read_stage(int n, const CycleData *pointer) const;
-  INLINE CycleData *write_upstream(bool force_to_0);
-  INLINE CycleData *write_stage(int n);
-  INLINE CycleData *write_stage_upstream(int n, bool force_to_0);
-  INLINE CycleData *elevate_read_stage(int n, const CycleData *pointer);
-  INLINE CycleData *elevate_read_stage_upstream(int n, const CycleData *pointer,
-                                                bool force_to_0);
-  INLINE void release_write_stage(int n, CycleData *pointer);
+  INLINE const CycleData *read_stage(int pipeline_stage, Thread *current_thread) const;
+  INLINE void release_read_stage(int pipeline_stage, const CycleData *pointer) const;
+  INLINE CycleData *write_stage(int pipeline_stage, Thread *current_thread);
+  INLINE CycleData *write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread);
+  INLINE CycleData *elevate_read_stage(int pipeline_stage, const CycleData *pointer, Thread *current_thread);
+  INLINE CycleData *elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer,
+                                                bool force_to_0, Thread *current_thread);
+  INLINE void release_write_stage(int pipeline_stage, CycleData *pointer);
 
 
   INLINE TypeHandle get_parent_type() const;
   INLINE TypeHandle get_parent_type() const;
 
 

+ 48 - 48
panda/src/pipeline/pipelineCyclerTrivialImpl.I

@@ -85,7 +85,7 @@ INLINE PipelineCyclerTrivialImpl::
 //               walking the list of stages.
 //               walking the list of stages.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PipelineCyclerTrivialImpl::
 INLINE void PipelineCyclerTrivialImpl::
-lock() {
+lock(Thread *) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -107,7 +107,7 @@ release() {
 //               released by calling release_read().
 //               released by calling release_read().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const CycleData *PipelineCyclerTrivialImpl::
 INLINE const CycleData *PipelineCyclerTrivialImpl::
-read() const {
+read(Thread *) const {
 #ifdef SIMPLE_STRUCT_POINTERS
 #ifdef SIMPLE_STRUCT_POINTERS
   return (const CycleData *)this;
   return (const CycleData *)this;
 #else
 #else
@@ -153,7 +153,45 @@ release_read(const CycleData *) const {
 //               stage (but see elevate_read).
 //               stage (but see elevate_read).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrivialImpl::
 INLINE CycleData *PipelineCyclerTrivialImpl::
-write() {
+write(Thread *) {
+#ifdef SIMPLE_STRUCT_POINTERS
+  return (CycleData *)this;
+#else
+  return _data;
+#endif  // SIMPLE_STRUCT_POINTERS
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PipelineCyclerTrivialImpl::write_upstream
+//       Access: Public
+//  Description: This special variant on write() will automatically
+//               propagate changes back to upstream pipeline stages.
+//               If force_to_0 is false, then it propagates back only
+//               as long as the CycleData pointers are equivalent,
+//               guaranteeing that it does not modify upstream data
+//               (other than the modification that will be performed
+//               by the code that returns this pointer).  This is
+//               particularly appropriate for minor updates, where it
+//               doesn't matter much if the update is lost, such as
+//               storing a cached value.
+//
+//               If force_to_0 is trivial, then the CycleData pointer for
+//               the current pipeline stage is propagated all the way
+//               back up to stage 0; after this call, there will be
+//               only one CycleData pointer that is duplicated in all
+//               stages between stage 0 and the current stage.  This
+//               may undo some recent changes that were made
+//               independently at pipeline stage 0 (or any other
+//               upstream stage).  However, it guarantees that the
+//               change that is to be applied at this pipeline stage
+//               will stick.  This is slightly dangerous because of
+//               the risk of losing upstream changes; generally, this
+//               should only be done when you are confident that there
+//               are no upstream changes to be lost (for instance, for
+//               an object that has been recently created).
+////////////////////////////////////////////////////////////////////
+CycleData *PipelineCyclerTrivialImpl::
+write_upstream(bool, Thread *) {
 #ifdef SIMPLE_STRUCT_POINTERS
 #ifdef SIMPLE_STRUCT_POINTERS
   return (CycleData *)this;
   return (CycleData *)this;
 #else
 #else
@@ -171,7 +209,7 @@ write() {
 //               current stage.
 //               current stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrivialImpl::
 INLINE CycleData *PipelineCyclerTrivialImpl::
-elevate_read(const CycleData *) {
+elevate_read(const CycleData *, Thread *) {
 #ifdef SIMPLE_STRUCT_POINTERS
 #ifdef SIMPLE_STRUCT_POINTERS
   return (CycleData *)this;
   return (CycleData *)this;
 #else
 #else
@@ -188,7 +226,7 @@ elevate_read(const CycleData *) {
 //               write_upstream().
 //               write_upstream().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrivialImpl::
 INLINE CycleData *PipelineCyclerTrivialImpl::
-elevate_read_upstream(const CycleData *, bool) {
+elevate_read_upstream(const CycleData *, bool, Thread *) {
 #ifdef SIMPLE_STRUCT_POINTERS
 #ifdef SIMPLE_STRUCT_POINTERS
   return (CycleData *)this;
   return (CycleData *)this;
 #else
 #else
@@ -236,7 +274,7 @@ get_num_stages() {
 //               release_read().
 //               release_read().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const CycleData *PipelineCyclerTrivialImpl::
 INLINE const CycleData *PipelineCyclerTrivialImpl::
-read_stage(int) const {
+read_stage(int, Thread *) const {
 #ifdef SIMPLE_STRUCT_POINTERS
 #ifdef SIMPLE_STRUCT_POINTERS
   return (const CycleData *)this;
   return (const CycleData *)this;
 #else
 #else
@@ -254,44 +292,6 @@ INLINE void PipelineCyclerTrivialImpl::
 release_read_stage(int, const CycleData *) const {
 release_read_stage(int, const CycleData *) const {
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: PipelineCyclerTrivialImpl::write_upstream
-//       Access: Public
-//  Description: This special variant on write() will automatically
-//               propagate changes back to upstream pipeline stages.
-//               If force_to_0 is false, then it propagates back only
-//               as long as the CycleData pointers are equivalent,
-//               guaranteeing that it does not modify upstream data
-//               (other than the modification that will be performed
-//               by the code that returns this pointer).  This is
-//               particularly appropriate for minor updates, where it
-//               doesn't matter much if the update is lost, such as
-//               storing a cached value.
-//
-//               If force_to_0 is trivial, then the CycleData pointer for
-//               the current pipeline stage is propagated all the way
-//               back up to stage 0; after this call, there will be
-//               only one CycleData pointer that is duplicated in all
-//               stages between stage 0 and the current stage.  This
-//               may undo some recent changes that were made
-//               independently at pipeline stage 0 (or any other
-//               upstream stage).  However, it guarantees that the
-//               change that is to be applied at this pipeline stage
-//               will stick.  This is slightly dangerous because of
-//               the risk of losing upstream changes; generally, this
-//               should only be done when you are confident that there
-//               are no upstream changes to be lost (for instance, for
-//               an object that has been recently created).
-////////////////////////////////////////////////////////////////////
-CycleData *PipelineCyclerTrivialImpl::
-write_upstream(bool) {
-#ifdef SIMPLE_STRUCT_POINTERS
-  return (CycleData *)this;
-#else
-  return _data;
-#endif  // SIMPLE_STRUCT_POINTERS
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PipelineCyclerTrivialImpl::write_stage
 //     Function: PipelineCyclerTrivialImpl::write_stage
 //       Access: Public
 //       Access: Public
@@ -303,7 +303,7 @@ write_upstream(bool) {
 //               release_write_stage().
 //               release_write_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrivialImpl::
 INLINE CycleData *PipelineCyclerTrivialImpl::
-write_stage(int) {
+write_stage(int, Thread *) {
 #ifdef SIMPLE_STRUCT_POINTERS
 #ifdef SIMPLE_STRUCT_POINTERS
   return (CycleData *)this;
   return (CycleData *)this;
 #else
 #else
@@ -322,7 +322,7 @@ write_stage(int) {
 //               release_write_stage().
 //               release_write_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrivialImpl::
 INLINE CycleData *PipelineCyclerTrivialImpl::
-write_stage_upstream(int, bool) {
+write_stage_upstream(int, bool, Thread *) {
 #ifdef SIMPLE_STRUCT_POINTERS
 #ifdef SIMPLE_STRUCT_POINTERS
   return (CycleData *)this;
   return (CycleData *)this;
 #else
 #else
@@ -340,7 +340,7 @@ write_stage_upstream(int, bool) {
 //               current stage.
 //               current stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrivialImpl::
 INLINE CycleData *PipelineCyclerTrivialImpl::
-elevate_read_stage(int, const CycleData *) {
+elevate_read_stage(int, const CycleData *, Thread *) {
 #ifdef SIMPLE_STRUCT_POINTERS
 #ifdef SIMPLE_STRUCT_POINTERS
   return (CycleData *)this;
   return (CycleData *)this;
 #else
 #else
@@ -358,7 +358,7 @@ elevate_read_stage(int, const CycleData *) {
 //               current stage.
 //               current stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrivialImpl::
 INLINE CycleData *PipelineCyclerTrivialImpl::
-elevate_read_stage_upstream(int, const CycleData *, bool) {
+elevate_read_stage_upstream(int, const CycleData *, bool, Thread *) {
 #ifdef SIMPLE_STRUCT_POINTERS
 #ifdef SIMPLE_STRUCT_POINTERS
   return (CycleData *)this;
   return (CycleData *)this;
 #else
 #else

+ 18 - 14
panda/src/pipeline/pipelineCyclerTrivialImpl.h

@@ -23,6 +23,7 @@
 
 
 #ifndef DO_PIPELINING
 #ifndef DO_PIPELINING
 
 
+#include "thread.h"
 #include "cycleData.h"
 #include "cycleData.h"
 
 
 class Pipeline;
 class Pipeline;
@@ -56,29 +57,32 @@ private:
 public:
 public:
   INLINE ~PipelineCyclerTrivialImpl();
   INLINE ~PipelineCyclerTrivialImpl();
 
 
-  INLINE void lock();
+  INLINE void lock(Thread *current_thread = NULL);
   INLINE void release();
   INLINE void release();
 
 
-  INLINE const CycleData *read() const;
+  INLINE const CycleData *read(Thread *current_thread) const;
   INLINE void increment_read(const CycleData *pointer) const;
   INLINE void increment_read(const CycleData *pointer) const;
   INLINE void release_read(const CycleData *pointer) const;
   INLINE void release_read(const CycleData *pointer) const;
 
 
-  INLINE CycleData *write();
-  INLINE CycleData *elevate_read(const CycleData *pointer);
-  INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0);
+  INLINE CycleData *write(Thread *current_thread);
+  INLINE CycleData *write_upstream(bool force_to_0, Thread *current_thread);
+  INLINE CycleData *elevate_read(const CycleData *pointer, Thread *current_thread);
+  INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0,
+                                          Thread *current_thread);
   INLINE void increment_write(CycleData *pointer) const;
   INLINE void increment_write(CycleData *pointer) const;
   INLINE void release_write(CycleData *pointer);
   INLINE void release_write(CycleData *pointer);
 
 
   INLINE int get_num_stages();
   INLINE int get_num_stages();
-  INLINE const CycleData *read_stage(int n) const;
-  INLINE void release_read_stage(int n, const CycleData *pointer) const;
-  INLINE CycleData *write_upstream(bool force_to_0);
-  INLINE CycleData *write_stage(int n);
-  INLINE CycleData *write_stage_upstream(int n, bool force_to_0);
-  INLINE CycleData *elevate_read_stage(int n, const CycleData *pointer);
-  INLINE CycleData *elevate_read_stage_upstream(int n, const CycleData *pointer,
-                                                bool force_to_0);
-  INLINE void release_write_stage(int n, CycleData *pointer);
+  INLINE const CycleData *read_stage(int pipeline_stage, Thread *current_thread) const;
+  INLINE void release_read_stage(int pipeline_stage, const CycleData *pointer) const;
+  INLINE CycleData *write_stage(int pipeline_stage, Thread *current_thread);
+  INLINE CycleData *write_stage_upstream(int pipeline_stage, bool force_to_0,
+                                         Thread *current_thread);
+  INLINE CycleData *elevate_read_stage(int pipeline_stage, const CycleData *pointer,
+                                       Thread *current_thread);
+  INLINE CycleData *elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer,
+                                                bool force_to_0, Thread *current_thread);
+  INLINE void release_write_stage(int pipeline_stage, CycleData *pointer);
 
 
   INLINE TypeHandle get_parent_type() const;
   INLINE TypeHandle get_parent_type() const;
 
 

+ 85 - 69
panda/src/pipeline/pipelineCyclerTrueImpl.I

@@ -30,6 +30,19 @@ lock() {
   _lock.lock();
   _lock.lock();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: PipelineCyclerTrueImpl::lock
+//       Access: Public
+//  Description: Grabs an overall lock on the cycler.  Release it with
+//               a call to release().  This lock should be held while
+//               walking the list of stages.
+////////////////////////////////////////////////////////////////////
+INLINE void PipelineCyclerTrueImpl::
+lock(Thread *current_thread) {
+  TAU_PROFILE("void PipelineCyclerTrueImpl::lock(Thread *)", " ", TAU_USER);
+  _lock.lock(current_thread);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PipelineCyclerTrueImpl::release
 //     Function: PipelineCyclerTrueImpl::release
 //       Access: Public
 //       Access: Public
@@ -54,11 +67,11 @@ release() {
 //               data when this function is called.
 //               data when this function is called.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const CycleData *PipelineCyclerTrueImpl::
 INLINE const CycleData *PipelineCyclerTrueImpl::
-read() const {
-  TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read()", " ", TAU_USER);
-  int pipeline_stage = Thread::get_current_pipeline_stage();
+read(Thread *current_thread) const {
+  TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read(Thread *)", " ", TAU_USER);
+  int pipeline_stage = current_thread->get_pipeline_stage();
   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
-  _lock.lock();
+  _lock.lock(current_thread);
   return _data[pipeline_stage];
   return _data[pipeline_stage];
 }
 }
 
 
@@ -77,7 +90,7 @@ increment_read(const CycleData *pointer) const {
   nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
   nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
   nassertv(_data[pipeline_stage] == pointer);
   nassertv(_data[pipeline_stage] == pointer);
 #endif
 #endif
-  _lock.lock();
+  _lock.elevate_lock();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -114,10 +127,45 @@ release_read(const CycleData *pointer) const {
 //               stage (but see elevate_read).
 //               stage (but see elevate_read).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrueImpl::
 INLINE CycleData *PipelineCyclerTrueImpl::
-write() {
-  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::write()", " ", TAU_USER);
-  int pipeline_stage = Thread::get_current_pipeline_stage();
-  return write_stage(pipeline_stage);
+write(Thread *current_thread) {
+  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::write(Thread *)", " ", TAU_USER);
+  return write_stage(current_thread->get_pipeline_stage(), current_thread);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: PipelineCyclerTrueImpl::write_upstream
+//       Access: Public
+//  Description: This special variant on write() will automatically
+//               propagate changes back to upstream pipeline stages.
+//               If force_to_0 is false, then it propagates back only
+//               as long as the CycleData pointers are equivalent,
+//               guaranteeing that it does not modify upstream data
+//               (other than the modification that will be performed
+//               by the code that returns this pointer).  This is
+//               particularly appropriate for minor updates, where it
+//               doesn't matter much if the update is lost, such as
+//               storing a cached value.
+//
+//               If force_to_0 is true, then the CycleData pointer for
+//               the current pipeline stage is propagated all the way
+//               back up to stage 0; after this call, there will be
+//               only one CycleData pointer that is duplicated in all
+//               stages between stage 0 and the current stage.  This
+//               may undo some recent changes that were made
+//               independently at pipeline stage 0 (or any other
+//               upstream stage).  However, it guarantees that the
+//               change that is to be applied at this pipeline stage
+//               will stick.  This is slightly dangerous because of
+//               the risk of losing upstream changes; generally, this
+//               should only be done when you are confident that there
+//               are no upstream changes to be lost (for instance, for
+//               an object that has been recently created).
+////////////////////////////////////////////////////////////////////
+INLINE CycleData *PipelineCyclerTrueImpl::
+write_upstream(bool force_to_0, Thread *current_thread) {
+  TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::write_upstream(bool, Thread *)", " ", TAU_USER);
+  return write_stage_upstream(current_thread->get_pipeline_stage(), force_to_0,
+                              current_thread);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -130,14 +178,14 @@ write() {
 //               current stage.
 //               current stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrueImpl::
 INLINE CycleData *PipelineCyclerTrueImpl::
-elevate_read(const CycleData *pointer) {
+elevate_read(const CycleData *pointer, Thread *current_thread) {
   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read(const CycleData *)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read(const CycleData *)", " ", TAU_USER);
 #ifdef _DEBUG
 #ifdef _DEBUG
-  int pipeline_stage = Thread::get_current_pipeline_stage();
+  int pipeline_stage = current_thread->get_pipeline_stage();
   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
   nassertr(_data[pipeline_stage] == pointer, NULL);
   nassertr(_data[pipeline_stage] == pointer, NULL);
 #endif
 #endif
-  CycleData *new_pointer = write();
+  CycleData *new_pointer = write(current_thread);
   _lock.release();
   _lock.release();
   return new_pointer;
   return new_pointer;
 }
 }
@@ -151,14 +199,14 @@ elevate_read(const CycleData *pointer) {
 //               write_upstream().
 //               write_upstream().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrueImpl::
 INLINE CycleData *PipelineCyclerTrueImpl::
-elevate_read_upstream(const CycleData *pointer, bool force_to_0) {
+elevate_read_upstream(const CycleData *pointer, bool force_to_0, Thread *current_thread) {
   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_upstream(const CycleData *, bool)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_upstream(const CycleData *, bool)", " ", TAU_USER);
 #ifdef _DEBUG
 #ifdef _DEBUG
-  int pipeline_stage = Thread::get_current_pipeline_stage();
+  int pipeline_stage = current_thread->get_pipeline_stage();
   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
   nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
   nassertr(_data[pipeline_stage] == pointer, NULL);
   nassertr(_data[pipeline_stage] == pointer, NULL);
 #endif
 #endif
-  CycleData *new_pointer = write_upstream(force_to_0);
+  CycleData *new_pointer = write_upstream(force_to_0, current_thread);
   _lock.release();
   _lock.release();
   return new_pointer;
   return new_pointer;
 }
 }
@@ -178,7 +226,7 @@ increment_write(CycleData *pointer) const {
   nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
   nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
   nassertv(_data[pipeline_stage] == pointer);
   nassertv(_data[pipeline_stage] == pointer);
 #endif
 #endif
-  _lock.lock();
+  _lock.elevate_lock();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -220,11 +268,11 @@ get_num_stages() {
 //               data when this function is called.
 //               data when this function is called.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE const CycleData *PipelineCyclerTrueImpl::
 INLINE const CycleData *PipelineCyclerTrueImpl::
-read_stage(int n) const {
+read_stage(int pipeline_stage, Thread *current_thread) const {
   TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int)", " ", TAU_USER);
   TAU_PROFILE("const CycleData *PipelineCyclerTrueImpl::read_stage(int)", " ", TAU_USER);
-  nassertr(n >= 0 && n < _num_stages, NULL);
-  _lock.lock();
-  return _data[n];
+  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
+  _lock.lock(current_thread);
+  return _data[pipeline_stage];
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -234,50 +282,15 @@ read_stage(int n) const {
 //               read_stage().
 //               read_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PipelineCyclerTrueImpl::
 INLINE void PipelineCyclerTrueImpl::
-release_read_stage(int n, const CycleData *pointer) const {
+release_read_stage(int pipeline_stage, const CycleData *pointer) const {
   TAU_PROFILE("void PipelineCyclerTrueImpl::release_read_stage(int, const CycleData *)", " ", TAU_USER);
   TAU_PROFILE("void PipelineCyclerTrueImpl::release_read_stage(int, const CycleData *)", " ", TAU_USER);
 #ifdef _DEBUG
 #ifdef _DEBUG
-  nassertv(n >= 0 && n < _num_stages);
-  nassertv(_data[n] == pointer);
+  nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
+  nassertv(_data[pipeline_stage] == pointer);
 #endif
 #endif
   _lock.release();
   _lock.release();
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: PipelineCyclerTrueImpl::write_upstream
-//       Access: Public
-//  Description: This special variant on write() will automatically
-//               propagate changes back to upstream pipeline stages.
-//               If force_to_0 is false, then it propagates back only
-//               as long as the CycleData pointers are equivalent,
-//               guaranteeing that it does not modify upstream data
-//               (other than the modification that will be performed
-//               by the code that returns this pointer).  This is
-//               particularly appropriate for minor updates, where it
-//               doesn't matter much if the update is lost, such as
-//               storing a cached value.
-//
-//               If force_to_0 is true, then the CycleData pointer for
-//               the current pipeline stage is propagated all the way
-//               back up to stage 0; after this call, there will be
-//               only one CycleData pointer that is duplicated in all
-//               stages between stage 0 and the current stage.  This
-//               may undo some recent changes that were made
-//               independently at pipeline stage 0 (or any other
-//               upstream stage).  However, it guarantees that the
-//               change that is to be applied at this pipeline stage
-//               will stick.  This is slightly dangerous because of
-//               the risk of losing upstream changes; generally, this
-//               should only be done when you are confident that there
-//               are no upstream changes to be lost (for instance, for
-//               an object that has been recently created).
-////////////////////////////////////////////////////////////////////
-INLINE CycleData *PipelineCyclerTrueImpl::
-write_upstream(bool force_to_0) {
-  int pipeline_stage = Thread::get_current_pipeline_stage();
-  return write_stage_upstream(pipeline_stage, force_to_0);
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: PipelineCyclerTrueImpl::elevate_read_stage
 //     Function: PipelineCyclerTrueImpl::elevate_read_stage
 //       Access: Public
 //       Access: Public
@@ -288,13 +301,14 @@ write_upstream(bool force_to_0) {
 //               indicated stage.
 //               indicated stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrueImpl::
 INLINE CycleData *PipelineCyclerTrueImpl::
-elevate_read_stage(int n, const CycleData *pointer) {
+elevate_read_stage(int pipeline_stage, const CycleData *pointer,
+                   Thread *current_thread) {
   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
 #ifdef _DEBUG
 #ifdef _DEBUG
-  nassertr(n >= 0 && n < _num_stages, NULL);
-  nassertr(_data[n] == pointer, NULL);
+  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
+  nassertr(_data[pipeline_stage] == pointer, NULL);
 #endif
 #endif
-  CycleData *new_pointer = write_stage(n);
+  CycleData *new_pointer = write_stage(pipeline_stage, current_thread);
   _lock.release();
   _lock.release();
   return new_pointer;
   return new_pointer;
 }
 }
@@ -309,13 +323,15 @@ elevate_read_stage(int n, const CycleData *pointer) {
 //               indicated stage.
 //               indicated stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE CycleData *PipelineCyclerTrueImpl::
 INLINE CycleData *PipelineCyclerTrueImpl::
-elevate_read_stage_upstream(int n, const CycleData *pointer, bool force_to_0) {
+elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer, 
+                            bool force_to_0, Thread *current_thread) {
   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
   TAU_PROFILE("CycleData *PipelineCyclerTrueImpl::elevate_read_stage(int, const CycleData *)", " ", TAU_USER);
 #ifdef _DEBUG
 #ifdef _DEBUG
-  nassertr(n >= 0 && n < _num_stages, NULL);
-  nassertr(_data[n] == pointer, NULL);
+  nassertr(pipeline_stage >= 0 && pipeline_stage < _num_stages, NULL);
+  nassertr(_data[pipeline_stage] == pointer, NULL);
 #endif
 #endif
-  CycleData *new_pointer = write_stage_upstream(n, force_to_0);
+  CycleData *new_pointer = 
+    write_stage_upstream(pipeline_stage, force_to_0, current_thread);
   _lock.release();
   _lock.release();
   return new_pointer;
   return new_pointer;
 }
 }
@@ -327,11 +343,11 @@ elevate_read_stage_upstream(int n, const CycleData *pointer, bool force_to_0) {
 //               write_stage().
 //               write_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 INLINE void PipelineCyclerTrueImpl::
 INLINE void PipelineCyclerTrueImpl::
-release_write_stage(int n, CycleData *pointer) {
+release_write_stage(int pipeline_stage, CycleData *pointer) {
   TAU_PROFILE("void PipelineCyclerTrueImpl::release_write_stage(int, const CycleData *)", " ", TAU_USER);
   TAU_PROFILE("void PipelineCyclerTrueImpl::release_write_stage(int, const CycleData *)", " ", TAU_USER);
 #ifdef _DEBUG
 #ifdef _DEBUG
-  nassertv(n >= 0 && n < _num_stages);
-  nassertv(_data[n] == pointer);
+  nassertv(pipeline_stage >= 0 && pipeline_stage < _num_stages);
+  nassertv(_data[pipeline_stage] == pointer);
 #endif
 #endif
   _lock.release();
   _lock.release();
 }
 }

+ 4 - 4
panda/src/pipeline/pipelineCyclerTrueImpl.cxx

@@ -140,8 +140,8 @@ PipelineCyclerTrueImpl::
 //               release_write_stage().
 //               release_write_stage().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CycleData *PipelineCyclerTrueImpl::
 CycleData *PipelineCyclerTrueImpl::
-write_stage(int pipeline_stage) {
-  _lock.lock();
+write_stage(int pipeline_stage, Thread *current_thread) {
+  _lock.lock(current_thread);
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
   nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {
   nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {
@@ -174,8 +174,8 @@ write_stage(int pipeline_stage) {
 //               pipeline stages.  See write_upstream().
 //               pipeline stages.  See write_upstream().
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CycleData *PipelineCyclerTrueImpl::
 CycleData *PipelineCyclerTrueImpl::
-write_stage_upstream(int pipeline_stage, bool force_to_0) {
-  _lock.lock();
+write_stage_upstream(int pipeline_stage, bool force_to_0, Thread *current_thread) {
+  _lock.lock(current_thread);
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
   nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {
   nassertd(pipeline_stage >= 0 && pipeline_stage < _num_stages) {

+ 16 - 12
panda/src/pipeline/pipelineCyclerTrueImpl.h

@@ -58,27 +58,31 @@ public:
   ~PipelineCyclerTrueImpl();
   ~PipelineCyclerTrueImpl();
 
 
   INLINE void lock();
   INLINE void lock();
+  INLINE void lock(Thread *current_thread);
   INLINE void release();
   INLINE void release();
 
 
-  INLINE const CycleData *read() const;
+  INLINE const CycleData *read(Thread *current_thread) const;
   INLINE void increment_read(const CycleData *pointer) const;
   INLINE void increment_read(const CycleData *pointer) const;
   INLINE void release_read(const CycleData *pointer) const;
   INLINE void release_read(const CycleData *pointer) const;
 
 
-  INLINE CycleData *write();
-  INLINE CycleData *elevate_read(const CycleData *pointer);
-  INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0);
+  INLINE CycleData *write(Thread *current_thread);
+  INLINE CycleData *write_upstream(bool force_to_0, Thread *current_thread);
+  INLINE CycleData *elevate_read(const CycleData *pointer, Thread *current_thread);
+  INLINE CycleData *elevate_read_upstream(const CycleData *pointer, bool force_to_0, Thread *current_thread);
   INLINE void increment_write(CycleData *pointer) const;
   INLINE void increment_write(CycleData *pointer) const;
   INLINE void release_write(CycleData *pointer);
   INLINE void release_write(CycleData *pointer);
 
 
   INLINE int get_num_stages();
   INLINE int get_num_stages();
-  INLINE const CycleData *read_stage(int n) const;
-  INLINE void release_read_stage(int n, const CycleData *pointer) const;
-  INLINE CycleData *write_upstream(bool force_to_0);
-  CycleData *write_stage(int pipeline_stage);
-  CycleData *write_stage_upstream(int pipeline_stage, bool force_to_0);
-  INLINE CycleData *elevate_read_stage(int n, const CycleData *pointer);
-  INLINE CycleData *elevate_read_stage_upstream(int n, const CycleData *pointer, bool force_to_0);
-  INLINE void release_write_stage(int n, CycleData *pointer);
+  INLINE const CycleData *read_stage(int pipeline_stage, Thread *current_thread) const;
+  INLINE void release_read_stage(int pipeline_stage, const CycleData *pointer) const;
+  CycleData *write_stage(int pipeline_stage, Thread *current_thread);
+  CycleData *write_stage_upstream(int pipeline_stage, bool force_to_0, 
+                                  Thread *current_thread);
+  INLINE CycleData *elevate_read_stage(int pipeline_stage, const CycleData *pointer, 
+                                       Thread *current_thread);
+  INLINE CycleData *elevate_read_stage_upstream(int pipeline_stage, const CycleData *pointer, 
+                                                bool force_to_0, Thread *current_thread);
+  INLINE void release_write_stage(int pipeline_stage, CycleData *pointer);
 
 
   INLINE TypeHandle get_parent_type() const;
   INLINE TypeHandle get_parent_type() const;
 
 

+ 61 - 2
panda/src/pipeline/reMutexDirect.I

@@ -25,7 +25,7 @@
 INLINE ReMutexDirect::
 INLINE ReMutexDirect::
 ReMutexDirect() 
 ReMutexDirect() 
 #ifndef HAVE_REMUTEXIMPL
 #ifndef HAVE_REMUTEXIMPL
-  : _cvar(_global_lock)
+  : _cvar_impl(_lock_impl)
 #endif
 #endif
 {
 {
 #ifndef HAVE_REMUTEXIMPL
 #ifndef HAVE_REMUTEXIMPL
@@ -51,7 +51,7 @@ INLINE ReMutexDirect::
 INLINE ReMutexDirect::
 INLINE ReMutexDirect::
 ReMutexDirect(const ReMutexDirect &copy)
 ReMutexDirect(const ReMutexDirect &copy)
 #ifndef HAVE_REMUTEXIMPL
 #ifndef HAVE_REMUTEXIMPL
-  : _cvar(_global_lock)
+  : _cvar_impl(_lock_impl)
 #endif
 #endif
 {
 {
   nassertv(false);
   nassertv(false);
@@ -92,6 +92,48 @@ lock() const {
 #endif  // HAVE_REMUTEXIMPL
 #endif  // HAVE_REMUTEXIMPL
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ReMutexDirect::lock
+//       Access: Public
+//  Description: This variant on lock() accepts the current thread as
+//               a parameter, if it is already known, as an
+//               optimization.
+////////////////////////////////////////////////////////////////////
+INLINE void ReMutexDirect::
+lock(Thread *current_thread) const {
+  TAU_PROFILE("void ReMutexDirect::lock(Thread *)", " ", TAU_USER);
+#ifdef HAVE_REMUTEXIMPL
+  ((ReMutexDirect *)this)->_impl.lock();
+#else
+  ((ReMutexDirect *)this)->do_lock(current_thread);
+#endif  // HAVE_REMUTEXIMPL
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: ReMutexDirect::elevate_lock
+//       Access: Public
+//  Description: This method increments the lock count, assuming the
+//               calling thread already holds the lock.  After this
+//               call, release() will need to be called one additional
+//               time to release the lock.
+//
+//               This method really performs the same function as
+//               lock(), but it offers a potential (slight)
+//               performance benefit when the calling thread knows
+//               that it already holds the lock.  It is an error to
+//               call this when the calling thread does not hold the
+//               lock.
+////////////////////////////////////////////////////////////////////
+INLINE void ReMutexDirect::
+elevate_lock() const {
+  TAU_PROFILE("void ReMutexDirect::elevate_lock()", " ", TAU_USER);
+#ifdef HAVE_REMUTEXIMPL
+  ((ReMutexDirect *)this)->_impl.lock();
+#else
+  ((ReMutexDirect *)this)->do_elevate_lock();
+#endif  // HAVE_REMUTEXIMPL
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ReMutexDirect::release
 //     Function: ReMutexDirect::release
 //       Access: Public
 //       Access: Public
@@ -126,3 +168,20 @@ INLINE bool ReMutexDirect::
 debug_is_locked() const {
 debug_is_locked() const {
   return true;
   return true;
 }
 }
+
+#ifndef HAVE_REMUTEXIMPL
+////////////////////////////////////////////////////////////////////
+//     Function: ReMutexDirect::do_lock
+//       Access: Private
+//  Description: The private implementation of lock(), for the case in
+//               which the underlying lock system does not provide a
+//               reentrant mutex (and therefore we have to build this
+//               functionality on top of the existing non-reentrant
+//               mutex).
+////////////////////////////////////////////////////////////////////
+INLINE void ReMutexDirect::
+do_lock() {
+  do_lock(Thread::get_current_thread());
+}
+#endif
+

+ 50 - 16
panda/src/pipeline/reMutexDirect.cxx

@@ -19,10 +19,6 @@
 #include "reMutexDirect.h"
 #include "reMutexDirect.h"
 #include "thread.h"
 #include "thread.h"
 
 
-#ifndef HAVE_REMUTEXIMPL
-MutexImpl ReMutexDirect::_global_lock;
-#endif  // !HAVE_REMUTEXIMPL
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ReMutexDirect::output
 //     Function: ReMutexDirect::output
 //       Access: Public
 //       Access: Public
@@ -45,36 +41,72 @@ output(ostream &out) const {
 //               mutex).
 //               mutex).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ReMutexDirect::
 void ReMutexDirect::
-do_lock() {
-  _global_lock.lock();
+do_lock(Thread *current_thread) {
+  _lock_impl.lock();
 
 
   if (_locking_thread == (Thread *)NULL) {
   if (_locking_thread == (Thread *)NULL) {
     // The mutex is not already locked by anyone.  Lock it.
     // The mutex is not already locked by anyone.  Lock it.
-    _locking_thread = Thread::get_current_thread();
+    _locking_thread = current_thread;
     ++_lock_count;
     ++_lock_count;
     nassertd(_lock_count == 1) {
     nassertd(_lock_count == 1) {
     }
     }
 
 
-  } else if (_locking_thread == Thread::get_current_thread()) {
+  } else if (_locking_thread == current_thread) {
     // The mutex is already locked by this thread.  Increment the lock
     // The mutex is already locked by this thread.  Increment the lock
     // count.
     // count.
     ++_lock_count;
     ++_lock_count;
     nassertd(_lock_count > 0) {
     nassertd(_lock_count > 0) {
     }
     }
-
+    
   } else {
   } else {
     // The mutex is locked by some other thread.  Go to sleep on the
     // The mutex is locked by some other thread.  Go to sleep on the
     // condition variable until it's unlocked.
     // condition variable until it's unlocked.
     while (_locking_thread != (Thread *)NULL) {
     while (_locking_thread != (Thread *)NULL) {
-      _cvar.wait();
+      _cvar_impl.wait();
     }
     }
     
     
-    _locking_thread = Thread::get_current_thread();
+    _locking_thread = current_thread;
     ++_lock_count;
     ++_lock_count;
     nassertd(_lock_count == 1) {
     nassertd(_lock_count == 1) {
     }
     }
   }
   }
-  _global_lock.release();
+  _lock_impl.release();
+}
+#endif  // !HAVE_REMUTEXIMPL
+
+#ifndef HAVE_REMUTEXIMPL
+////////////////////////////////////////////////////////////////////
+//     Function: ReMutexDirect::do_elevate_lock
+//       Access: Private
+//  Description: The private implementation of lock(), for the case in
+//               which the underlying lock system does not provide a
+//               reentrant mutex (and therefore we have to build this
+//               functionality on top of the existing non-reentrant
+//               mutex).
+////////////////////////////////////////////////////////////////////
+void ReMutexDirect::
+do_elevate_lock() {
+  _lock_impl.lock();
+
+#ifdef _DEBUG
+  nassertd(_locking_thread == Thread::get_current_thread()) {
+    _lock_impl.release();
+    return;
+  }
+#elif !defined(NDEBUG)
+  nassertd(_locking_thread != (Thread *)NULL) {
+    _lock_impl.release();
+    return;
+  }
+#endif  // NDEBUG
+
+  // We know the mutex is already locked by this thread.  Increment
+  // the lock count.
+  ++_lock_count;
+  nassertd(_lock_count > 0) {
+  }
+
+  _lock_impl.release();
 }
 }
 #endif  // !HAVE_REMUTEXIMPL
 #endif  // !HAVE_REMUTEXIMPL
 
 
@@ -90,16 +122,18 @@ do_lock() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void ReMutexDirect::
 void ReMutexDirect::
 do_release() {
 do_release() {
-  _global_lock.lock();
+  _lock_impl.lock();
 
 
+#ifdef _DEBUG
   if (_locking_thread != Thread::get_current_thread()) {
   if (_locking_thread != Thread::get_current_thread()) {
     ostringstream ostr;
     ostringstream ostr;
     ostr << *_locking_thread << " attempted to release "
     ostr << *_locking_thread << " attempted to release "
          << *this << " which it does not own";
          << *this << " which it does not own";
     nassert_raise(ostr.str());
     nassert_raise(ostr.str());
-    _global_lock.release();
+    _lock_impl.release();
     return;
     return;
   }
   }
+#endif  // _DEBUG
 
 
   nassertd(_lock_count > 0) {
   nassertd(_lock_count > 0) {
   }
   }
@@ -108,8 +142,8 @@ do_release() {
   if (_lock_count == 0) {
   if (_lock_count == 0) {
     // That was the last lock held by this thread.  Release the lock.
     // That was the last lock held by this thread.  Release the lock.
     _locking_thread = (Thread *)NULL;
     _locking_thread = (Thread *)NULL;
-    _cvar.signal();
+    _cvar_impl.signal();
   }
   }
-  _global_lock.release();
+  _lock_impl.release();
 }
 }
 #endif  // !HAVE_REMUTEXIMPL
 #endif  // !HAVE_REMUTEXIMPL

+ 7 - 3
panda/src/pipeline/reMutexDirect.h

@@ -41,6 +41,8 @@ private:
 
 
 public:
 public:
   INLINE void lock() const;
   INLINE void lock() const;
+  INLINE void lock(Thread *current_thread) const;
+  INLINE void elevate_lock() const;
   INLINE void release() const;
   INLINE void release() const;
 
 
   INLINE bool debug_is_locked() const;
   INLINE bool debug_is_locked() const;
@@ -53,14 +55,16 @@ private:
 
 
 #else
 #else
   // If we don't have a reentrant mutex, we have to hand-roll one.
   // If we don't have a reentrant mutex, we have to hand-roll one.
-  void do_lock();
+  INLINE void do_lock();
+  void do_lock(Thread *current_thread);
+  void do_elevate_lock();
   void do_release();
   void do_release();
 
 
   Thread *_locking_thread;
   Thread *_locking_thread;
   int _lock_count;
   int _lock_count;
-  ConditionVarImpl _cvar;
 
 
-  static MutexImpl _global_lock;
+  MutexImpl _lock_impl;
+  ConditionVarImpl _cvar_impl;
 #endif  // HAVE_REMUTEXIMPL
 #endif  // HAVE_REMUTEXIMPL
 };
 };
 
 

+ 15 - 0
panda/src/pipeline/reMutexHolder.I

@@ -30,6 +30,21 @@ ReMutexHolder(const ReMutex &mutex) {
 #endif
 #endif
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: ReMutexHolder::Constructor
+//       Access: Public
+//  Description: This variant on the constructor accepts the current
+//               thread as a parameter, if it is already known, as an
+//               optimization.
+////////////////////////////////////////////////////////////////////
+INLINE ReMutexHolder::
+ReMutexHolder(const ReMutex &mutex, Thread *current_thread) {
+#if defined(HAVE_THREADS) || !defined(NDEBUG)
+  _mutex = &mutex;
+  _mutex->lock(current_thread);
+#endif
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: ReMutexHolder::Constructor
 //     Function: ReMutexHolder::Constructor
 //       Access: Public
 //       Access: Public

+ 3 - 0
panda/src/pipeline/reMutexHolder.h

@@ -22,6 +22,8 @@
 #include "pandabase.h"
 #include "pandabase.h"
 #include "reMutex.h"
 #include "reMutex.h"
 
 
+class Thread;
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : ReMutexHolder
 //       Class : ReMutexHolder
 // Description : Similar to MutexHolder, but for a reentrant mutex.
 // Description : Similar to MutexHolder, but for a reentrant mutex.
@@ -29,6 +31,7 @@
 class EXPCL_PANDA ReMutexHolder {
 class EXPCL_PANDA ReMutexHolder {
 public:
 public:
   INLINE ReMutexHolder(const ReMutex &mutex);
   INLINE ReMutexHolder(const ReMutex &mutex);
+  INLINE ReMutexHolder(const ReMutex &mutex, Thread *current_thread);
   INLINE ReMutexHolder(ReMutex *&mutex);
   INLINE ReMutexHolder(ReMutex *&mutex);
   INLINE ~ReMutexHolder();
   INLINE ~ReMutexHolder();
 private:
 private:

+ 3 - 3
panda/src/putil/bamReader.cxx

@@ -600,7 +600,7 @@ void BamReader::
 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler) {
 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler) {
   PipelineCyclerBase *old_cycler = _reading_cycler;
   PipelineCyclerBase *old_cycler = _reading_cycler;
   _reading_cycler = &cycler;
   _reading_cycler = &cycler;
-  CycleData *cdata = cycler.write();
+  CycleData *cdata = cycler.write(Thread::get_current_thread());
   cdata->fillin(scan, this);
   cdata->fillin(scan, this);
   cycler.release_write(cdata);
   cycler.release_write(cdata);
   _reading_cycler = old_cycler;
   _reading_cycler = old_cycler;
@@ -617,7 +617,7 @@ read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler,
            void *extra_data) {
            void *extra_data) {
   PipelineCyclerBase *old_cycler = _reading_cycler;
   PipelineCyclerBase *old_cycler = _reading_cycler;
   _reading_cycler = &cycler;
   _reading_cycler = &cycler;
-  CycleData *cdata = cycler.write();
+  CycleData *cdata = cycler.write(Thread::get_current_thread());
   cdata->fillin(scan, this, extra_data);
   cdata->fillin(scan, this, extra_data);
   cycler.release_write(cdata);
   cycler.release_write(cdata);
   _reading_cycler = old_cycler;
   _reading_cycler = old_cycler;
@@ -1114,7 +1114,7 @@ resolve_cycler_pointers(PipelineCyclerBase *cycler,
       
       
   if (is_complete) {
   if (is_complete) {
     // Okay, here's the complete list of pointers for you!
     // Okay, here's the complete list of pointers for you!
-    CycleData *cdata = cycler->write();
+    CycleData *cdata = cycler->write(Thread::get_current_thread());
     int num_completed = cdata->complete_pointers(&references[0], this);
     int num_completed = cdata->complete_pointers(&references[0], this);
     cycler->release_write(cdata);
     cycler->release_write(cdata);
     if (num_completed != (int)references.size()) {
     if (num_completed != (int)references.size()) {

+ 2 - 2
panda/src/putil/bamWriter.cxx

@@ -282,7 +282,7 @@ write_pointer(Datagram &packet, const TypedWritable *object) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void BamWriter::
 void BamWriter::
 write_cdata(Datagram &packet, const PipelineCyclerBase &cycler) {
 write_cdata(Datagram &packet, const PipelineCyclerBase &cycler) {
-  const CycleData *cdata = cycler.read();
+  const CycleData *cdata = cycler.read(Thread::get_current_thread());
   cdata->write_datagram(this, packet);
   cdata->write_datagram(this, packet);
   cycler.release_read(cdata);
   cycler.release_read(cdata);
 }
 }
@@ -296,7 +296,7 @@ write_cdata(Datagram &packet, const PipelineCyclerBase &cycler) {
 void BamWriter::
 void BamWriter::
 write_cdata(Datagram &packet, const PipelineCyclerBase &cycler,
 write_cdata(Datagram &packet, const PipelineCyclerBase &cycler,
             void *extra_data) {
             void *extra_data) {
-  const CycleData *cdata = cycler.read();
+  const CycleData *cdata = cycler.read(Thread::get_current_thread());
   cdata->write_datagram(this, packet, extra_data);
   cdata->write_datagram(this, packet, extra_data);
   cycler.release_read(cdata);
   cycler.release_read(cdata);
 }
 }