Prechádzať zdrojové kódy

more substream fixes

David Rose 23 rokov pred
rodič
commit
07ca085727

+ 52 - 7
panda/src/express/subStreamBuf.cxx

@@ -23,6 +23,34 @@
 typedef int streamsize;
 #endif /* HAVE_STREAMSIZE */
 
+// Temporary hack to make these thread-safe.
+//#define SUBSTREAM_THREAD_SAFE
+
+#ifdef SUBSTREAM_THREAD_SAFE
+// This requires NSPR for now.
+#include <prlock.h>
+PRLock *substream_mutex = (PRLock *)NULL;
+
+inline void init_lock() {
+  if (substream_mutex == (PRLock *)NULL) {
+    substream_mutex = PR_NewLock();
+  }
+}
+inline void grab_lock() {
+  PR_Lock(substream_mutex);
+}
+inline void release_lock() {
+  PR_Unlock(substream_mutex);
+}
+#else  // SUBSTREAM_THREAD_SAFE
+inline void init_lock() {
+}
+inline void grab_lock() {
+}
+inline void release_lock() {
+}
+#endif  // SUBSTREAM_THREAD_SAFE
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SubStreamBuf::Constructor
 //       Access: Public
@@ -47,13 +75,14 @@ SubStreamBuf() {
   _cur = 0;
 
   // _unused counts the number of bytes at the beginning of the buffer
-  // that are unused.  Usually this is 0, but when we reach the end of
-  // the file we might not need the whole buffer to read the last bit,
-  // so the first part of the buffer is unused.  This is important to
-  // prevent us from inadvertently seeking into the unused part of the
-  // buffer.
+  // that are unused.  Usually this is 0 after a read, but when we
+  // reach the end of the file we might not need the whole buffer to
+  // read the last bit, so the first part of the buffer is unused.
+  // This is important to prevent us from inadvertently seeking into
+  // the unused part of the buffer.
   _unused = 0;
 
+  init_lock();
 
 #ifdef WIN32_VC
   // In spite of the claims of the MSDN Library to the contrary,
@@ -90,7 +119,9 @@ open(istream *source, streampos start, streampos end) {
   _start = start;
   _end = end;
   _cur = _start;
-  _unused = 0;
+
+  // Initially, the entire buffer is unused.  Duh.
+  _unused = egptr() - eback();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -136,8 +167,10 @@ seekoff(streamoff off, ios::seek_dir dir, int mode) {
     if (_end == (streampos)0) {
       // If the end of the file is unspecified, we have to seek to
       // find it.
+      grab_lock();
       _source->seekg(off, ios::end);
       new_pos = _source->tellg();
+      release_lock();
 
     } else {
       new_pos = _end + off;
@@ -181,6 +214,16 @@ seekpos(streampos pos, int mode) {
   return seekoff(pos, ios::beg, mode);
 }
 
+#ifdef WIN32_VC
+// Windows seems to be a little confused about the proper definition
+// of seekoff().  We have to define both variants in order to get
+// reliable seeking.
+streampos SubStreamBuf::
+seekoff(streamoff off, ios::seekdir dir, ios::openmode mode) {
+  return seekoff(off, (ios::seek_dir)dir, (int)mode);
+}
+#endif
+
 ////////////////////////////////////////////////////////////////////
 //     Function: SubStreamBuf::overflow
 //       Access: Protected, Virtual
@@ -232,12 +275,14 @@ underflow() {
       num_bytes = (size_t)(_end - _cur);
     }
 
-    _source->seekg(_cur);
     gbump(-(int)num_bytes);
     nassertr(gptr() + num_bytes <= egptr(), EOF);
 
+    grab_lock();
+    _source->seekg(_cur);
     _source->read(gptr(), num_bytes);
     size_t read_count = _source->gcount();
+    release_lock();
 
     if (read_count != num_bytes) {
       // Oops, we didn't read what we thought we would.

+ 4 - 0
panda/src/express/subStreamBuf.h

@@ -36,6 +36,10 @@ public:
   virtual streampos seekoff(streamoff off, ios::seek_dir dir, int mode);
   virtual streampos seekpos(streampos pos, int mode);
 
+#ifdef WIN32_VC
+  virtual streampos seekoff(streamoff off, ios::seekdir dir, ios::openmode mode);
+#endif
+
 protected:
   virtual int overflow(int c);
   virtual int sync(void);