diff --git a/panda/src/express/subStreamBuf.cxx b/panda/src/express/subStreamBuf.cxx index 002fc34720..e89a73d563 100644 --- a/panda/src/express/subStreamBuf.cxx +++ b/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 *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. diff --git a/panda/src/express/subStreamBuf.h b/panda/src/express/subStreamBuf.h index 634f4a26e5..1b04ecfd21 100644 --- a/panda/src/express/subStreamBuf.h +++ b/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);