From Colin McDonald,

"On fixing the pointer access I discovered that reading osga archives
    containing ive files went into a cpu loop.  This turned out to be a
    problem with proxy_streambuf on Solaris.  Public methods in the Solaris
    streambuf standard library implementation rely on the gptr() being set,
    which proxy_streambuf was not doing.  So I have modified
    proxy_streambuf to set the input sequence pointers, and have also
    aligned it more with the standard library streambuf implementation
    where all input is through underflow(), not uflow() which merely calls
    underflow() and advances the pointer."

From Robert Osfield, change from using pointer cast and assignment to using
    a templated _write and _read method to avoid pointer aliasing to 2/4/8
    byte boundaries that some computer system may produce.  These changes
    where inspried by Colin McDonalds change to using memcpy, these
    changes weren't merged as memcpy is not as clear in naming as _read,
    _write and memcpy will incurr a function call just for copy a
    uint.
This commit is contained in:
Robert Osfield
2005-06-24 19:50:14 +00:00
parent f2b4ac179d
commit 57eb631654
2 changed files with 47 additions and 32 deletions

View File

@@ -83,7 +83,8 @@ OSGA_Archive::IndexBlock* OSGA_Archive::IndexBlock::read(std::istream& in, bool
ptr += sizeof(size_type);
osg::swapBytes(ptr,sizeof(unsigned int));
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(ptr));
unsigned int filename_size; // = *(reinterpret_cast<unsigned int*>(ptr));
_read(ptr, filename_size);
ptr += sizeof(unsigned int);
ptr += filename_size;
@@ -113,7 +114,8 @@ std::string OSGA_Archive::IndexBlock::getFirstFileName() const
ptr += sizeof(pos_type);
ptr += sizeof(size_type);
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(ptr));
unsigned int filename_size; // = *(reinterpret_cast<unsigned int*>(ptr));
_read(ptr, filename_size);
ptr += sizeof(unsigned int);
return std::string(ptr, ptr+filename_size);
@@ -134,13 +136,16 @@ bool OSGA_Archive::IndexBlock::getFileReferences(FileNamePositionMap& indexMap)
char* end_ptr = _data + _offsetOfNextAvailableSpace;
while (ptr<end_ptr)
{
pos_type position = *(reinterpret_cast<pos_type*>(ptr));
pos_type position; // = *(reinterpret_cast<pos_type*>(ptr));
_read(ptr, position);
ptr += sizeof(pos_type);
size_type size = *(reinterpret_cast<size_type*>(ptr));
size_type size; // = *(reinterpret_cast<size_type*>(ptr));
_read(ptr, size);
ptr += sizeof(size_type);
unsigned int filename_size = *(reinterpret_cast<unsigned int*>(ptr));
unsigned int filename_size; // = *(reinterpret_cast<unsigned int*>(ptr));
_read(ptr, filename_size);
ptr += sizeof(unsigned int);
std::string filename(ptr, ptr+filename_size);
@@ -184,13 +189,16 @@ bool OSGA_Archive::IndexBlock::addFileReference(pos_type position, size_type siz
{
char* ptr = _data+_offsetOfNextAvailableSpace;
*(reinterpret_cast<pos_type*>(ptr)) = position;
//*(reinterpret_cast<pos_type*>(ptr)) = position;
_write(ptr, position);
ptr += sizeof(pos_type);
*(reinterpret_cast<size_type*>(ptr)) = size;
//*(reinterpret_cast<size_type*>(ptr)) = size;
_write(ptr, size);
ptr += sizeof(size_type);
*(reinterpret_cast<unsigned int*>(ptr)) = filename.size();
//*(reinterpret_cast<unsigned int*>(ptr)) = filename.size();
_write(ptr, static_cast<unsigned int>(filename.size()));
ptr += sizeof(unsigned int);
for(unsigned int i=0;i<filename.size();++i, ++ptr)
@@ -478,41 +486,36 @@ class proxy_streambuf : public std::streambuf
proxy_streambuf(std::streambuf* streambuf, unsigned int numChars):
_streambuf(streambuf),
_numChars(numChars),
value_peeked(false),
peek_value(0) {}
_numChars(numChars) {
setg(&oneChar, (&oneChar)+1, (&oneChar)+1);
}
/// Destructor deallocates no buffer space.
virtual ~proxy_streambuf() {}
std::streambuf* _streambuf;
unsigned int _numChars;
bool value_peeked;
int_type peek_value;
protected:
virtual int_type uflow ()
unsigned int _numChars;
char_type oneChar;
virtual int_type underflow()
{
if (_numChars==0) return -1;
if ( gptr() == &oneChar ) return traits_type::to_int_type(oneChar);
if ( _numChars==0 ) return traits_type::eof();
--_numChars;
int_type val = value_peeked ? peek_value : _streambuf->sbumpc();
value_peeked = false;
return val;
}
virtual int_type
underflow()
{
if (value_peeked) return peek_value;
value_peeked = true;
peek_value = _streambuf->sbumpc();
return peek_value;
int_type next_value = _streambuf->sbumpc();
if ( !traits_type::eq_int_type(next_value,traits_type::eof()) )
{
setg(&oneChar, &oneChar, (&oneChar)+1);
oneChar = traits_type::to_char_type(next_value);
}
return next_value;
}
};

View File

@@ -210,6 +210,18 @@ class OSGA_Archive : public osgDB::Archive
std::string _masterFileName;
IndexBlockList _indexBlockList;
FileNamePositionMap _indexMap;
template <typename T>
static inline void _write(char* ptr, const T& value)
{
std::copy(reinterpret_cast<const char*>(&value),reinterpret_cast<const char*>(&value)+sizeof(value),ptr);
}
template <typename T>
static inline void _read(char* ptr, T& value)
{
std::copy(ptr,ptr+sizeof(value),reinterpret_cast<char*>(&value));
}
};